feat: migrate to starlight

This commit is contained in:
DuroCodes
2024-05-06 17:15:30 -04:00
parent 767acedea7
commit bb190f2d81
15140 changed files with 2828326 additions and 35408 deletions

201
node_modules/typedoc/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

90
node_modules/typedoc/README.md generated vendored Normal file
View File

@@ -0,0 +1,90 @@
# TypeDoc
Documentation generator for TypeScript projects.
[![CI](https://github.com/TypeStrong/typedoc/workflows/CI/badge.svg)](https://github.com/TypeStrong/typedoc/actions)
[![NPM Version](https://img.shields.io/npm/v/typedoc?color=33cd56&logo=npm)](https://www.npmjs.com/package/typedoc)
## Documentation
For more detailed documentation, the changelog, and TypeDoc documentation rendered with TypeDoc, see https://typedoc.org.
## Installation
TypeDoc runs on Node.js and is available as a NPM package.
```text
npm install typedoc --save-dev
```
## Usage
To generate documentation TypeDoc needs to know your project entry point and TypeScript
compiler options. It will automatically try to find your `tsconfig.json` file, so you can
just specify the entry point of your library:
```text
typedoc src/index.ts
```
If you have multiple entry points, specify each of them.
```text
typedoc package1/index.ts package2/index.ts
```
If you specify a directory, TypeDoc will use the `entryPointStrategy` option to determine how to resolve it.
By default, TypeDoc will search for a file called `index` under the directory.
### Monorepos / Workspaces
If your codebase is comprised of one or more npm packages, you can build documentation for each of them individually
and merge the results together into a single site by setting `entryPointStrategy` to `packages`. In this mode TypeDoc
requires configuration to be present in each directory to specify the entry points. For an example setup, see
https://github.com/Gerrit0/typedoc-packages-example
### Arguments
For a complete list of the command line arguments run `typedoc --help` or visit
[our website](https://typedoc.org/options/).
- `--out <path/to/documentation/>`<br>
Specifies the location the documentation should be written to. Defaults to `./docs`
- `--json <path/to/output.json>`<br>
Specifies the location and file name a json file describing the project is
written to. When specified no documentation will be generated unless `--out` is also
specified.
- `--options`<br>
Specify a json option file that should be loaded. If not specified TypeDoc
will look for 'typedoc.json' in the current directory.
- `--tsconfig <path/to/tsconfig.json>`<br>
Specify a typescript config file that should be loaded. If not
specified TypeDoc will look for 'tsconfig.json' in the current directory.
- `--exclude <pattern>`<br>
Exclude files by the given pattern when a path is provided as source.
Supports standard minimatch patterns.
#### Theming
- `--theme <default|plugin defined theme>`<br>
Specify the theme that should be used.
- `--name <Documentation title>`<br>
Set the name of the project that will be used in the header of the template.
- `--readme <path/to/readme|none>`<br>
Path to the readme file that should be displayed on the index page. Pass `none` to disable the index page
and start the documentation on the globals page.
#### Miscellaneous
- `--version`<br>
Display the version number of TypeDoc.
- `--help`<br>
Display all TypeDoc options.
## Contributing
This project is maintained by a community of developers. Contributions are welcome and appreciated.
You can find TypeDoc on GitHub; feel free to open an issue or create a pull request:
https://github.com/TypeStrong/typedoc
For more information, read the [contribution guide](https://github.com/TypeStrong/typedoc/blob/master/.github/CONTRIBUTING.md).

5
node_modules/typedoc/bin/typedoc generated vendored Executable file
View File

@@ -0,0 +1,5 @@
#!/usr/bin/env node
//@ts-check
/* eslint-disable @typescript-eslint/no-var-requires */
require("../dist/lib/cli");

28
node_modules/typedoc/dist/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,28 @@
export { Application } from "./lib/application";
export { EventDispatcher, Event } from "./lib/utils/events";
export { resetReflectionID } from "./lib/models/reflections/abstract";
/**
* All symbols documented under the Models namespace are also available in the root import.
*
* @categoryDescription Types
* Describes a TypeScript type.
*
* @categoryDescription Reflections
* Describes a documentation entry. The root entry is a {@link ProjectReflection}
* and contains {@link DeclarationReflection} instances.
*/
export * as Models from "./lib/models";
/**
* All symbols documented under the Configuration namespace are also available in the root import.
*/
export * as Configuration from "./lib/utils/options";
export * from "./lib/models";
export { Converter, Context, type CommentParserConfig, type DeclarationReference, type SymbolReference, type ComponentPath, type Meaning, type MeaningKeyword, type ExternalResolveResult, type ExternalSymbolResolver, } from "./lib/converter";
export { Renderer, DefaultTheme, DefaultThemeRenderContext, UrlMapping, Theme, PageEvent, RendererEvent, MarkdownEvent, IndexEvent, } from "./lib/output";
export type { RenderTemplate, RendererHooks, NavigationElement, } from "./lib/output";
export { ArgumentsReader, Option, BindOption, CommentStyle, JSX, LogLevel, Logger, Options, PackageJsonReader, ParameterHint, ParameterType, TSConfigReader, TypeDocReader, EntryPointStrategy, EventHooks, MinimalSourceFile, normalizePath, } from "./lib/utils";
export type { OptionsReader, TypeDocOptions, TypeDocOptionMap, ValidationOptions, TypeDocOptionValues, KeyToDeclaration, DeclarationOption, DeclarationOptionBase, StringDeclarationOption, NumberDeclarationOption, BooleanDeclarationOption, ArrayDeclarationOption, MixedDeclarationOption, ObjectDeclarationOption, MapDeclarationOption, FlagsDeclarationOption, DeclarationOptionToOptionType, SortStrategy, ParameterTypeToOptionTypeMap, DocumentationEntryPoint, ManuallyValidatedOption, EnumKeys, JsDocCompatibility, } from "./lib/utils";
export type { EventMap, EventCallback } from "./lib/utils/events";
export { JSONOutput, Serializer, Deserializer, type Deserializable, type DeserializerComponent, type SerializerComponent, SerializeEvent, } from "./lib/serialization";
import TypeScript from "typescript";
export { TypeScript };

93
node_modules/typedoc/dist/index.js generated vendored Normal file
View File

@@ -0,0 +1,93 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TypeScript = exports.SerializeEvent = exports.Deserializer = exports.Serializer = exports.JSONOutput = exports.normalizePath = exports.MinimalSourceFile = exports.EventHooks = exports.EntryPointStrategy = exports.TypeDocReader = exports.TSConfigReader = exports.ParameterType = exports.ParameterHint = exports.PackageJsonReader = exports.Options = exports.Logger = exports.LogLevel = exports.JSX = exports.CommentStyle = exports.BindOption = exports.Option = exports.ArgumentsReader = exports.IndexEvent = exports.MarkdownEvent = exports.RendererEvent = exports.PageEvent = exports.Theme = exports.UrlMapping = exports.DefaultThemeRenderContext = exports.DefaultTheme = exports.Renderer = exports.Context = exports.Converter = exports.Configuration = exports.Models = exports.resetReflectionID = exports.Event = exports.EventDispatcher = exports.Application = void 0;
var application_1 = require("./lib/application");
Object.defineProperty(exports, "Application", { enumerable: true, get: function () { return application_1.Application; } });
var events_1 = require("./lib/utils/events");
Object.defineProperty(exports, "EventDispatcher", { enumerable: true, get: function () { return events_1.EventDispatcher; } });
Object.defineProperty(exports, "Event", { enumerable: true, get: function () { return events_1.Event; } });
var abstract_1 = require("./lib/models/reflections/abstract");
Object.defineProperty(exports, "resetReflectionID", { enumerable: true, get: function () { return abstract_1.resetReflectionID; } });
/**
* All symbols documented under the Models namespace are also available in the root import.
*
* @categoryDescription Types
* Describes a TypeScript type.
*
* @categoryDescription Reflections
* Describes a documentation entry. The root entry is a {@link ProjectReflection}
* and contains {@link DeclarationReflection} instances.
*/
exports.Models = __importStar(require("./lib/models"));
/**
* All symbols documented under the Configuration namespace are also available in the root import.
*/
exports.Configuration = __importStar(require("./lib/utils/options"));
__exportStar(require("./lib/models"), exports);
var converter_1 = require("./lib/converter");
Object.defineProperty(exports, "Converter", { enumerable: true, get: function () { return converter_1.Converter; } });
Object.defineProperty(exports, "Context", { enumerable: true, get: function () { return converter_1.Context; } });
var output_1 = require("./lib/output");
Object.defineProperty(exports, "Renderer", { enumerable: true, get: function () { return output_1.Renderer; } });
Object.defineProperty(exports, "DefaultTheme", { enumerable: true, get: function () { return output_1.DefaultTheme; } });
Object.defineProperty(exports, "DefaultThemeRenderContext", { enumerable: true, get: function () { return output_1.DefaultThemeRenderContext; } });
Object.defineProperty(exports, "UrlMapping", { enumerable: true, get: function () { return output_1.UrlMapping; } });
Object.defineProperty(exports, "Theme", { enumerable: true, get: function () { return output_1.Theme; } });
Object.defineProperty(exports, "PageEvent", { enumerable: true, get: function () { return output_1.PageEvent; } });
Object.defineProperty(exports, "RendererEvent", { enumerable: true, get: function () { return output_1.RendererEvent; } });
Object.defineProperty(exports, "MarkdownEvent", { enumerable: true, get: function () { return output_1.MarkdownEvent; } });
Object.defineProperty(exports, "IndexEvent", { enumerable: true, get: function () { return output_1.IndexEvent; } });
var utils_1 = require("./lib/utils");
Object.defineProperty(exports, "ArgumentsReader", { enumerable: true, get: function () { return utils_1.ArgumentsReader; } });
Object.defineProperty(exports, "Option", { enumerable: true, get: function () { return utils_1.Option; } });
Object.defineProperty(exports, "BindOption", { enumerable: true, get: function () { return utils_1.BindOption; } });
Object.defineProperty(exports, "CommentStyle", { enumerable: true, get: function () { return utils_1.CommentStyle; } });
Object.defineProperty(exports, "JSX", { enumerable: true, get: function () { return utils_1.JSX; } });
Object.defineProperty(exports, "LogLevel", { enumerable: true, get: function () { return utils_1.LogLevel; } });
Object.defineProperty(exports, "Logger", { enumerable: true, get: function () { return utils_1.Logger; } });
Object.defineProperty(exports, "Options", { enumerable: true, get: function () { return utils_1.Options; } });
Object.defineProperty(exports, "PackageJsonReader", { enumerable: true, get: function () { return utils_1.PackageJsonReader; } });
Object.defineProperty(exports, "ParameterHint", { enumerable: true, get: function () { return utils_1.ParameterHint; } });
Object.defineProperty(exports, "ParameterType", { enumerable: true, get: function () { return utils_1.ParameterType; } });
Object.defineProperty(exports, "TSConfigReader", { enumerable: true, get: function () { return utils_1.TSConfigReader; } });
Object.defineProperty(exports, "TypeDocReader", { enumerable: true, get: function () { return utils_1.TypeDocReader; } });
Object.defineProperty(exports, "EntryPointStrategy", { enumerable: true, get: function () { return utils_1.EntryPointStrategy; } });
Object.defineProperty(exports, "EventHooks", { enumerable: true, get: function () { return utils_1.EventHooks; } });
Object.defineProperty(exports, "MinimalSourceFile", { enumerable: true, get: function () { return utils_1.MinimalSourceFile; } });
Object.defineProperty(exports, "normalizePath", { enumerable: true, get: function () { return utils_1.normalizePath; } });
var serialization_1 = require("./lib/serialization");
Object.defineProperty(exports, "JSONOutput", { enumerable: true, get: function () { return serialization_1.JSONOutput; } });
Object.defineProperty(exports, "Serializer", { enumerable: true, get: function () { return serialization_1.Serializer; } });
Object.defineProperty(exports, "Deserializer", { enumerable: true, get: function () { return serialization_1.Deserializer; } });
Object.defineProperty(exports, "SerializeEvent", { enumerable: true, get: function () { return serialization_1.SerializeEvent; } });
const typescript_1 = __importDefault(require("typescript"));
exports.TypeScript = typescript_1.default;

View File

@@ -0,0 +1,5 @@
export declare const ApplicationEvents: {
BOOTSTRAP_END: string;
REVIVE: string;
VALIDATE_PROJECT: string;
};

8
node_modules/typedoc/dist/lib/application-events.js generated vendored Normal file
View File

@@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ApplicationEvents = void 0;
exports.ApplicationEvents = {
BOOTSTRAP_END: "bootstrapEnd",
REVIVE: "reviveProject",
VALIDATE_PROJECT: "validateProject",
};

129
node_modules/typedoc/dist/lib/application.d.ts generated vendored Normal file
View File

@@ -0,0 +1,129 @@
import { Converter } from "./converter/index";
import { Renderer } from "./output/renderer";
import { Deserializer, Serializer } from "./serialization";
import type { ProjectReflection } from "./models/index";
import { Logger, OptionsReader } from "./utils/index";
import { AbstractComponent, ChildableComponent } from "./utils/component";
import { Options } from "./utils";
import type { TypeDocOptions } from "./utils/options/declaration";
import { DocumentationEntryPoint, EntryPointStrategy } from "./utils/entry-point";
export declare function createAppForTesting(): Application;
/**
* The default TypeDoc main application class.
*
* This class holds the two main components of TypeDoc, the {@link Converter} and
* the {@link Renderer}. When running TypeDoc, first the {@link Converter} is invoked which
* generates a {@link ProjectReflection} from the passed in source files. The
* {@link ProjectReflection} is a hierarchical model representation of the TypeScript
* project. Afterwards the model is passed to the {@link Renderer} which uses an instance
* of {@link Theme} to generate the final documentation.
*
* Both the {@link Converter} and the {@link Renderer} emit a series of events while processing the project.
* Subscribe to these Events to control the application flow or alter the output.
*/
export declare class Application extends ChildableComponent<Application, AbstractComponent<Application>> {
/**
* The converter used to create the declaration reflections.
*/
converter: Converter;
/**
* The renderer used to generate the documentation output.
*/
renderer: Renderer;
/**
* The serializer used to generate JSON output.
*/
serializer: Serializer;
/**
* The deserializer used to restore previously serialized JSON output.
*/
deserializer: Deserializer;
/**
* The logger that should be used to output messages.
*/
logger: Logger;
options: Options;
/** @internal */
accessor skipErrorChecking: boolean;
/** @internal */
accessor entryPointStrategy: EntryPointStrategy;
/** @internal */
accessor entryPoints: string[];
/**
* The version number of TypeDoc.
*/
static VERSION: string;
/**
* Emitted after plugins have been loaded and options have been read, but before they have been frozen.
* The listener will be given an instance of {@link Application}.
*/
static readonly EVENT_BOOTSTRAP_END: string;
/**
* Emitted after a project has been deserialized from JSON.
* The listener will be given an instance of {@link ProjectReflection}.
*/
static readonly EVENT_PROJECT_REVIVE: string;
/**
* Emitted when validation is being run.
* The listener will be given an instance of {@link ProjectReflection}.
*/
static readonly EVENT_VALIDATE_PROJECT: string;
/**
* Create a new TypeDoc application instance.
*/
private constructor();
/**
* Initialize TypeDoc, loading plugins if applicable.
*/
static bootstrapWithPlugins(options?: Partial<TypeDocOptions>, readers?: readonly OptionsReader[]): Promise<Application>;
/**
* Initialize TypeDoc without loading plugins.
*
* @example
* Initialize the application with pretty-printing output disabled.
* ```ts
* const app = Application.bootstrap({ pretty: false });
* ```
*
* @param options Options to set during initialization
* @param readers Option readers to use to discover options from config files.
*/
static bootstrap(options?: Partial<TypeDocOptions>, readers?: readonly OptionsReader[]): Promise<Application>;
private _bootstrap;
private setOptions;
/**
* Return the path to the TypeScript compiler.
*/
getTypeScriptPath(): string;
getTypeScriptVersion(): string;
/**
* Gets the entry points to be documented according to the current `entryPoints` and `entryPointStrategy` options.
* May return undefined if entry points fail to be expanded.
*/
getEntryPoints(): DocumentationEntryPoint[] | undefined;
/**
* Run the converter for the given set of files and return the generated reflections.
*
* @returns An instance of ProjectReflection on success, undefined otherwise.
*/
convert(): Promise<ProjectReflection | undefined>;
convertAndWatch(success: (project: ProjectReflection) => Promise<void>): void;
validate(project: ProjectReflection): void;
/**
* Render HTML for the given project
*/
generateDocs(project: ProjectReflection, out: string): Promise<void>;
/**
* Write the reflections to a json file.
*
* @param out The path and file name of the target file.
* @returns Whether the JSON file could be written successfully.
*/
generateJson(project: ProjectReflection, out: string): Promise<void>;
/**
* Print the version number.
*/
toString(): string;
private _convertPackages;
private _merge;
}

566
node_modules/typedoc/dist/lib/application.js generated vendored Normal file
View File

@@ -0,0 +1,566 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
var _, done = false;
for (var i = decorators.length - 1; i >= 0; i--) {
var context = {};
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
if (kind === "accessor") {
if (result === void 0) continue;
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
if (_ = accept(result.get)) descriptor.get = _;
if (_ = accept(result.set)) descriptor.set = _;
if (_ = accept(result.init)) initializers.unshift(_);
}
else if (_ = accept(result)) {
if (kind === "field") initializers.unshift(_);
else descriptor[key] = _;
}
}
if (target) Object.defineProperty(target, contextIn.name, descriptor);
done = true;
};
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
var useValue = arguments.length > 2;
for (var i = 0; i < initializers.length; i++) {
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
}
return useValue ? value : void 0;
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Application = exports.createAppForTesting = void 0;
const Path = __importStar(require("path"));
const typescript_1 = __importDefault(require("typescript"));
const index_1 = require("./converter/index");
const renderer_1 = require("./output/renderer");
const serialization_1 = require("./serialization");
const index_2 = require("./utils/index");
const component_1 = require("./utils/component");
const utils_1 = require("./utils");
const array_1 = require("./utils/array");
const assert_1 = require("assert");
const entry_point_1 = require("./utils/entry-point");
const paths_1 = require("./utils/paths");
const general_1 = require("./utils/general");
const exports_1 = require("./validation/exports");
const documentation_1 = require("./validation/documentation");
const links_1 = require("./validation/links");
const application_events_1 = require("./application-events");
const tsconfig_1 = require("./utils/tsconfig");
const fs_1 = require("./utils/fs");
const abstract_1 = require("./models/reflections/abstract");
const ReflectionSymbolId_1 = require("./models/reflections/ReflectionSymbolId");
// eslint-disable-next-line @typescript-eslint/no-var-requires
const packageInfo = require("../../package.json");
const supportedVersionMajorMinor = packageInfo.peerDependencies.typescript
.split("||")
.map((version) => version.replace(/^\s*|\.x\s*$/g, ""));
const DETECTOR = Symbol();
function createAppForTesting() {
// @ts-expect-error private constructor
return new Application(DETECTOR);
}
exports.createAppForTesting = createAppForTesting;
const DEFAULT_READERS = [
new index_2.TypeDocReader(),
new index_2.PackageJsonReader(),
new index_2.TSConfigReader(),
];
/**
* The default TypeDoc main application class.
*
* This class holds the two main components of TypeDoc, the {@link Converter} and
* the {@link Renderer}. When running TypeDoc, first the {@link Converter} is invoked which
* generates a {@link ProjectReflection} from the passed in source files. The
* {@link ProjectReflection} is a hierarchical model representation of the TypeScript
* project. Afterwards the model is passed to the {@link Renderer} which uses an instance
* of {@link Theme} to generate the final documentation.
*
* Both the {@link Converter} and the {@link Renderer} emit a series of events while processing the project.
* Subscribe to these Events to control the application flow or alter the output.
*/
let Application = (() => {
var _Application_skipErrorChecking_accessor_storage, _Application_entryPointStrategy_accessor_storage, _Application_entryPoints_accessor_storage;
let _classDecorators = [(0, component_1.Component)({ name: "application", internal: true })];
let _classDescriptor;
let _classExtraInitializers = [];
let _classThis;
let _classSuper = component_1.ChildableComponent;
let _skipErrorChecking_decorators;
let _skipErrorChecking_initializers = [];
let _skipErrorChecking_extraInitializers = [];
let _entryPointStrategy_decorators;
let _entryPointStrategy_initializers = [];
let _entryPointStrategy_extraInitializers = [];
let _entryPoints_decorators;
let _entryPoints_initializers = [];
let _entryPoints_extraInitializers = [];
var Application = _classThis = class extends _classSuper {
/** @internal */
get skipErrorChecking() { return __classPrivateFieldGet(this, _Application_skipErrorChecking_accessor_storage, "f"); }
set skipErrorChecking(value) { __classPrivateFieldSet(this, _Application_skipErrorChecking_accessor_storage, value, "f"); }
/** @internal */
get entryPointStrategy() { return __classPrivateFieldGet(this, _Application_entryPointStrategy_accessor_storage, "f"); }
set entryPointStrategy(value) { __classPrivateFieldSet(this, _Application_entryPointStrategy_accessor_storage, value, "f"); }
/** @internal */
get entryPoints() { return __classPrivateFieldGet(this, _Application_entryPoints_accessor_storage, "f"); }
set entryPoints(value) { __classPrivateFieldSet(this, _Application_entryPoints_accessor_storage, value, "f"); }
/**
* Create a new TypeDoc application instance.
*/
constructor(detector) {
if (detector !== DETECTOR) {
throw new Error("An application handle must be retrieved with Application.bootstrap or Application.bootstrapWithPlugins");
}
super(null); // We own ourselves
/**
* The serializer used to generate JSON output.
*/
this.serializer = new serialization_1.Serializer();
/**
* The deserializer used to restore previously serialized JSON output.
*/
this.deserializer = new serialization_1.Deserializer(this);
/**
* The logger that should be used to output messages.
*/
this.logger = new index_2.ConsoleLogger();
this.options = new utils_1.Options();
_Application_skipErrorChecking_accessor_storage.set(this, __runInitializers(this, _skipErrorChecking_initializers, void 0));
_Application_entryPointStrategy_accessor_storage.set(this, (__runInitializers(this, _skipErrorChecking_extraInitializers), __runInitializers(this, _entryPointStrategy_initializers, void 0)));
_Application_entryPoints_accessor_storage.set(this, (__runInitializers(this, _entryPointStrategy_extraInitializers), __runInitializers(this, _entryPoints_initializers, void 0)));
__runInitializers(this, _entryPoints_extraInitializers);
this.converter = this.addComponent("converter", index_1.Converter);
this.renderer = this.addComponent("renderer", renderer_1.Renderer);
}
/**
* Initialize TypeDoc, loading plugins if applicable.
*/
static async bootstrapWithPlugins(options = {}, readers = DEFAULT_READERS) {
const app = new Application(DETECTOR);
readers.forEach((r) => app.options.addReader(r));
app.options.reset();
app.setOptions(options, /* reportErrors */ false);
await app.options.read(new index_2.Logger());
app.logger.level = app.options.getValue("logLevel");
await (0, index_2.loadPlugins)(app, app.options.getValue("plugin"));
await app._bootstrap(options);
return app;
}
/**
* Initialize TypeDoc without loading plugins.
*
* @example
* Initialize the application with pretty-printing output disabled.
* ```ts
* const app = Application.bootstrap({ pretty: false });
* ```
*
* @param options Options to set during initialization
* @param readers Option readers to use to discover options from config files.
*/
static async bootstrap(options = {}, readers = DEFAULT_READERS) {
const app = new Application(DETECTOR);
readers.forEach((r) => app.options.addReader(r));
await app._bootstrap(options);
return app;
}
async _bootstrap(options) {
this.options.reset();
this.setOptions(options, /* reportErrors */ false);
await this.options.read(this.logger);
this.setOptions(options);
this.logger.level = this.options.getValue("logLevel");
if ((0, general_1.hasBeenLoadedMultipleTimes)()) {
this.logger.warn(`TypeDoc has been loaded multiple times. This is commonly caused by plugins which have their own installation of TypeDoc. The loaded paths are:\n\t${(0, general_1.getLoadedPaths)().join("\n\t")}`);
}
this.trigger(application_events_1.ApplicationEvents.BOOTSTRAP_END, this);
}
setOptions(options, reportErrors = true) {
for (const [key, val] of Object.entries(options)) {
try {
this.options.setValue(key, val);
}
catch (error) {
(0, assert_1.ok)(error instanceof Error);
if (reportErrors) {
this.logger.error(error.message);
}
}
}
}
/**
* Return the path to the TypeScript compiler.
*/
getTypeScriptPath() {
return (0, paths_1.nicePath)(Path.dirname(require.resolve("typescript")));
}
getTypeScriptVersion() {
return typescript_1.default.version;
}
/**
* Gets the entry points to be documented according to the current `entryPoints` and `entryPointStrategy` options.
* May return undefined if entry points fail to be expanded.
*/
getEntryPoints() {
return (0, entry_point_1.getEntryPoints)(this.logger, this.options);
}
/**
* Run the converter for the given set of files and return the generated reflections.
*
* @returns An instance of ProjectReflection on success, undefined otherwise.
*/
async convert() {
const start = Date.now();
// We freeze here rather than in the Converter class since TypeDoc's tests reuse the Application
// with a few different settings.
this.options.freeze();
this.logger.verbose(`Using TypeScript ${this.getTypeScriptVersion()} from ${this.getTypeScriptPath()}`);
if (this.entryPointStrategy === entry_point_1.EntryPointStrategy.Merge) {
return this._merge();
}
if (this.entryPointStrategy === entry_point_1.EntryPointStrategy.Packages) {
return this._convertPackages();
}
if (!supportedVersionMajorMinor.some((version) => version == typescript_1.default.versionMajorMinor)) {
this.logger.warn(`You are running with an unsupported TypeScript version! If TypeDoc crashes, this is why. TypeDoc supports ${supportedVersionMajorMinor.join(", ")}`);
}
const entryPoints = this.getEntryPoints();
if (!entryPoints) {
// Fatal error already reported.
return;
}
const programs = (0, array_1.unique)(entryPoints.map((e) => e.program));
this.logger.verbose(`Converting with ${programs.length} programs ${entryPoints.length} entry points`);
if (this.skipErrorChecking === false) {
const errors = programs.flatMap((program) => typescript_1.default.getPreEmitDiagnostics(program));
if (errors.length) {
this.logger.diagnostics(errors);
return;
}
}
if (this.options.getValue("emit") === "both") {
for (const program of programs) {
program.emit();
}
}
const startConversion = Date.now();
this.logger.verbose(`Finished getting entry points in ${Date.now() - start}ms`);
const project = this.converter.convert(entryPoints);
this.logger.verbose(`Finished conversion in ${Date.now() - startConversion}ms`);
return project;
}
convertAndWatch(success) {
this.options.freeze();
if (!this.options.getValue("preserveWatchOutput") &&
this.logger instanceof index_2.ConsoleLogger) {
typescript_1.default.sys.clearScreen?.();
}
this.logger.verbose(`Using TypeScript ${this.getTypeScriptVersion()} from ${this.getTypeScriptPath()}`);
if (!supportedVersionMajorMinor.some((version) => version == typescript_1.default.versionMajorMinor)) {
this.logger.warn(`You are running with an unsupported TypeScript version! TypeDoc supports ${supportedVersionMajorMinor.join(", ")}`);
}
if (Object.keys(this.options.getCompilerOptions()).length === 0) {
this.logger.warn(`No compiler options set. This likely means that TypeDoc did not find your tsconfig.json. Generated documentation will probably be empty.`);
}
// Doing this is considerably more complicated, we'd need to manage an array of programs, not convert until all programs
// have reported in the first time... just error out for now. I'm not convinced anyone will actually notice.
if (this.options.getFileNames().length === 0) {
this.logger.error("The provided tsconfig file looks like a solution style tsconfig, which is not supported in watch mode.");
return;
}
// Support for packages mode is currently unimplemented
if (this.entryPointStrategy !== entry_point_1.EntryPointStrategy.Resolve &&
this.entryPointStrategy !== entry_point_1.EntryPointStrategy.Expand) {
this.logger.error("entryPointStrategy must be set to either resolve or expand for watch mode.");
return;
}
const tsconfigFile = (0, tsconfig_1.findTsConfigFile)(this.options.getValue("tsconfig")) ??
"tsconfig.json";
// We don't want to do it the first time to preserve initial debug status messages. They'll be lost
// after the user saves a file, but better than nothing...
let firstStatusReport = true;
const host = typescript_1.default.createWatchCompilerHost(tsconfigFile, {}, typescript_1.default.sys, typescript_1.default.createEmitAndSemanticDiagnosticsBuilderProgram, (diagnostic) => this.logger.diagnostic(diagnostic), (status, newLine, _options, errorCount) => {
if (!firstStatusReport &&
errorCount === void 0 &&
!this.options.getValue("preserveWatchOutput") &&
this.logger instanceof index_2.ConsoleLogger) {
typescript_1.default.sys.clearScreen?.();
}
firstStatusReport = false;
this.logger.info(typescript_1.default.flattenDiagnosticMessageText(status.messageText, newLine));
});
let successFinished = true;
let currentProgram;
const runSuccess = () => {
if (!currentProgram) {
return;
}
if (successFinished) {
if (this.options.getValue("emit") === "both") {
currentProgram.emit();
}
this.logger.resetErrors();
this.logger.resetWarnings();
const entryPoints = (0, entry_point_1.getWatchEntryPoints)(this.logger, this.options, currentProgram);
if (!entryPoints) {
return;
}
const project = this.converter.convert(entryPoints);
currentProgram = undefined;
successFinished = false;
void success(project).then(() => {
successFinished = true;
runSuccess();
});
}
};
const origCreateProgram = host.createProgram;
host.createProgram = (rootNames, options, host, oldProgram, configDiagnostics, references) => {
// If we always do this, we'll get a crash the second time a program is created.
if (rootNames !== undefined) {
options = this.options.fixCompilerOptions(options || {});
}
return origCreateProgram(rootNames, options, host, oldProgram, configDiagnostics, references);
};
const origAfterProgramCreate = host.afterProgramCreate;
host.afterProgramCreate = (program) => {
if (typescript_1.default.getPreEmitDiagnostics(program.getProgram()).length === 0) {
currentProgram = program.getProgram();
runSuccess();
}
origAfterProgramCreate?.(program);
};
typescript_1.default.createWatchProgram(host);
}
validate(project) {
const checks = this.options.getValue("validation");
const start = Date.now();
// No point in validating exports when merging. Warnings will have already been emitted when
// creating the project jsons that this run merges together.
if (checks.notExported &&
this.entryPointStrategy !== entry_point_1.EntryPointStrategy.Merge) {
(0, exports_1.validateExports)(project, this.logger, this.options.getValue("intentionallyNotExported"));
}
if (checks.notDocumented) {
(0, documentation_1.validateDocumentation)(project, this.logger, this.options.getValue("requiredToBeDocumented"));
}
if (checks.invalidLink) {
(0, links_1.validateLinks)(project, this.logger);
}
this.trigger(Application.EVENT_VALIDATE_PROJECT, project);
this.logger.verbose(`Validation took ${Date.now() - start}ms`);
}
/**
* Render HTML for the given project
*/
async generateDocs(project, out) {
const start = Date.now();
out = Path.resolve(out);
await this.renderer.render(project, out);
if (this.logger.hasErrors()) {
this.logger.error("Documentation could not be generated due to the errors above.");
}
else {
this.logger.info(`Documentation generated at ${(0, paths_1.nicePath)(out)}`);
this.logger.verbose(`HTML rendering took ${Date.now() - start}ms`);
}
}
/**
* Write the reflections to a json file.
*
* @param out The path and file name of the target file.
* @returns Whether the JSON file could be written successfully.
*/
async generateJson(project, out) {
const start = Date.now();
out = Path.resolve(out);
const ser = this.serializer.projectToObject(project, process.cwd());
const space = this.options.getValue("pretty") ? "\t" : "";
await (0, index_2.writeFile)(out, JSON.stringify(ser, null, space));
this.logger.info(`JSON written to ${(0, paths_1.nicePath)(out)}`);
this.logger.verbose(`JSON rendering took ${Date.now() - start}ms`);
}
/**
* Print the version number.
*/
toString() {
return [
"",
`TypeDoc ${Application.VERSION}`,
`Using TypeScript ${this.getTypeScriptVersion()} from ${this.getTypeScriptPath()}`,
"",
].join("\n");
}
async _convertPackages() {
if (!this.options.isSet("entryPoints")) {
this.logger.error("No entry points provided to packages mode, documentation cannot be generated.");
return;
}
const packageDirs = (0, entry_point_1.getPackageDirectories)(this.logger, this.options, this.options.getValue("entryPoints"));
if (packageDirs.length === 0) {
this.logger.error("Failed to find any packages, ensure you have provided at least one directory as an entry point containing package.json");
return;
}
const origOptions = this.options;
const projects = [];
const projectsToConvert = [];
// Generate a json file for each package
for (const dir of packageDirs) {
this.logger.verbose(`Reading project at ${(0, paths_1.nicePath)(dir)}`);
const opts = origOptions.copyForPackage(dir);
await opts.read(this.logger, dir);
// Invalid links should only be reported after everything has been merged.
opts.setValue("validation", { invalidLink: false });
if (opts.getValue("entryPointStrategy") ===
entry_point_1.EntryPointStrategy.Packages) {
this.logger.error(`Project at ${(0, paths_1.nicePath)(dir)} has entryPointStrategy set to packages, but nested packages are not supported.`);
continue;
}
(0, ReflectionSymbolId_1.addInferredDeclarationMapPaths)(opts.getCompilerOptions(), opts.getFileNames());
projectsToConvert.push({ dir, options: opts });
}
for (const { dir, options } of projectsToConvert) {
this.logger.info(`Converting project at ${(0, paths_1.nicePath)(dir)}`);
this.options = options;
const project = await this.convert();
if (project) {
this.validate(project);
projects.push(this.serializer.projectToObject(project, process.cwd()));
}
(0, abstract_1.resetReflectionID)();
}
this.options = origOptions;
this.logger.info(`Merging converted projects`);
if (projects.length !== packageDirs.length) {
this.logger.error("Failed to convert one or more packages, result will not be merged together.");
return;
}
const result = this.deserializer.reviveProjects(this.options.getValue("name") || "Documentation", projects);
this.trigger(application_events_1.ApplicationEvents.REVIVE, result);
return result;
}
_merge() {
const start = Date.now();
if (!this.options.isSet("entryPoints")) {
this.logger.error("No entry points provided to merge.");
return;
}
const rootDir = (0, fs_1.deriveRootDir)(this.entryPoints);
const entryPoints = this.entryPoints.flatMap((entry) => {
const result = (0, fs_1.glob)(entry, rootDir);
if (result.length === 0) {
this.logger.warn(`The entrypoint glob ${(0, paths_1.nicePath)(entry)} did not match any files.`);
}
else {
this.logger.verbose(`Expanded ${(0, paths_1.nicePath)(entry)} to:\n\t${result
.map(paths_1.nicePath)
.join("\n\t")}`);
}
return result;
});
const jsonProjects = entryPoints.map((path) => {
try {
return JSON.parse((0, fs_1.readFile)(path));
}
catch {
this.logger.error(`Failed to parse file at ${(0, paths_1.nicePath)(path)} as json.`);
return null;
}
});
if (this.logger.hasErrors())
return;
const result = this.deserializer.reviveProjects(this.options.getValue("name"), jsonProjects);
this.logger.verbose(`Reviving projects took ${Date.now() - start}ms`);
this.trigger(application_events_1.ApplicationEvents.REVIVE, result);
return result;
}
};
_Application_skipErrorChecking_accessor_storage = new WeakMap();
_Application_entryPointStrategy_accessor_storage = new WeakMap();
_Application_entryPoints_accessor_storage = new WeakMap();
__setFunctionName(_classThis, "Application");
(() => {
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
_skipErrorChecking_decorators = [(0, utils_1.Option)("skipErrorChecking")];
_entryPointStrategy_decorators = [(0, utils_1.Option)("entryPointStrategy")];
_entryPoints_decorators = [(0, utils_1.Option)("entryPoints")];
__esDecorate(_classThis, null, _skipErrorChecking_decorators, { kind: "accessor", name: "skipErrorChecking", static: false, private: false, access: { has: obj => "skipErrorChecking" in obj, get: obj => obj.skipErrorChecking, set: (obj, value) => { obj.skipErrorChecking = value; } }, metadata: _metadata }, _skipErrorChecking_initializers, _skipErrorChecking_extraInitializers);
__esDecorate(_classThis, null, _entryPointStrategy_decorators, { kind: "accessor", name: "entryPointStrategy", static: false, private: false, access: { has: obj => "entryPointStrategy" in obj, get: obj => obj.entryPointStrategy, set: (obj, value) => { obj.entryPointStrategy = value; } }, metadata: _metadata }, _entryPointStrategy_initializers, _entryPointStrategy_extraInitializers);
__esDecorate(_classThis, null, _entryPoints_decorators, { kind: "accessor", name: "entryPoints", static: false, private: false, access: { has: obj => "entryPoints" in obj, get: obj => obj.entryPoints, set: (obj, value) => { obj.entryPoints = value; } }, metadata: _metadata }, _entryPoints_initializers, _entryPoints_extraInitializers);
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
Application = _classThis = _classDescriptor.value;
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
})();
/**
* The version number of TypeDoc.
*/
_classThis.VERSION = packageInfo.version;
/**
* Emitted after plugins have been loaded and options have been read, but before they have been frozen.
* The listener will be given an instance of {@link Application}.
*/
_classThis.EVENT_BOOTSTRAP_END = application_events_1.ApplicationEvents.BOOTSTRAP_END;
/**
* Emitted after a project has been deserialized from JSON.
* The listener will be given an instance of {@link ProjectReflection}.
*/
_classThis.EVENT_PROJECT_REVIVE = application_events_1.ApplicationEvents.REVIVE;
/**
* Emitted when validation is being run.
* The listener will be given an instance of {@link ProjectReflection}.
*/
_classThis.EVENT_VALIDATE_PROJECT = application_events_1.ApplicationEvents.VALIDATE_PROJECT;
(() => {
__runInitializers(_classThis, _classExtraInitializers);
})();
return Application = _classThis;
})();
exports.Application = Application;

1
node_modules/typedoc/dist/lib/cli.d.ts generated vendored Normal file
View File

@@ -0,0 +1 @@
export {};

132
node_modules/typedoc/dist/lib/cli.js generated vendored Normal file
View File

@@ -0,0 +1,132 @@
"use strict";
/* eslint-disable no-console */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const ExitCodes = {
Ok: 0,
OptionError: 1,
CompileError: 3,
ValidationError: 4,
OutputError: 5,
ExceptionThrown: 6,
Watching: 7,
};
const td = __importStar(require("typedoc"));
void main();
async function main() {
let app;
try {
const start = Date.now();
app = await td.Application.bootstrapWithPlugins({}, [
new td.ArgumentsReader(0),
new td.TypeDocReader(),
new td.PackageJsonReader(),
new td.TSConfigReader(),
new td.ArgumentsReader(300),
]);
const exitCode = await run(app);
if (exitCode !== ExitCodes.Watching) {
app.logger.verbose(`Full run took ${Date.now() - start}ms`);
process.exit(exitCode);
}
}
catch (error) {
console.error("TypeDoc exiting with unexpected error:");
console.error(error);
if (app?.options.getValue("skipErrorChecking")) {
console.error("Try turning off --skipErrorChecking. If TypeDoc still crashes, please report a bug.");
}
process.exit(ExitCodes.ExceptionThrown);
}
}
async function run(app) {
if (app.options.getValue("version")) {
console.log(app.toString());
return ExitCodes.Ok;
}
if (app.options.getValue("help")) {
console.log(app.options.getHelp());
return ExitCodes.Ok;
}
if (app.options.getValue("showConfig")) {
console.log(app.options.getRawValues());
return ExitCodes.Ok;
}
if (app.logger.hasErrors()) {
return ExitCodes.OptionError;
}
if (app.options.getValue("treatWarningsAsErrors") &&
app.logger.hasWarnings()) {
return ExitCodes.OptionError;
}
if (app.options.getValue("watch")) {
app.convertAndWatch(async (project) => {
const json = app.options.getValue("json");
if (!json || app.options.isSet("out")) {
await app.generateDocs(project, app.options.getValue("out"));
}
if (json) {
await app.generateJson(project, json);
}
});
return ExitCodes.Watching;
}
const project = await app.convert();
if (!project) {
return ExitCodes.CompileError;
}
if (app.options.getValue("treatWarningsAsErrors") &&
app.logger.hasWarnings()) {
return ExitCodes.CompileError;
}
const preValidationWarnCount = app.logger.warningCount;
app.validate(project);
const hadValidationWarnings = app.logger.warningCount !== preValidationWarnCount;
if (app.logger.hasErrors()) {
return ExitCodes.ValidationError;
}
if (hadValidationWarnings &&
(app.options.getValue("treatWarningsAsErrors") ||
app.options.getValue("treatValidationWarningsAsErrors"))) {
return ExitCodes.ValidationError;
}
if (app.options.getValue("emit") !== "none") {
const json = app.options.getValue("json");
if (!json || app.options.isSet("out")) {
await app.generateDocs(project, app.options.getValue("out"));
}
if (json) {
await app.generateJson(project, json);
}
if (app.logger.hasErrors()) {
return ExitCodes.OutputError;
}
if (app.options.getValue("treatWarningsAsErrors") &&
app.logger.hasWarnings()) {
return ExitCodes.OutputError;
}
}
return ExitCodes.Ok;
}

View File

@@ -0,0 +1,3 @@
import ts from "typescript";
import { Token } from "./lexer";
export declare function lexBlockComment(file: string, pos?: number, end?: number, jsDoc?: ts.JSDoc | undefined, checker?: ts.TypeChecker | undefined): Generator<Token, undefined, undefined>;

View File

@@ -0,0 +1,379 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.lexBlockComment = void 0;
const typescript_1 = __importDefault(require("typescript"));
const lexer_1 = require("./lexer");
const ReflectionSymbolId_1 = require("../../models/reflections/ReflectionSymbolId");
const symbols_1 = require("../utils/symbols");
function* lexBlockComment(file, pos = 0, end = file.length, jsDoc = undefined, checker = undefined) {
// Wrapper around our real lex function to collapse adjacent text tokens.
let textToken;
for (const token of lexBlockComment2(file, pos, end, getLinkTags(jsDoc), checker)) {
if (token.kind === lexer_1.TokenSyntaxKind.Text) {
if (textToken) {
textToken.text += token.text;
}
else {
textToken = token;
}
}
else {
if (textToken) {
yield textToken;
textToken = void 0;
}
yield token;
}
}
if (textToken) {
yield textToken;
}
return;
}
exports.lexBlockComment = lexBlockComment;
function getLinkTags(jsDoc) {
const result = [];
if (jsDoc?.comment && typeof jsDoc.comment !== "string") {
for (const part of jsDoc.comment) {
switch (part.kind) {
case typescript_1.default.SyntaxKind.JSDocLink:
case typescript_1.default.SyntaxKind.JSDocLinkCode:
case typescript_1.default.SyntaxKind.JSDocLinkPlain:
result.push(part);
}
}
}
for (const block of jsDoc?.tags || []) {
if (!block.comment || typeof block.comment === "string")
continue;
for (const part of block.comment) {
switch (part.kind) {
case typescript_1.default.SyntaxKind.JSDocLink:
case typescript_1.default.SyntaxKind.JSDocLinkCode:
case typescript_1.default.SyntaxKind.JSDocLinkPlain:
result.push(part);
}
}
}
return result;
}
function* lexBlockComment2(file, pos, end, linkTags, checker) {
pos += 2; // Leading '/*'
end -= 2; // Trailing '*/'
if (pos < end && file[pos] === "*") {
// Might start with '/**'
pos++;
}
// Before skipping whitespace, figure out the comment indent size
const [commentHasStars, indent] = discoverIndent(file, pos, end);
// Skip leading whitespace
while (pos < end && /\s/.test(file[pos])) {
pos++;
}
// Trailing whitespace
while (pos < end && /\s/.test(file[end - 1])) {
end--;
}
let lineStart = true;
let braceStartsType = false;
let linkTagIndex = 0;
for (;;) {
if (pos >= end) {
return;
}
if (lineStart) {
pos = skipIndent(pos);
if (commentHasStars && file[pos] === "*") {
pos++;
if (file[pos] === " ") {
pos++;
}
}
lineStart = false;
}
switch (file[pos]) {
case "\n":
yield makeToken(lexer_1.TokenSyntaxKind.NewLine, 1);
lineStart = true;
break;
case "{":
if (braceStartsType && nextNonWs(pos + 1) !== "@") {
yield makeToken(lexer_1.TokenSyntaxKind.TypeAnnotation, findEndOfType(pos) - pos);
braceStartsType = false;
}
else {
yield makeToken(lexer_1.TokenSyntaxKind.OpenBrace, 1);
}
break;
case "}":
yield makeToken(lexer_1.TokenSyntaxKind.CloseBrace, 1);
braceStartsType = false;
break;
case "`": {
// Markdown's code rules are a royal pain. This could be one of several things.
// 1. Inline code: <1-n ticks><text><same number of ticks>
// 2. Code block: <3 ticks><language, no ticks>\n<text>\n<3 ticks>\n
// 3. Unmatched tick(s), not code, but part of some text.
// We don't quite handle #2 correctly yet. PR welcome!
braceStartsType = false;
let tickCount = 1;
let lookahead = pos;
while (lookahead + 1 < end && file[lookahead + 1] === "`") {
tickCount++;
lookahead++;
}
let lookaheadStart = pos;
const codeText = [];
lookahead++;
while (lookahead < end) {
if (lookaheadExactlyNTicks(lookahead, tickCount)) {
lookahead += tickCount;
codeText.push(file.substring(lookaheadStart, lookahead));
yield {
kind: lexer_1.TokenSyntaxKind.Code,
text: codeText.join(""),
pos,
};
pos = lookahead;
break;
}
else if (file[lookahead] === "`") {
while (lookahead < end && file[lookahead] === "`") {
lookahead++;
}
}
else if (file[lookahead] === "\\" &&
lookahead + 1 < end &&
file[lookahead + 1] === "/") {
codeText.push(file.substring(lookaheadStart, lookahead));
lookaheadStart = lookahead + 1;
lookahead += 2;
}
else if (file[lookahead] === "\\" &&
lookahead + 1 < end &&
file[lookahead + 1] !== "\n") {
lookahead += 2;
}
else if (file[lookahead] === "\n") {
lookahead++;
codeText.push(file.substring(lookaheadStart, lookahead));
lookahead = skipIndent(lookahead);
if (commentHasStars && file[lookahead] === "*") {
lookahead++;
if (file[lookahead] === " ") {
lookahead++;
}
}
lookaheadStart = lookahead;
}
else {
lookahead++;
}
}
if (lookahead >= end && pos !== lookahead) {
if (tickCount === 3 &&
file.substring(pos, end).includes("\n")) {
codeText.push(file.substring(lookaheadStart, end));
yield {
kind: lexer_1.TokenSyntaxKind.Code,
text: codeText.join(""),
pos,
};
pos = lookahead;
}
else {
yield makeToken(lexer_1.TokenSyntaxKind.Text, tickCount);
}
}
break;
}
case "@": {
let lookahead = pos + 1;
while (lookahead < end && /[a-z]/i.test(file[lookahead])) {
lookahead++;
}
if (lookahead !== pos + 1) {
while (lookahead < end &&
/[a-z0-9]/i.test(file[lookahead])) {
lookahead++;
}
}
if (lookahead !== pos + 1 &&
(lookahead === end || /[\s}]/.test(file[lookahead]))) {
braceStartsType = true;
const token = makeToken(lexer_1.TokenSyntaxKind.Tag, lookahead - pos);
attachLinkTagResult(token);
yield token;
break;
}
}
// fall through if we didn't find something that looks like a tag
default: {
const textParts = [];
let lookaheadStart = pos;
let lookahead = pos;
while (lookahead < end) {
if ("{}\n`".includes(file[lookahead]))
break;
if (lookahead !== pos &&
file[lookahead] === "@" &&
/\s/.test(file[lookahead - 1])) {
// Probably the start of a modifier tag
break;
}
if (file[lookahead] === "\\" &&
lookahead + 1 < end &&
"{}@/`".includes(file[lookahead + 1])) {
textParts.push(file.substring(lookaheadStart, lookahead), file[lookahead + 1]);
lookahead++;
lookaheadStart = lookahead + 1;
}
lookahead++;
}
textParts.push(file.substring(lookaheadStart, lookahead));
if (textParts.some((part) => /\S/.test(part))) {
braceStartsType = false;
}
// This piece of text had line continuations or escaped text
yield {
kind: lexer_1.TokenSyntaxKind.Text,
text: textParts.join(""),
pos,
};
pos = lookahead;
break;
}
}
}
function attachLinkTagResult(token) {
// We might need to skip link tags if someone has link tags inside of an example comment
// pos-1 for opening brace, TS doesn't allow spaces between opening brace and @ sign as of 5.0.2
while (linkTagIndex < linkTags.length &&
linkTags[linkTagIndex].pos < token.pos - 1) {
linkTagIndex++;
}
if (linkTagIndex < linkTags.length &&
linkTags[linkTagIndex].pos === token.pos - 1) {
const link = linkTags[linkTagIndex];
if (link.name) {
const tsTarget = checker?.getSymbolAtLocation(getRightmostName(link.name));
if (tsTarget) {
token.tsLinkTarget = new ReflectionSymbolId_1.ReflectionSymbolId((0, symbols_1.resolveAliasedSymbol)(tsTarget, checker));
token.tsLinkText = link.text.replace(/^\s*\|\s*/, "");
}
}
}
}
function makeToken(kind, size) {
const start = pos;
pos += size;
return {
kind,
text: file.substring(start, pos),
pos: start,
};
}
function skipIndent(pos) {
let taken = indent;
let lookahead = pos;
while (taken > 0 &&
lookahead < end &&
file[lookahead] !== "\n" &&
/\s/.test(file[lookahead])) {
taken--;
lookahead++;
}
return lookahead;
}
function lookaheadExactlyNTicks(pos, n) {
if (pos + n > end) {
return false;
}
return file.startsWith("`".repeat(n), pos) && file[pos + n] !== "`";
}
function findEndOfType(pos) {
let openBraces = 0;
while (pos < end) {
if (file[pos] === "{") {
openBraces++;
}
else if (file[pos] === "}") {
if (--openBraces === 0) {
break;
}
}
else if ("`'\"".includes(file[pos])) {
pos = findEndOfString(pos);
}
pos++;
}
if (pos < end && file[pos] === "}") {
pos++;
}
return pos;
}
function findEndOfString(pos) {
const endOfString = file[pos];
pos++;
while (pos < end) {
if (file[pos] === endOfString) {
break;
}
else if (file[pos] === "\\") {
pos++; // Skip escaped character
}
else if (endOfString === "`" &&
file[pos] === "$" &&
file[pos + 1] === "{") {
// Template literal with data inside a ${}
while (pos < end && file[pos] !== "}") {
if ("`'\"".includes(file[pos])) {
pos = findEndOfString(pos) + 1;
}
else {
pos++;
}
}
}
pos++;
}
return pos;
}
function nextNonWs(pos) {
while (pos < end && /\s/.test(file[pos])) {
pos++;
}
return file[pos];
}
}
function discoverIndent(file, pos, end) {
let indent = 0;
while (pos < end && file[pos] !== "\n") {
pos++;
}
outer: while (pos < end) {
pos++;
const lineStart = pos;
while (pos < end && file[pos] !== "\n") {
if (/\S/.test(file[pos])) {
indent = pos - lineStart;
break outer;
}
pos++;
}
}
const commentHasStars = pos < end && file[pos] === "*";
return [commentHasStars, indent];
}
function getRightmostName(name) {
if (typescript_1.default.isJSDocMemberName(name)) {
return name.right;
}
if (typescript_1.default.isQualifiedName(name)) {
return name.right;
}
return name;
}

View File

@@ -0,0 +1,40 @@
/**
* Parser for declaration references, see the [TSDoc grammar](https://github.com/microsoft/tsdoc/blob/main/tsdoc/src/beta/DeclarationReference.grammarkdown)
* for reference. TypeDoc **does not** support the full grammar today. This is intentional, since the TSDoc
* specified grammar allows the user to construct nonsensical declaration references such as `abc![def!ghi]`
*
* @module
*/
export declare const MeaningKeywords: readonly ["class", "interface", "type", "enum", "namespace", "function", "var", "constructor", "member", "event", "call", "new", "index", "complex", "getter", "setter"];
export type MeaningKeyword = (typeof MeaningKeywords)[number];
export interface DeclarationReference {
resolutionStart: "global" | "local";
moduleSource?: string;
symbolReference?: SymbolReference;
}
export interface Meaning {
keyword?: MeaningKeyword;
label?: string;
index?: number;
}
export interface SymbolReference {
path?: ComponentPath[];
meaning?: Meaning;
}
export interface ComponentPath {
/**
* How to resolve the `path`
* - `.` - Navigate via `exports` of symbol
* - `#` - Navigate via `members` of symbol
* - `~` - Navigate via `locals` of symbol
*/
navigation: "." | "#" | "~";
path: string;
}
export declare function parseString(source: string, pos: number, end: number): [string, number] | undefined;
export declare function parseModuleSource(source: string, pos: number, end: number): [string, number] | undefined;
export declare function parseSymbolReference(source: string, pos: number, end: number): [SymbolReference, number] | undefined;
export declare function parseComponent(source: string, pos: number, end: number): [string, number] | undefined;
export declare function parseComponentPath(source: string, pos: number, end: number): readonly [ComponentPath[], number] | undefined;
export declare function parseMeaning(source: string, pos: number, end: number): [Meaning, number] | undefined;
export declare function parseDeclarationReference(source: string, pos: number, end: number): [DeclarationReference, number] | undefined;

View File

@@ -0,0 +1,329 @@
"use strict";
/**
* Parser for declaration references, see the [TSDoc grammar](https://github.com/microsoft/tsdoc/blob/main/tsdoc/src/beta/DeclarationReference.grammarkdown)
* for reference. TypeDoc **does not** support the full grammar today. This is intentional, since the TSDoc
* specified grammar allows the user to construct nonsensical declaration references such as `abc![def!ghi]`
*
* @module
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseDeclarationReference = exports.parseMeaning = exports.parseComponentPath = exports.parseComponent = exports.parseSymbolReference = exports.parseModuleSource = exports.parseString = exports.MeaningKeywords = void 0;
exports.MeaningKeywords = [
"class", // SymbolFlags.Class
"interface", // SymbolFlags.Interface
"type", // SymbolFlags.TypeAlias
"enum", // SymbolFlags.Enum
"namespace", // SymbolFlags.Module
"function", // SymbolFlags.Function
"var", // SymbolFlags.Variable
"constructor", // SymbolFlags.Constructor
"member", // SymbolFlags.ClassMember | SymbolFlags.EnumMember
"event", //
"call", // SymbolFlags.Signature (for __call)
"new", // SymbolFlags.Signature (for __new)
"index", // SymbolFlags.Signature (for __index)
"complex", // Any complex type
// TypeDoc specific
"getter",
"setter",
];
// <TAB> <VT> <FF> <SP> <NBSP> <ZWNBSP> <USP>
const WhiteSpace = /[\t\u2B7F\u240C \u00A0\uFEFF\p{White_Space}]/u;
const LineTerminator = "\r\n\u2028\u2029";
const Punctuators = "{}()[]!.#~:,";
const FutureReservedPunctuator = "{}@";
const NavigationPunctuator = ".#~";
const DecimalDigit = "0123456789";
const HexDigit = DecimalDigit + "abcdefABCDEF";
const SingleEscapeCharacter = `'"\\bfnrtv`;
const EscapeCharacter = SingleEscapeCharacter + DecimalDigit + "xu";
const UserLabelStart = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_";
const UserLabelCharacter = UserLabelStart + DecimalDigit;
const SingleEscapeChars = {
"'": "'",
'"': '"',
"\\": "\\",
b: "\b",
f: "\f",
n: "\n",
r: "\r",
t: "\t",
v: "\v",
};
// EscapeSequence::
// SingleEscapeCharacter
// NonEscapeCharacter
// `0` [lookahead != DecimalDigit]
// HexEscapeSequence
// UnicodeEscapeSequence
function parseEscapeSequence(source, pos, end) {
// SingleEscapeCharacter
if (SingleEscapeCharacter.includes(source[pos])) {
return [SingleEscapeChars[source[pos]], pos + 1];
}
// NonEscapeCharacter:: SourceCharacter but not one of EscapeCharacter or LineTerminator
if (!(EscapeCharacter + LineTerminator).includes(source[pos])) {
return [source[pos], pos + 1];
}
// `0` [lookahead != DecimalDigit]
if (source[pos] === "0" &&
pos + 1 < end &&
!DecimalDigit.includes(source[pos + 1])) {
return ["\x00", pos + 1];
}
// HexEscapeSequence:: x HexDigit HexDigit
if (source[pos] === "x" &&
pos + 2 < end &&
HexDigit.includes(source[pos + 1]) &&
HexDigit.includes(source[pos + 2])) {
return [
String.fromCharCode(parseInt(source.substring(pos + 1, pos + 3), 16)),
pos + 3,
];
}
return parseUnicodeEscapeSequence(source, pos, end);
}
// UnicodeEscapeSequence::
// `u` HexDigit HexDigit HexDigit HexDigit
// `u` `{` CodePoint `}`
// CodePoint:: > |HexDigits| but only if MV of |HexDigits| ≤ 0x10FFFF
function parseUnicodeEscapeSequence(source, pos, end) {
if (source[pos] !== "u" || pos + 1 >= end) {
return;
}
if (HexDigit.includes(source[pos + 1])) {
if (pos + 4 >= end ||
!HexDigit.includes(source[pos + 2]) ||
!HexDigit.includes(source[pos + 3]) ||
!HexDigit.includes(source[pos + 4])) {
return;
}
return [
String.fromCharCode(parseInt(source.substring(pos + 1, pos + 5), 16)),
pos + 5,
];
}
if (source[pos + 1] === "{" &&
pos + 2 < end &&
HexDigit.includes(source[pos + 2])) {
let lookahead = pos + 3;
while (lookahead < end && HexDigit.includes(source[lookahead])) {
lookahead++;
}
if (lookahead >= end || source[lookahead] !== "}")
return;
const codePoint = parseInt(source.substring(pos + 2, lookahead), 16);
if (codePoint <= 0x10ffff) {
return [String.fromCodePoint(codePoint), lookahead + 1];
}
}
}
// String:: `"` StringCharacters? `"`
// StringCharacters:: StringCharacter StringCharacters?
// StringCharacter::
// SourceCharacter but not one of `"` or `\` or LineTerminator
// `\` EscapeSequence
function parseString(source, pos, end) {
let result = "";
if (source[pos++] !== '"')
return;
while (pos < end) {
if (source[pos] === '"') {
return [result, pos + 1];
}
if (LineTerminator.includes(source[pos]))
return;
if (source[pos] === "\\") {
const esc = parseEscapeSequence(source, pos + 1, end);
if (!esc)
return;
result += esc[0];
pos = esc[1];
continue;
}
result += source[pos++];
}
}
exports.parseString = parseString;
// ModuleSource:: String | ModuleSourceCharacters
function parseModuleSource(source, pos, end) {
if (pos >= end)
return;
if (source[pos] === '"') {
return parseString(source, pos, end);
}
let lookahead = pos;
while (lookahead < end &&
!('"!' + LineTerminator).includes(source[lookahead])) {
lookahead++;
}
if (lookahead === pos)
return;
return [source.substring(pos, lookahead), lookahead];
}
exports.parseModuleSource = parseModuleSource;
// SymbolReference:
// ComponentPath Meaning?
// Meaning
function parseSymbolReference(source, pos, end) {
const path = parseComponentPath(source, pos, end);
pos = path?.[1] ?? pos;
const meaning = parseMeaning(source, pos, end);
pos = meaning?.[1] ?? pos;
if (path || meaning) {
return [{ path: path?.[0], meaning: meaning?.[0] }, pos];
}
}
exports.parseSymbolReference = parseSymbolReference;
// Component::
// String
// ComponentCharacters
// `[` DeclarationReference `]` <--- THIS ONE IS NOT IMPLEMENTED.
function parseComponent(source, pos, end) {
if (pos < end && source[pos] === '"') {
return parseString(source, pos, end);
}
let lookahead = pos;
while (lookahead < end &&
!('"' +
Punctuators +
FutureReservedPunctuator +
LineTerminator).includes(source[lookahead]) &&
!WhiteSpace.test(source[lookahead])) {
lookahead++;
}
if (lookahead === pos)
return;
return [source.substring(pos, lookahead), lookahead];
}
exports.parseComponent = parseComponent;
// ComponentPath:
// Component
// ComponentPath `.` Component // Navigate via 'exports' of |ComponentPath|
// ComponentPath `#` Component // Navigate via 'members' of |ComponentPath|
// ComponentPath `~` Component // Navigate via 'locals' of |ComponentPath|
function parseComponentPath(source, pos, end) {
const components = [];
let component = parseComponent(source, pos, end);
if (!component)
return;
pos = component[1];
components.push({ navigation: ".", path: component[0] });
while (pos < end && NavigationPunctuator.includes(source[pos])) {
const navigation = source[pos];
pos++;
component = parseComponent(source, pos, end);
if (!component) {
return;
}
pos = component[1];
components.push({ navigation, path: component[0] });
}
return [components, pos];
}
exports.parseComponentPath = parseComponentPath;
// The TSDoc specification permits the first four branches of Meaning. TypeDoc adds the UserLabel
// branch so that the @label tag can be used with this form of declaration references.
// Meaning:
// `:` MeaningKeyword // Indicates the meaning of a symbol (i.e. ':class')
// `:` MeaningKeyword `(` DecimalDigits `)` // Indicates an overloaded meaning (i.e. ':function(1)')
// `:` `(` DecimalDigits `)` // Shorthand for an overloaded meaning (i.e. `:(1)`)
// `:` DecimalDigits // Shorthand for an overloaded meaning (i.e. ':1')
// `:` UserLabel // Indicates a user defined label via {@label CUSTOM_LABEL}
//
// UserLabel:
// UserLabelStart UserLabelCharacter*
function parseMeaning(source, pos, end) {
if (source[pos++] !== ":")
return;
const keyword = exports.MeaningKeywords.find((kw) => pos + kw.length <= end && source.startsWith(kw, pos));
if (keyword) {
pos += keyword.length;
}
if (!keyword && UserLabelStart.includes(source[pos])) {
let lookahead = pos + 1;
while (lookahead < end &&
UserLabelCharacter.includes(source[lookahead])) {
lookahead++;
}
return [{ label: source.substring(pos, lookahead) }, lookahead];
}
if (pos + 1 < end &&
source[pos] === "(" &&
DecimalDigit.includes(source[pos + 1])) {
let lookahead = pos + 1;
while (lookahead < end && DecimalDigit.includes(source[lookahead])) {
lookahead++;
}
if (lookahead < end && source[lookahead] === ")") {
return [
{
keyword,
index: parseInt(source.substring(pos + 1, lookahead)),
},
lookahead + 1,
];
}
}
if (!keyword && pos < end && DecimalDigit.includes(source[pos])) {
let lookahead = pos;
while (lookahead < end && DecimalDigit.includes(source[lookahead])) {
lookahead++;
}
return [
{
index: parseInt(source.substring(pos, lookahead)),
},
lookahead,
];
}
if (keyword) {
return [{ keyword }, pos];
}
}
exports.parseMeaning = parseMeaning;
// // NOTE: The following grammar is incorrect as |SymbolReference| and |ModuleSource| have an
// // ambiguous parse. The correct solution is to use a cover grammar to parse
// // |SymbolReference| until we hit a `!` and then reinterpret the grammar.
// DeclarationReference:
// [empty]
// SymbolReference // Shorthand reference to symbol
// ModuleSource `!` // Reference to a module
// ModuleSource `!` SymbolReference // Reference to an export of a module
// ModuleSource `!` `~` SymbolReference // Reference to a local of a module
// `!` SymbolReference // Reference to global symbol
function parseDeclarationReference(source, pos, end) {
let moduleSource;
let symbolReference;
let resolutionStart = "local";
const moduleSourceOrSymbolRef = parseModuleSource(source, pos, end);
if (moduleSourceOrSymbolRef) {
if (moduleSourceOrSymbolRef[1] < end &&
source[moduleSourceOrSymbolRef[1]] === "!") {
// We had a module source!
pos = moduleSourceOrSymbolRef[1] + 1;
resolutionStart = "global";
moduleSource = moduleSourceOrSymbolRef[0];
}
}
else if (source[pos] === "!") {
pos++;
resolutionStart = "global";
}
const ref = parseSymbolReference(source, pos, end);
if (ref) {
symbolReference = ref[0];
pos = ref[1];
}
if (!moduleSource && !symbolReference)
return;
return [
{
moduleSource,
resolutionStart,
symbolReference,
},
pos,
];
}
exports.parseDeclarationReference = parseDeclarationReference;

View File

@@ -0,0 +1,3 @@
import { Reflection } from "../../models";
import type { DeclarationReference } from "./declarationReference";
export declare function resolveDeclarationReference(reflection: Reflection, ref: DeclarationReference): Reflection | undefined;

View File

@@ -0,0 +1,204 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveDeclarationReference = void 0;
const assert_1 = require("assert");
const models_1 = require("../../models");
const utils_1 = require("../../utils");
function resolveReferenceReflection(ref) {
if (ref instanceof models_1.ReferenceReflection) {
return ref.getTargetReflectionDeep();
}
return ref;
}
function resolveDeclarationReference(reflection, ref) {
let high = [];
let low = [];
if (ref.moduleSource) {
high =
reflection.project.children?.filter((c) => c.kindOf(models_1.ReflectionKind.SomeModule) &&
c.name === ref.moduleSource) || [];
}
else if (ref.resolutionStart === "global") {
high.push(reflection.project);
}
else {
(0, assert_1.ok)(ref.resolutionStart === "local");
// TypeScript's behavior is to first try to resolve links via variable scope, and then
// if the link still hasn't been found, check either siblings (if comment belongs to a member)
// or otherwise children.
let refl = reflection;
if (refl.kindOf(models_1.ReflectionKind.ExportContainer)) {
high.push(refl);
}
while (refl.parent) {
refl = refl.parent;
if (refl.kindOf(models_1.ReflectionKind.ExportContainer)) {
high.push(refl);
}
else {
low.push(refl);
}
}
if (reflection.kindOf(models_1.ReflectionKind.SomeMember)) {
high.push(reflection.parent);
}
else if (reflection.kindOf(models_1.ReflectionKind.SomeSignature) &&
reflection.parent.kindOf(models_1.ReflectionKind.SomeMember)) {
high.push(reflection.parent.parent);
}
else if (high[0] !== reflection) {
if (reflection.parent instanceof models_1.ContainerReflection) {
high.push(...(reflection.parent.children?.filter((c) => c.name === reflection.name) || []));
}
else {
high.push(reflection);
}
}
}
if (ref.symbolReference) {
for (const part of ref.symbolReference.path || []) {
const high2 = high;
high = [];
const low2 = low;
low = [];
for (const refl of high2) {
const resolved = resolveSymbolReferencePart(refl, part);
high.push(...resolved.high.map(resolveReferenceReflection));
low.push(...resolved.low.map(resolveReferenceReflection));
}
for (const refl of low2) {
const resolved = resolveSymbolReferencePart(refl, part);
low.push(...resolved.high.map(resolveReferenceReflection));
low.push(...resolved.low.map(resolveReferenceReflection));
}
}
if (ref.symbolReference.meaning) {
high = filterMapByMeaning(high, ref.symbolReference.meaning);
low = filterMapByMeaning(low, ref.symbolReference.meaning);
}
}
return high[0] || low[0];
}
exports.resolveDeclarationReference = resolveDeclarationReference;
function filterMapByMeaning(reflections, meaning) {
return (0, utils_1.filterMap)(reflections, (refl) => {
const kwResolved = resolveKeyword(refl, meaning.keyword) || [];
if (meaning.label) {
return kwResolved.find((r) => r.comment?.label === meaning.label);
}
return kwResolved[meaning.index || 0];
});
}
function resolveKeyword(refl, kw) {
switch (kw) {
case undefined:
return refl instanceof models_1.DeclarationReflection && refl.signatures
? refl.signatures
: [refl];
case "class":
if (refl.kindOf(models_1.ReflectionKind.Class))
return [refl];
break;
case "interface":
if (refl.kindOf(models_1.ReflectionKind.Interface))
return [refl];
break;
case "type":
if (refl.kindOf(models_1.ReflectionKind.SomeType))
return [refl];
break;
case "enum":
if (refl.kindOf(models_1.ReflectionKind.Enum))
return [refl];
break;
case "namespace":
if (refl.kindOf(models_1.ReflectionKind.SomeModule))
return [refl];
break;
case "function":
if (refl.kindOf(models_1.ReflectionKind.FunctionOrMethod)) {
return refl.signatures;
}
break;
case "var":
if (refl.kindOf(models_1.ReflectionKind.Variable))
return [refl];
break;
case "new":
case "constructor":
if (refl.kindOf(models_1.ReflectionKind.ClassOrInterface |
models_1.ReflectionKind.TypeLiteral)) {
const ctor = refl.children?.find((c) => c.kindOf(models_1.ReflectionKind.Constructor));
return ctor?.signatures;
}
break;
case "member":
if (refl.kindOf(models_1.ReflectionKind.SomeMember))
return [refl];
break;
case "event":
// Never resolve. Nobody should use this.
// It's required by the grammar, but is not documented by TypeDoc
// nor by the comments in the grammar.
break;
case "call":
return refl.signatures;
case "index":
if (refl.indexSignature) {
return [refl.indexSignature];
}
break;
case "complex":
if (refl.kindOf(models_1.ReflectionKind.SomeType))
return [refl];
break;
case "getter":
if (refl.getSignature) {
return [refl.getSignature];
}
break;
case "setter":
if (refl.setSignature) {
return [refl.setSignature];
}
break;
default:
(0, utils_1.assertNever)(kw);
}
}
function resolveSymbolReferencePart(refl, path) {
let high = [];
let low = [];
if (!(refl instanceof models_1.ContainerReflection) || !refl.children) {
return { high, low };
}
switch (path.navigation) {
// Grammar says resolve via "exports"... as always, reality is more complicated.
// Check exports first, but also allow this as a general purpose "some child" operator
// so that resolution doesn't behave very poorly with projects using JSDoc style resolution.
// Also is more consistent with how TypeScript resolves link tags.
case ".":
high = refl.children.filter((r) => r.name === path.path &&
(r.kindOf(models_1.ReflectionKind.SomeExport) || r.flags.isStatic));
low = refl.children.filter((r) => r.name === path.path &&
(!r.kindOf(models_1.ReflectionKind.SomeExport) || !r.flags.isStatic));
break;
// Resolve via "members", interface children, class instance properties/accessors/methods,
// enum members, type literal properties
case "#":
high = refl.children.filter((r) => {
return (r.name === path.path &&
r.kindOf(models_1.ReflectionKind.SomeMember) &&
!r.flags.isStatic);
});
break;
// Resolve via "locals"... treat this as a stricter `.` which only supports traversing
// module/namespace exports since TypeDoc doesn't support documenting locals.
case "~":
if (refl.kindOf(models_1.ReflectionKind.SomeModule | models_1.ReflectionKind.Project)) {
high = refl.children.filter((r) => r.name === path.path);
}
break;
}
return { high, low };
}

View File

@@ -0,0 +1,17 @@
import ts from "typescript";
import { ReflectionKind } from "../../models";
import { Logger } from "../../utils";
import { CommentStyle } from "../../utils/options/declaration";
export interface DiscoveredComment {
file: ts.SourceFile;
ranges: ts.CommentRange[];
jsDoc: ts.JSDoc | undefined;
}
export declare function discoverFileComment(node: ts.SourceFile, commentStyle: CommentStyle): {
file: ts.SourceFile;
ranges: ts.CommentRange[];
jsDoc: ts.JSDoc | undefined;
} | undefined;
export declare function discoverNodeComment(node: ts.Node, commentStyle: CommentStyle): DiscoveredComment | undefined;
export declare function discoverComment(symbol: ts.Symbol, kind: ReflectionKind, logger: Logger, commentStyle: CommentStyle): DiscoveredComment | undefined;
export declare function discoverSignatureComment(declaration: ts.SignatureDeclaration | ts.JSDocSignature, commentStyle: CommentStyle): DiscoveredComment | undefined;

View File

@@ -0,0 +1,364 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.discoverSignatureComment = exports.discoverComment = exports.discoverNodeComment = exports.discoverFileComment = void 0;
const typescript_1 = __importDefault(require("typescript"));
const models_1 = require("../../models");
const utils_1 = require("../../utils");
const declaration_1 = require("../../utils/options/declaration");
const paths_1 = require("../../utils/paths");
const assert_1 = require("assert");
const variablePropertyKinds = [
typescript_1.default.SyntaxKind.PropertyDeclaration,
typescript_1.default.SyntaxKind.PropertySignature,
typescript_1.default.SyntaxKind.BinaryExpression,
typescript_1.default.SyntaxKind.PropertyAssignment,
// class X { constructor(/** Comment */ readonly z: string) }
typescript_1.default.SyntaxKind.Parameter,
// Variable values
typescript_1.default.SyntaxKind.VariableDeclaration,
typescript_1.default.SyntaxKind.BindingElement,
typescript_1.default.SyntaxKind.ExportAssignment,
typescript_1.default.SyntaxKind.PropertyAccessExpression,
];
// Note: This does NOT include JSDoc syntax kinds. This is important!
// Comments from @typedef and @callback tags are handled specially by
// the JSDoc converter because we only want part of the comment when
// getting them.
const wantedKinds = {
[models_1.ReflectionKind.Project]: [
typescript_1.default.SyntaxKind.SourceFile,
typescript_1.default.SyntaxKind.ModuleDeclaration,
],
[models_1.ReflectionKind.Module]: [
typescript_1.default.SyntaxKind.SourceFile,
typescript_1.default.SyntaxKind.ModuleDeclaration,
],
[models_1.ReflectionKind.Namespace]: [
typescript_1.default.SyntaxKind.ModuleDeclaration,
typescript_1.default.SyntaxKind.SourceFile,
typescript_1.default.SyntaxKind.BindingElement,
typescript_1.default.SyntaxKind.ExportSpecifier,
typescript_1.default.SyntaxKind.NamespaceExport,
// @namespace support
typescript_1.default.SyntaxKind.VariableDeclaration,
typescript_1.default.SyntaxKind.BindingElement,
typescript_1.default.SyntaxKind.ExportAssignment,
typescript_1.default.SyntaxKind.PropertyAccessExpression,
],
[models_1.ReflectionKind.Enum]: [
typescript_1.default.SyntaxKind.EnumDeclaration,
typescript_1.default.SyntaxKind.VariableDeclaration,
],
[models_1.ReflectionKind.EnumMember]: [
typescript_1.default.SyntaxKind.EnumMember,
// These here so that @enum gets comments
typescript_1.default.SyntaxKind.PropertyAssignment,
typescript_1.default.SyntaxKind.PropertySignature,
],
[models_1.ReflectionKind.Variable]: variablePropertyKinds,
[models_1.ReflectionKind.Function]: [
typescript_1.default.SyntaxKind.FunctionDeclaration,
typescript_1.default.SyntaxKind.BindingElement,
typescript_1.default.SyntaxKind.VariableDeclaration,
typescript_1.default.SyntaxKind.ExportAssignment,
typescript_1.default.SyntaxKind.PropertyAccessExpression,
],
[models_1.ReflectionKind.Class]: [
typescript_1.default.SyntaxKind.ClassDeclaration,
typescript_1.default.SyntaxKind.BindingElement,
// If marked with @class
typescript_1.default.SyntaxKind.VariableDeclaration,
typescript_1.default.SyntaxKind.ExportAssignment,
typescript_1.default.SyntaxKind.FunctionDeclaration,
],
[models_1.ReflectionKind.Interface]: [
typescript_1.default.SyntaxKind.InterfaceDeclaration,
typescript_1.default.SyntaxKind.TypeAliasDeclaration,
],
[models_1.ReflectionKind.Constructor]: [typescript_1.default.SyntaxKind.Constructor],
[models_1.ReflectionKind.Property]: variablePropertyKinds,
[models_1.ReflectionKind.Method]: [
typescript_1.default.SyntaxKind.FunctionDeclaration,
typescript_1.default.SyntaxKind.MethodDeclaration,
],
[models_1.ReflectionKind.CallSignature]: [
typescript_1.default.SyntaxKind.FunctionDeclaration,
typescript_1.default.SyntaxKind.VariableDeclaration,
typescript_1.default.SyntaxKind.MethodDeclaration,
typescript_1.default.SyntaxKind.MethodDeclaration,
typescript_1.default.SyntaxKind.PropertyDeclaration,
typescript_1.default.SyntaxKind.PropertySignature,
typescript_1.default.SyntaxKind.CallSignature,
],
[models_1.ReflectionKind.IndexSignature]: [typescript_1.default.SyntaxKind.IndexSignature],
[models_1.ReflectionKind.ConstructorSignature]: [typescript_1.default.SyntaxKind.ConstructSignature],
[models_1.ReflectionKind.Parameter]: [typescript_1.default.SyntaxKind.Parameter],
[models_1.ReflectionKind.TypeLiteral]: [typescript_1.default.SyntaxKind.TypeLiteral],
[models_1.ReflectionKind.TypeParameter]: [typescript_1.default.SyntaxKind.TypeParameter],
[models_1.ReflectionKind.Accessor]: [typescript_1.default.SyntaxKind.PropertyDeclaration],
[models_1.ReflectionKind.GetSignature]: [typescript_1.default.SyntaxKind.GetAccessor],
[models_1.ReflectionKind.SetSignature]: [typescript_1.default.SyntaxKind.SetAccessor],
[models_1.ReflectionKind.TypeAlias]: [typescript_1.default.SyntaxKind.TypeAliasDeclaration],
[models_1.ReflectionKind.Reference]: [
typescript_1.default.SyntaxKind.NamespaceExport,
typescript_1.default.SyntaxKind.ExportSpecifier,
],
};
function discoverFileComment(node, commentStyle) {
const text = node.text;
const comments = collectCommentRanges(typescript_1.default.getLeadingCommentRanges(text, node.pos));
const selectedDocComment = comments.find((ranges) => permittedRange(text, ranges, commentStyle));
if (selectedDocComment) {
return {
file: node,
ranges: selectedDocComment,
jsDoc: findJsDocForComment(node, selectedDocComment),
};
}
}
exports.discoverFileComment = discoverFileComment;
function discoverNodeComment(node, commentStyle) {
const text = node.getSourceFile().text;
const comments = collectCommentRanges(typescript_1.default.getLeadingCommentRanges(text, node.pos));
comments.reverse();
const selectedDocComment = comments.find((ranges) => permittedRange(text, ranges, commentStyle));
if (selectedDocComment) {
return {
file: node.getSourceFile(),
ranges: selectedDocComment,
jsDoc: findJsDocForComment(node, selectedDocComment),
};
}
}
exports.discoverNodeComment = discoverNodeComment;
function discoverComment(symbol, kind, logger, commentStyle) {
// For a module comment, we want the first one defined in the file,
// not the last one, since that will apply to the import or declaration.
const reverse = !symbol.declarations?.some(typescript_1.default.isSourceFile);
const discovered = [];
const seen = new Set();
for (const decl of symbol.declarations || []) {
const text = decl.getSourceFile().text;
if (wantedKinds[kind].includes(decl.kind)) {
const node = declarationToCommentNode(decl);
if (!node || seen.has(node)) {
continue;
}
seen.add(node);
// Special behavior here! We temporarily put the implementation comment
// on the reflection which contains all the signatures. This lets us pull
// the comment on the implementation if some signature does not have a comment.
// However, we don't want to skip the node if it is a reference to something.
// See the gh1770 test for an example.
if (kind & models_1.ReflectionKind.ContainsCallSignatures &&
[
typescript_1.default.SyntaxKind.FunctionDeclaration,
typescript_1.default.SyntaxKind.MethodDeclaration,
typescript_1.default.SyntaxKind.Constructor,
].includes(node.kind) &&
!node.body) {
continue;
}
const comments = collectCommentRanges(typescript_1.default.getLeadingCommentRanges(text, node.pos));
if (reverse) {
comments.reverse();
}
const selectedDocComment = comments.find((ranges) => permittedRange(text, ranges, commentStyle));
if (selectedDocComment) {
discovered.push({
file: decl.getSourceFile(),
ranges: selectedDocComment,
jsDoc: findJsDocForComment(node, selectedDocComment),
});
}
}
}
switch (discovered.length) {
case 0:
return undefined;
case 1:
return discovered[0];
default: {
logger.warn(`${symbol.name} has multiple declarations with a comment. An arbitrary comment will be used.`);
const locations = discovered.map(({ file, ranges: [{ pos }] }) => {
const path = (0, paths_1.nicePath)(file.fileName);
const line = typescript_1.default.getLineAndCharacterOfPosition(file, pos).line + 1;
return `${path}:${line}`;
});
logger.info(`The comments for ${symbol.name} are declared at:\n\t${locations.join("\n\t")}`);
return discovered[0];
}
}
}
exports.discoverComment = discoverComment;
function discoverSignatureComment(declaration, commentStyle) {
const node = declarationToCommentNode(declaration);
if (!node) {
return;
}
if (typescript_1.default.isJSDocSignature(node)) {
const comment = node.parent.parent;
(0, assert_1.ok)(typescript_1.default.isJSDoc(comment));
return {
file: node.getSourceFile(),
ranges: [
{
kind: typescript_1.default.SyntaxKind.MultiLineCommentTrivia,
pos: comment.pos,
end: comment.end,
},
],
jsDoc: comment,
};
}
const text = node.getSourceFile().text;
const comments = collectCommentRanges(typescript_1.default.getLeadingCommentRanges(text, node.pos));
comments.reverse();
const comment = comments.find((ranges) => permittedRange(text, ranges, commentStyle));
if (comment) {
return {
file: node.getSourceFile(),
ranges: comment,
jsDoc: findJsDocForComment(node, comment),
};
}
}
exports.discoverSignatureComment = discoverSignatureComment;
function findJsDocForComment(node, ranges) {
if (ranges[0].kind === typescript_1.default.SyntaxKind.MultiLineCommentTrivia) {
const jsDocs = typescript_1.default
.getJSDocCommentsAndTags(node)
.map((doc) => typescript_1.default.findAncestor(doc, typescript_1.default.isJSDoc));
return jsDocs.find((doc) => doc.pos === ranges[0].pos);
}
}
/**
* Check whether the given module declaration is the topmost.
*
* This function returns TRUE if there is no trailing module defined, in
* the following example this would be the case only for module `C`.
*
* ```
* module A.B.C { }
* ```
*
* @param node The module definition that should be tested.
* @return TRUE if the given node is the topmost module declaration, FALSE otherwise.
*/
function isTopmostModuleDeclaration(node) {
return node.getChildren().some(typescript_1.default.isModuleBlock);
}
/**
* Return the root module declaration of the given module declaration.
*
* In the following example this function would always return module
* `A` no matter which of the modules was passed in.
*
* ```
* module A.B.C { }
* ```
*/
function getRootModuleDeclaration(node) {
while (node.parent &&
node.parent.kind === typescript_1.default.SyntaxKind.ModuleDeclaration) {
const parent = node.parent;
if (node.name.pos === parent.name.end + 1) {
node = parent;
}
else {
break;
}
}
return node;
}
function declarationToCommentNode(node) {
if (!node.parent)
return node;
// const abc = 123
// ^^^
if (node.parent.kind === typescript_1.default.SyntaxKind.VariableDeclarationList) {
return node.parent.parent;
}
// const a = () => {}
// ^^^^^^^^
if (node.parent.kind === typescript_1.default.SyntaxKind.VariableDeclaration) {
return node.parent.parent.parent;
}
// class X { y = () => {} }
// ^^^^^^^^
// function Z() {}
// Z.method = () => {}
// ^^^^^^^^
// export default () => {}
// ^^^^^^^^
if ([
typescript_1.default.SyntaxKind.PropertyDeclaration,
typescript_1.default.SyntaxKind.BinaryExpression,
typescript_1.default.SyntaxKind.ExportAssignment,
].includes(node.parent.kind)) {
return node.parent;
}
if (typescript_1.default.isModuleDeclaration(node)) {
if (!isTopmostModuleDeclaration(node)) {
return;
}
else {
return getRootModuleDeclaration(node);
}
}
if (node.kind === typescript_1.default.SyntaxKind.ExportSpecifier) {
return node.parent.parent;
}
if (typescript_1.default.SyntaxKind.NamespaceExport === node.kind) {
return node.parent;
}
return node;
}
/**
* Separate comment ranges into arrays so that multiple line comments are kept together
* and each block comment is left on its own.
*/
function collectCommentRanges(ranges) {
const result = [];
let collect = [];
for (const range of ranges || []) {
collect.push(range);
switch (range.kind) {
case typescript_1.default.SyntaxKind.MultiLineCommentTrivia:
if (collect.length) {
result.push(collect);
collect = [];
}
result.push([range]);
break;
case typescript_1.default.SyntaxKind.SingleLineCommentTrivia:
collect.push(range);
break;
/* istanbul ignore next */
default:
(0, utils_1.assertNever)(range.kind);
}
}
if (collect.length) {
result.push(collect);
}
return result;
}
function permittedRange(text, ranges, commentStyle) {
switch (commentStyle) {
case declaration_1.CommentStyle.All:
return true;
case declaration_1.CommentStyle.Block:
return ranges[0].kind === typescript_1.default.SyntaxKind.MultiLineCommentTrivia;
case declaration_1.CommentStyle.Line:
return ranges[0].kind === typescript_1.default.SyntaxKind.SingleLineCommentTrivia;
case declaration_1.CommentStyle.JSDoc:
return (ranges[0].kind === typescript_1.default.SyntaxKind.MultiLineCommentTrivia &&
text[ranges[0].pos] === "/" &&
text[ranges[0].pos + 1] === "*" &&
text[ranges[0].pos + 2] === "*");
}
}

View File

@@ -0,0 +1,16 @@
import ts from "typescript";
import { Comment, ReflectionKind } from "../../models";
import { Logger } from "../../utils";
import type { CommentStyle, JsDocCompatibility } from "../../utils/options/declaration";
export interface CommentParserConfig {
blockTags: Set<string>;
inlineTags: Set<string>;
modifierTags: Set<string>;
jsDocCompatibility: JsDocCompatibility;
}
export declare function clearCommentCache(): void;
export declare function getComment(symbol: ts.Symbol, kind: ReflectionKind, config: CommentParserConfig, logger: Logger, commentStyle: CommentStyle, checker: ts.TypeChecker | undefined): Comment | undefined;
export declare function getNodeComment(node: ts.Node, kind: ReflectionKind, config: CommentParserConfig, logger: Logger, commentStyle: CommentStyle, checker: ts.TypeChecker | undefined): Comment | undefined;
export declare function getFileComment(file: ts.SourceFile, config: CommentParserConfig, logger: Logger, commentStyle: CommentStyle, checker: ts.TypeChecker | undefined): Comment | undefined;
export declare function getSignatureComment(declaration: ts.SignatureDeclaration | ts.JSDocSignature, config: CommentParserConfig, logger: Logger, commentStyle: CommentStyle, checker: ts.TypeChecker | undefined): Comment | undefined;
export declare function getJsDocComment(declaration: ts.JSDocPropertyLikeTag | ts.JSDocCallbackTag | ts.JSDocTypedefTag | ts.JSDocTemplateTag | ts.JSDocEnumTag, config: CommentParserConfig, logger: Logger, checker: ts.TypeChecker | undefined): Comment | undefined;

View File

@@ -0,0 +1,167 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getJsDocComment = exports.getSignatureComment = exports.getFileComment = exports.getNodeComment = exports.getComment = exports.clearCommentCache = void 0;
const typescript_1 = __importDefault(require("typescript"));
const models_1 = require("../../models");
const utils_1 = require("../../utils");
const blockLexer_1 = require("./blockLexer");
const discovery_1 = require("./discovery");
const lineLexer_1 = require("./lineLexer");
const parser_1 = require("./parser");
const jsDocCommentKinds = [
typescript_1.default.SyntaxKind.JSDocPropertyTag,
typescript_1.default.SyntaxKind.JSDocCallbackTag,
typescript_1.default.SyntaxKind.JSDocTypedefTag,
typescript_1.default.SyntaxKind.JSDocTemplateTag,
typescript_1.default.SyntaxKind.JSDocEnumTag,
];
let commentCache = new WeakMap();
// We need to do this for tests so that changing the tsLinkResolution option
// actually works. Without it, we'd get the old parsed comment which doesn't
// have the TS symbols attached.
function clearCommentCache() {
commentCache = new WeakMap();
}
exports.clearCommentCache = clearCommentCache;
function getCommentWithCache(discovered, config, logger, checker) {
if (!discovered)
return;
const { file, ranges, jsDoc } = discovered;
const cache = commentCache.get(file) || new Map();
if (cache?.has(ranges[0].pos)) {
return cache.get(ranges[0].pos).clone();
}
let comment;
switch (ranges[0].kind) {
case typescript_1.default.SyntaxKind.MultiLineCommentTrivia:
comment = (0, parser_1.parseComment)((0, blockLexer_1.lexBlockComment)(file.text, ranges[0].pos, ranges[0].end, jsDoc, checker), config, file, logger);
break;
case typescript_1.default.SyntaxKind.SingleLineCommentTrivia:
comment = (0, parser_1.parseComment)((0, lineLexer_1.lexLineComments)(file.text, ranges), config, file, logger);
break;
default:
(0, utils_1.assertNever)(ranges[0].kind);
}
cache.set(ranges[0].pos, comment);
commentCache.set(file, cache);
return comment.clone();
}
function getCommentImpl(commentSource, config, logger, moduleComment, checker) {
const comment = getCommentWithCache(commentSource, config, logger, checker);
if (moduleComment && comment) {
// Module comment, make sure it is tagged with @packageDocumentation or @module.
// If it isn't then the comment applies to the first statement in the file, so throw it away.
if (!comment.hasModifier("@packageDocumentation") &&
!comment.getTag("@module")) {
return;
}
}
if (!moduleComment && comment) {
// Ensure module comments are not attached to non-module reflections.
if (comment.hasModifier("@packageDocumentation") ||
comment.getTag("@module")) {
return;
}
}
return comment;
}
function getComment(symbol, kind, config, logger, commentStyle, checker) {
const declarations = symbol.declarations || [];
if (declarations.length &&
declarations.every((d) => jsDocCommentKinds.includes(d.kind))) {
return getJsDocComment(declarations[0], config, logger, checker);
}
const isModule = declarations.some((decl) => {
if (typescript_1.default.isSourceFile(decl))
return true;
if (typescript_1.default.isModuleDeclaration(decl) && typescript_1.default.isStringLiteral(decl.name)) {
return true;
}
return false;
});
const comment = getCommentImpl((0, discovery_1.discoverComment)(symbol, kind, logger, commentStyle), config, logger, isModule, checker);
if (!comment && kind === models_1.ReflectionKind.Property) {
return getConstructorParamPropertyComment(symbol, config, logger, commentStyle, checker);
}
return comment;
}
exports.getComment = getComment;
function getNodeComment(node, kind, config, logger, commentStyle, checker) {
return getCommentImpl((0, discovery_1.discoverNodeComment)(node, commentStyle), config, logger, kind === models_1.ReflectionKind.Module, checker);
}
exports.getNodeComment = getNodeComment;
function getFileComment(file, config, logger, commentStyle, checker) {
return getCommentImpl((0, discovery_1.discoverFileComment)(file, commentStyle), config, logger,
/* moduleComment */ true, checker);
}
exports.getFileComment = getFileComment;
function getConstructorParamPropertyComment(symbol, config, logger, commentStyle, checker) {
const decl = symbol.declarations?.find(typescript_1.default.isParameter);
if (!decl)
return;
const ctor = decl.parent;
const comment = getSignatureComment(ctor, config, logger, commentStyle, checker);
const paramTag = comment?.getIdentifiedTag(symbol.name, "@param");
if (paramTag) {
return new models_1.Comment(paramTag.content);
}
}
function getSignatureComment(declaration, config, logger, commentStyle, checker) {
return getCommentImpl((0, discovery_1.discoverSignatureComment)(declaration, commentStyle), config, logger, false, checker);
}
exports.getSignatureComment = getSignatureComment;
function getJsDocComment(declaration, config, logger, checker) {
const file = declaration.getSourceFile();
// First, get the whole comment. We know we'll need all of it.
let parent = declaration.parent;
while (!typescript_1.default.isJSDoc(parent)) {
parent = parent.parent;
}
// Then parse it.
const comment = getCommentWithCache({
file,
ranges: [
{
kind: typescript_1.default.SyntaxKind.MultiLineCommentTrivia,
pos: parent.pos,
end: parent.end,
},
],
jsDoc: parent,
}, config, logger, checker);
// And pull out the tag we actually care about.
if (typescript_1.default.isJSDocEnumTag(declaration)) {
return new models_1.Comment(comment.getTag("@enum")?.content);
}
if (typescript_1.default.isJSDocTemplateTag(declaration) &&
declaration.comment &&
declaration.typeParameters.length > 1) {
// We could just put the same comment on everything, but due to how comment parsing works,
// we'd have to search for any @template with a name starting with the first type parameter's name
// which feels horribly hacky.
logger.warn(`TypeDoc does not support multiple type parameters defined in a single @template tag with a comment.`, declaration);
return;
}
let name;
if (typescript_1.default.isJSDocTemplateTag(declaration)) {
// This isn't really ideal.
name = declaration.typeParameters[0].name.text;
}
else {
name = declaration.name?.getText();
}
if (!name) {
return;
}
const tag = comment.getIdentifiedTag(name, `@${declaration.tagName.text}`);
if (!tag) {
logger.error(`Failed to find JSDoc tag for ${name} after parsing comment, please file a bug report.`, declaration);
}
else {
return new models_1.Comment(models_1.Comment.cloneDisplayParts(tag.content));
}
}
exports.getJsDocComment = getJsDocComment;

View File

@@ -0,0 +1,17 @@
import type { ReflectionSymbolId } from "../../models";
export declare enum TokenSyntaxKind {
Text = "text",
NewLine = "new_line",
OpenBrace = "open_brace",
CloseBrace = "close_brace",
Tag = "tag",
Code = "code",
TypeAnnotation = "type"
}
export interface Token {
kind: TokenSyntaxKind;
text: string;
pos: number;
tsLinkTarget?: ReflectionSymbolId;
tsLinkText?: string;
}

View File

@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TokenSyntaxKind = void 0;
var TokenSyntaxKind;
(function (TokenSyntaxKind) {
TokenSyntaxKind["Text"] = "text";
TokenSyntaxKind["NewLine"] = "new_line";
TokenSyntaxKind["OpenBrace"] = "open_brace";
TokenSyntaxKind["CloseBrace"] = "close_brace";
TokenSyntaxKind["Tag"] = "tag";
TokenSyntaxKind["Code"] = "code";
TokenSyntaxKind["TypeAnnotation"] = "type";
})(TokenSyntaxKind || (exports.TokenSyntaxKind = TokenSyntaxKind = {}));

View File

@@ -0,0 +1,3 @@
import type * as ts from "typescript";
import { Token } from "./lexer";
export declare function lexLineComments(file: string, ranges: ts.CommentRange[]): Generator<Token, undefined, undefined>;

View File

@@ -0,0 +1,267 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.lexLineComments = void 0;
const lexer_1 = require("./lexer");
function* lexLineComments(file, ranges) {
// Wrapper around our real lex function to collapse adjacent text tokens.
let textToken;
for (const token of lexLineComments2(file, ranges[0].pos, ranges[ranges.length - 1].end)) {
if (token.kind === lexer_1.TokenSyntaxKind.Text) {
if (textToken) {
textToken.text += token.text;
}
else {
textToken = token;
}
}
else {
if (textToken) {
yield textToken;
textToken = void 0;
}
yield token;
}
}
if (textToken) {
yield textToken;
}
return;
}
exports.lexLineComments = lexLineComments;
function* lexLineComments2(file, pos, end) {
// Trailing whitespace
while (pos < end && /\s/.test(file[end - 1])) {
end--;
}
let lineStart = true;
let braceStartsType = false;
for (;;) {
if (lineStart) {
pos = skipLeadingLineTrivia(pos);
lineStart = false;
}
if (pos >= end) {
return;
}
switch (file[pos]) {
case "\n":
yield makeToken(lexer_1.TokenSyntaxKind.NewLine, 1);
lineStart = true;
break;
case "{":
if (braceStartsType && nextNonWs(pos + 1) !== "@") {
yield makeToken(lexer_1.TokenSyntaxKind.TypeAnnotation, findEndOfType(pos) - pos);
braceStartsType = false;
}
else {
yield makeToken(lexer_1.TokenSyntaxKind.OpenBrace, 1);
}
break;
case "}":
yield makeToken(lexer_1.TokenSyntaxKind.CloseBrace, 1);
braceStartsType = false;
break;
case "`": {
// Markdown's code rules are a royal pain. This could be one of several things.
// 1. Inline code: <1-n ticks><text><same number of ticks>
// 2. Code block: <3 ticks><language, no ticks>\n<text>\n<3 ticks>\n
// 3. Unmatched tick(s), not code, but part of some text.
// We don't quite handle #2 correctly yet. PR welcome!
braceStartsType = false;
let tickCount = 1;
let lookahead = pos;
while (lookahead + 1 < end && file[lookahead + 1] === "`") {
tickCount++;
lookahead++;
}
let lookaheadStart = pos;
const codeText = [];
lookahead++;
while (lookahead < end) {
if (lookaheadExactlyNTicks(lookahead, tickCount)) {
lookahead += tickCount;
codeText.push(file.substring(lookaheadStart, lookahead));
yield {
kind: lexer_1.TokenSyntaxKind.Code,
text: codeText.join(""),
pos,
};
pos = lookahead;
break;
}
else if (file[lookahead] === "`") {
while (lookahead < end && file[lookahead] === "`") {
lookahead++;
}
}
else if (file[lookahead] === "\\" &&
lookahead + 1 < end &&
file[lookahead + 1] !== "\n") {
lookahead += 2;
}
else if (file[lookahead] === "\n") {
lookahead++;
codeText.push(file.substring(lookaheadStart, lookahead));
lookahead = skipLeadingLineTrivia(lookahead);
lookaheadStart = lookahead;
}
else {
lookahead++;
}
}
if (lookahead >= end && pos !== lookahead) {
if (tickCount === 3 &&
file.substring(pos, end).includes("\n")) {
codeText.push(file.substring(lookaheadStart, end));
yield {
kind: lexer_1.TokenSyntaxKind.Code,
text: codeText.join(""),
pos,
};
pos = lookahead;
}
else {
yield makeToken(lexer_1.TokenSyntaxKind.Text, tickCount);
}
}
break;
}
case "@": {
let lookahead = pos + 1;
while (lookahead < end && /[a-z]/i.test(file[lookahead])) {
lookahead++;
}
if (lookahead !== pos + 1) {
while (lookahead < end &&
/[a-z0-9]/i.test(file[lookahead])) {
lookahead++;
}
}
if (lookahead !== pos + 1 &&
(lookahead === end || /[\s}]/.test(file[lookahead]))) {
braceStartsType = true;
yield makeToken(lexer_1.TokenSyntaxKind.Tag, lookahead - pos);
break;
}
}
// fall through if we didn't find something that looks like a tag
default: {
const textParts = [];
let lookaheadStart = pos;
let lookahead = pos;
while (lookahead < end) {
if ("{}\n`".includes(file[lookahead]))
break;
if (lookahead !== pos &&
file[lookahead] === "@" &&
/\s/.test(file[lookahead - 1])) {
// Probably the start of a modifier tag
break;
}
if (file[lookahead] === "\\" &&
lookahead + 1 < end &&
"{}@`".includes(file[lookahead + 1])) {
textParts.push(file.substring(lookaheadStart, lookahead), file[lookahead + 1]);
lookahead++;
lookaheadStart = lookahead + 1;
}
lookahead++;
}
textParts.push(file.substring(lookaheadStart, lookahead));
if (textParts.some((part) => /\S/.test(part))) {
braceStartsType = false;
}
// This piece of text had line continuations or escaped text
yield {
kind: lexer_1.TokenSyntaxKind.Text,
text: textParts.join(""),
pos,
};
pos = lookahead;
break;
}
}
}
function makeToken(kind, size) {
const start = pos;
pos += size;
return {
kind,
text: file.substring(start, pos),
pos: start,
};
}
function skipLeadingLineTrivia(pos) {
let lookahead = pos;
while (lookahead < end && /\s/.test(file[lookahead])) {
lookahead++;
}
while (lookahead < end && file[lookahead] === "/") {
lookahead++;
}
if (lookahead < end && file[lookahead] === " ") {
lookahead++;
}
return lookahead;
}
function lookaheadExactlyNTicks(pos, n) {
if (pos + n > end) {
return false;
}
return file.startsWith("`".repeat(n), pos) && file[pos + n] !== "`";
}
function findEndOfType(pos) {
let openBraces = 0;
while (pos < end) {
if (file[pos] === "{") {
openBraces++;
}
else if (file[pos] === "}") {
if (--openBraces === 0) {
break;
}
}
else if ("`'\"".includes(file[pos])) {
pos = findEndOfString(pos);
}
pos++;
}
if (pos < end && file[pos] === "}") {
pos++;
}
return pos;
}
function findEndOfString(pos) {
const endOfString = file[pos];
pos++;
while (pos < end) {
if (file[pos] === endOfString) {
break;
}
else if (file[pos] === "\\") {
pos++; // Skip escaped character
}
else if (endOfString === "`" &&
file[pos] === "$" &&
file[pos + 1] === "{") {
// Template literal with data inside a ${}
while (pos < end && file[pos] !== "}") {
if ("`'\"".includes(file[pos])) {
pos = findEndOfString(pos) + 1;
}
else {
pos++;
}
}
}
pos++;
}
return pos;
}
function nextNonWs(pos) {
while (pos < end && /\s/.test(file[pos])) {
pos++;
}
return file[pos];
}
}

View File

@@ -0,0 +1,20 @@
import { Comment, CommentDisplayPart, Reflection, ReflectionSymbolId } from "../../models";
import { DeclarationReference } from "./declarationReference";
export type ExternalResolveResult = {
target: string;
caption?: string;
};
/**
* @param ref - Parsed declaration reference to resolve. This may be created automatically for some symbol, or
* parsed from user input.
* @param refl - Reflection that contains the resolved link
* @param part - If the declaration reference was created from a comment, the originating part.
* @param symbolId - If the declaration reference was created from a symbol, or `useTsLinkResolution` is turned
* on and TypeScript resolved the link to some symbol, the ID of that symbol.
*/
export type ExternalSymbolResolver = (ref: DeclarationReference, refl: Reflection, part: Readonly<CommentDisplayPart> | undefined, symbolId: ReflectionSymbolId | undefined) => ExternalResolveResult | string | undefined;
export type LinkResolverOptions = {
preserveLinkText: boolean;
};
export declare function resolveLinks(comment: Comment, reflection: Reflection, externalResolver: ExternalSymbolResolver, options: LinkResolverOptions): void;
export declare function resolvePartLinks(reflection: Reflection, parts: readonly CommentDisplayPart[], externalResolver: ExternalSymbolResolver, options: LinkResolverOptions): CommentDisplayPart[];

View File

@@ -0,0 +1,126 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolvePartLinks = exports.resolveLinks = void 0;
const typescript_1 = __importDefault(require("typescript"));
const models_1 = require("../../models");
const declarationReference_1 = require("./declarationReference");
const declarationReferenceResolver_1 = require("./declarationReferenceResolver");
const urlPrefix = /^(http|ftp)s?:\/\//;
function resolveLinks(comment, reflection, externalResolver, options) {
comment.summary = resolvePartLinks(reflection, comment.summary, externalResolver, options);
for (const tag of comment.blockTags) {
tag.content = resolvePartLinks(reflection, tag.content, externalResolver, options);
}
if (reflection instanceof models_1.DeclarationReflection && reflection.readme) {
reflection.readme = resolvePartLinks(reflection, reflection.readme, externalResolver, options);
}
}
exports.resolveLinks = resolveLinks;
function resolvePartLinks(reflection, parts, externalResolver, options) {
return parts.flatMap((part) => processPart(reflection, part, externalResolver, options));
}
exports.resolvePartLinks = resolvePartLinks;
function processPart(reflection, part, externalResolver, options) {
if (part.kind === "inline-tag") {
if (part.tag === "@link" ||
part.tag === "@linkcode" ||
part.tag === "@linkplain") {
return resolveLinkTag(reflection, part, externalResolver, options);
}
}
return part;
}
function resolveLinkTag(reflection, part, externalResolver, options) {
let defaultDisplayText = "";
let pos = 0;
const end = part.text.length;
while (pos < end && typescript_1.default.isWhiteSpaceLike(part.text.charCodeAt(pos))) {
pos++;
}
let target;
// Try to parse a declaration reference if we didn't use the TS symbol for resolution
const declRef = (0, declarationReference_1.parseDeclarationReference)(part.text, pos, end);
// Might already know where it should go if useTsLinkResolution is turned on
if (part.target instanceof models_1.ReflectionSymbolId) {
const tsTarget = reflection.project.getReflectionFromSymbolId(part.target);
if (tsTarget) {
target = tsTarget;
pos = end;
defaultDisplayText =
part.tsLinkText ||
(options.preserveLinkText ? part.text : target.name);
}
else if (declRef) {
// If we didn't find a target, we might be pointing to a symbol in another project that will be merged in
// or some external symbol, so ask external resolvers to try resolution. Don't use regular declaration ref
// resolution in case it matches something that would have been merged in later.
const externalResolveResult = externalResolver(declRef[0], reflection, part, part.target instanceof models_1.ReflectionSymbolId
? part.target
: undefined);
defaultDisplayText = options.preserveLinkText
? part.text
: part.text.substring(0, pos);
switch (typeof externalResolveResult) {
case "string":
target = externalResolveResult;
break;
case "object":
target = externalResolveResult.target;
defaultDisplayText =
externalResolveResult.caption || defaultDisplayText;
}
}
}
if (!target && declRef) {
// Got one, great! Try to resolve the link
target = (0, declarationReferenceResolver_1.resolveDeclarationReference)(reflection, declRef[0]);
pos = declRef[1];
if (target) {
defaultDisplayText = options.preserveLinkText
? part.text
: target.name;
}
else {
// If we didn't find a link, it might be a @link tag to an external symbol, check that next.
const externalResolveResult = externalResolver(declRef[0], reflection, part, part.target instanceof models_1.ReflectionSymbolId
? part.target
: undefined);
defaultDisplayText = options.preserveLinkText
? part.text
: part.text.substring(0, pos);
switch (typeof externalResolveResult) {
case "string":
target = externalResolveResult;
break;
case "object":
target = externalResolveResult.target;
defaultDisplayText =
externalResolveResult.caption || defaultDisplayText;
}
}
}
if (!target && urlPrefix.test(part.text)) {
const wsIndex = part.text.search(/\s/);
target = wsIndex === -1 ? part.text : part.text.substring(0, wsIndex);
pos = target.length;
defaultDisplayText = target;
}
// Remaining text after an optional pipe is the link text, so advance
// until that's consumed.
while (pos < end && typescript_1.default.isWhiteSpaceLike(part.text.charCodeAt(pos))) {
pos++;
}
if (pos < end && part.text[pos] === "|") {
pos++;
}
if (!target) {
return part;
}
part.target = target;
part.text =
part.text.substring(pos).trim() || defaultDisplayText || part.text;
return part;
}

View File

@@ -0,0 +1,6 @@
import type { CommentParserConfig } from ".";
import { Comment } from "../../models";
import { Logger } from "../../utils";
import type { MinimalSourceFile } from "../../utils/minimalSourceFile";
import { Token } from "./lexer";
export declare function parseComment(tokens: Generator<Token, undefined, undefined>, config: CommentParserConfig, file: MinimalSourceFile, logger: Logger): Comment;

View File

@@ -0,0 +1,393 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseComment = void 0;
const assert_1 = require("assert");
const models_1 = require("../../models");
const utils_1 = require("../../utils");
const paths_1 = require("../../utils/paths");
const lexer_1 = require("./lexer");
const tagName_1 = require("./tagName");
function makeLookaheadGenerator(gen) {
let trackHistory = false;
const history = [];
const next = [gen.next()];
return {
done() {
return !!next[0].done;
},
peek() {
(0, assert_1.ok)(!next[0].done);
return next[0].value;
},
take() {
const thisItem = next.shift();
if (trackHistory) {
history.push(thisItem);
}
(0, assert_1.ok)(!thisItem.done);
next.push(gen.next());
return thisItem.value;
},
mark() {
(0, assert_1.ok)(!trackHistory, "Can only mark one location for backtracking at a time");
trackHistory = true;
},
release() {
trackHistory = false;
next.unshift(...history);
history.length = 0;
},
};
}
function parseComment(tokens, config, file, logger) {
const lexer = makeLookaheadGenerator(tokens);
const tok = lexer.done() || lexer.peek();
const comment = new models_1.Comment();
comment.summary = blockContent(comment, lexer, config, warningImpl);
while (!lexer.done()) {
comment.blockTags.push(blockTag(comment, lexer, config, warningImpl));
}
postProcessComment(comment, (message) => {
(0, assert_1.ok)(typeof tok === "object");
logger.warn(`${message} in comment at ${(0, paths_1.nicePath)(file.fileName)}:${file.getLineAndCharacterOfPosition(tok.pos).line + 1}`);
});
return comment;
function warningImpl(message, token) {
logger.warn(message, token.pos, file);
}
}
exports.parseComment = parseComment;
const HAS_USER_IDENTIFIER = [
"@callback",
"@param",
"@prop",
"@property",
"@template",
"@typedef",
"@typeParam",
"@inheritDoc",
];
function makeCodeBlock(text) {
return "```ts\n" + text + "\n```";
}
/**
* Loop over comment, produce lint warnings, and set tag names for tags
* which have them.
*/
function postProcessComment(comment, warning) {
for (const tag of comment.blockTags) {
if (HAS_USER_IDENTIFIER.includes(tag.tag) && tag.content.length) {
const first = tag.content[0];
if (first.kind === "text") {
const { name, newText } = (0, tagName_1.extractTagName)(first.text);
tag.name = name;
if (newText) {
first.text = newText;
}
else {
// Remove this token, no real text in it.
tag.content.shift();
}
}
}
if (tag.content.some((part) => part.kind === "inline-tag" && part.tag === "@inheritDoc")) {
warning("An inline @inheritDoc tag should not appear within a block tag as it will not be processed");
}
}
const remarks = comment.blockTags.filter((tag) => tag.tag === "@remarks");
if (remarks.length > 1) {
warning("At most one @remarks tag is expected in a comment, ignoring all but the first");
(0, utils_1.removeIf)(comment.blockTags, (tag) => remarks.indexOf(tag) > 0);
}
const returns = comment.blockTags.filter((tag) => tag.tag === "@returns");
if (remarks.length > 1) {
warning("At most one @returns tag is expected in a comment, ignoring all but the first");
(0, utils_1.removeIf)(comment.blockTags, (tag) => returns.indexOf(tag) > 0);
}
const inheritDoc = comment.blockTags.filter((tag) => tag.tag === "@inheritDoc");
const inlineInheritDoc = comment.summary.filter((part) => part.kind === "inline-tag" && part.tag === "@inheritDoc");
if (inlineInheritDoc.length + inheritDoc.length > 1) {
warning("At most one @inheritDoc tag is expected in a comment, ignoring all but the first");
const allInheritTags = [...inlineInheritDoc, ...inheritDoc];
(0, utils_1.removeIf)(comment.summary, (part) => allInheritTags.indexOf(part) > 0);
(0, utils_1.removeIf)(comment.blockTags, (tag) => allInheritTags.indexOf(tag) > 0);
}
if ((inlineInheritDoc.length || inheritDoc.length) &&
comment.summary.some((part) => part.kind !== "inline-tag" && /\S/.test(part.text))) {
warning("Content in the summary section will be overwritten by the @inheritDoc tag");
}
if ((inlineInheritDoc.length || inheritDoc.length) && remarks.length) {
warning("Content in the @remarks block will be overwritten by the @inheritDoc tag");
}
}
const aliasedTags = new Map([["@return", "@returns"]]);
function blockTag(comment, lexer, config, warning) {
const blockTag = lexer.take();
(0, assert_1.ok)(blockTag.kind === lexer_1.TokenSyntaxKind.Tag, "blockTag called not at the start of a block tag."); // blockContent is broken if this fails.
const tagName = aliasedTags.get(blockTag.text) || blockTag.text;
let content;
if (tagName === "@example") {
return exampleBlock(comment, lexer, config, warning);
}
else if (["@default", "@defaultValue"].includes(tagName) &&
config.jsDocCompatibility.defaultTag) {
content = defaultBlockContent(comment, lexer, config, warning);
}
else {
content = blockContent(comment, lexer, config, warning);
}
return new models_1.CommentTag(tagName, content);
}
/**
* The `@default` tag gets a special case because otherwise we will produce many warnings
* about unescaped/mismatched/missing braces in legacy JSDoc comments
*/
function defaultBlockContent(comment, lexer, config, warning) {
lexer.mark();
const content = blockContent(comment, lexer, config, () => { });
const end = lexer.done() || lexer.peek();
lexer.release();
if (content.some((part) => part.kind === "code")) {
return blockContent(comment, lexer, config, warning);
}
const tokens = [];
while ((lexer.done() || lexer.peek()) !== end) {
tokens.push(lexer.take());
}
const blockText = tokens
.map((tok) => tok.text)
.join("")
.trim();
return [
{
kind: "code",
text: makeCodeBlock(blockText),
},
];
}
/**
* The `@example` tag gets a special case because otherwise we will produce many warnings
* about unescaped/mismatched/missing braces in legacy JSDoc comments.
*
* In TSDoc, we also want to treat the first line of the block as the example name.
*/
function exampleBlock(comment, lexer, config, warning) {
lexer.mark();
const content = blockContent(comment, lexer, config, () => { });
const end = lexer.done() || lexer.peek();
lexer.release();
if (!config.jsDocCompatibility.exampleTag ||
content.some((part) => part.kind === "code" && part.text.startsWith("```"))) {
let exampleName = "";
// First line of @example block is the example name.
let warnedAboutRichNameContent = false;
outer: while ((lexer.done() || lexer.peek()) !== end) {
const next = lexer.peek();
switch (next.kind) {
case lexer_1.TokenSyntaxKind.NewLine:
lexer.take();
break outer;
case lexer_1.TokenSyntaxKind.Text: {
const newline = next.text.indexOf("\n");
if (newline !== -1) {
exampleName += next.text.substring(0, newline);
next.pos += newline + 1;
break outer;
}
else {
exampleName += lexer.take().text;
}
break;
}
case lexer_1.TokenSyntaxKind.Code:
case lexer_1.TokenSyntaxKind.Tag:
case lexer_1.TokenSyntaxKind.TypeAnnotation:
case lexer_1.TokenSyntaxKind.CloseBrace:
case lexer_1.TokenSyntaxKind.OpenBrace:
if (!warnedAboutRichNameContent) {
warning("The first line of an example tag will be taken literally as" +
" the example name, and should only contain text.", lexer.peek());
warnedAboutRichNameContent = true;
}
exampleName += lexer.take().text;
break;
default:
(0, utils_1.assertNever)(next.kind);
}
}
const content = blockContent(comment, lexer, config, warning);
const tag = new models_1.CommentTag("@example", content);
if (exampleName.trim()) {
tag.name = exampleName.trim();
}
return tag;
}
const tokens = [];
while ((lexer.done() || lexer.peek()) !== end) {
tokens.push(lexer.take());
}
const blockText = tokens
.map((tok) => tok.text)
.join("")
.trim();
const caption = blockText.match(/^\s*<caption>(.*?)<\/caption>\s*(\n|$)/);
if (caption) {
const tag = new models_1.CommentTag("@example", [
{
kind: "code",
text: makeCodeBlock(blockText.slice(caption[0].length)),
},
]);
tag.name = caption[1];
return tag;
}
else {
return new models_1.CommentTag("@example", [
{
kind: "code",
text: makeCodeBlock(blockText),
},
]);
}
}
function blockContent(comment, lexer, config, warning) {
const content = [];
let atNewLine = true;
loop: while (!lexer.done()) {
const next = lexer.peek();
let consume = true;
switch (next.kind) {
case lexer_1.TokenSyntaxKind.NewLine:
case lexer_1.TokenSyntaxKind.Text:
content.push({ kind: "text", text: next.text });
break;
case lexer_1.TokenSyntaxKind.Code:
content.push({ kind: "code", text: next.text });
break;
case lexer_1.TokenSyntaxKind.Tag:
if (next.text === "@inheritdoc") {
if (!config.jsDocCompatibility.inheritDocTag) {
warning("The @inheritDoc tag should be properly capitalized", next);
}
next.text = "@inheritDoc";
}
if (config.modifierTags.has(next.text)) {
comment.modifierTags.add(next.text);
break;
}
else if (!atNewLine && !config.blockTags.has(next.text)) {
// Treat unknown tag as a modifier, but warn about it.
comment.modifierTags.add(next.text);
warning(`Treating unrecognized tag "${next.text}" as a modifier tag`, next);
break;
}
else {
// Block tag or unknown tag, handled by our caller.
break loop;
}
case lexer_1.TokenSyntaxKind.TypeAnnotation:
// We always ignore these. In TS files they are redundant, in JS files
// they are required.
break;
case lexer_1.TokenSyntaxKind.CloseBrace:
// Unmatched closing brace, generate a warning, and treat it as text.
if (!config.jsDocCompatibility.ignoreUnescapedBraces) {
warning(`Unmatched closing brace`, next);
}
content.push({ kind: "text", text: next.text });
break;
case lexer_1.TokenSyntaxKind.OpenBrace:
inlineTag(lexer, content, config, warning);
consume = false;
break;
default:
(0, utils_1.assertNever)(next.kind);
}
if (consume && lexer.take().kind === lexer_1.TokenSyntaxKind.NewLine) {
atNewLine = true;
}
}
// Collapse adjacent text parts
for (let i = 0; i < content.length - 1 /* inside loop */;) {
if (content[i].kind === "text" && content[i + 1].kind === "text") {
content[i].text += content[i + 1].text;
content.splice(i + 1, 1);
}
else {
i++;
}
}
// Now get rid of extra whitespace, and any empty parts
for (let i = 0; i < content.length /* inside loop */;) {
if (i === 0 || content[i].kind === "inline-tag") {
content[i].text = content[i].text.trimStart();
}
if (i === content.length - 1 || content[i].kind === "inline-tag") {
content[i].text = content[i].text.trimEnd();
}
if (!content[i].text && content[i].kind === "text") {
content.splice(i, 1);
}
else {
i++;
}
}
return content;
}
function inlineTag(lexer, block, config, warning) {
const openBrace = lexer.take();
// Now skip whitespace to grab the tag name.
// If the first non-whitespace text after the brace isn't a tag,
// then produce a warning and treat what we've consumed as plain text.
if (lexer.done() ||
![lexer_1.TokenSyntaxKind.Text, lexer_1.TokenSyntaxKind.Tag].includes(lexer.peek().kind)) {
if (!config.jsDocCompatibility.ignoreUnescapedBraces) {
warning("Encountered an unescaped open brace without an inline tag", openBrace);
}
block.push({ kind: "text", text: openBrace.text });
return;
}
let tagName = lexer.take();
if (lexer.done() ||
(tagName.kind === lexer_1.TokenSyntaxKind.Text &&
(!/^\s+$/.test(tagName.text) ||
lexer.peek().kind != lexer_1.TokenSyntaxKind.Tag))) {
if (!config.jsDocCompatibility.ignoreUnescapedBraces) {
warning("Encountered an unescaped open brace without an inline tag", openBrace);
}
block.push({ kind: "text", text: openBrace.text + tagName.text });
return;
}
if (tagName.kind !== lexer_1.TokenSyntaxKind.Tag) {
tagName = lexer.take();
}
if (!config.inlineTags.has(tagName.text)) {
warning(`Encountered an unknown inline tag "${tagName.text}"`, tagName);
}
const content = [];
// At this point, we know we have an inline tag. Treat everything following as plain text,
// until we get to the closing brace.
while (!lexer.done() && lexer.peek().kind !== lexer_1.TokenSyntaxKind.CloseBrace) {
const token = lexer.take();
if (token.kind === lexer_1.TokenSyntaxKind.OpenBrace) {
warning("Encountered an open brace within an inline tag, this is likely a mistake", token);
}
content.push(token.kind === lexer_1.TokenSyntaxKind.NewLine ? " " : token.text);
}
if (lexer.done()) {
warning("Inline tag is not closed", openBrace);
}
else {
lexer.take(); // Close brace
}
const inlineTag = {
kind: "inline-tag",
tag: tagName.text,
text: content.join(""),
};
if (tagName.tsLinkTarget) {
inlineTag.target = tagName.tsLinkTarget;
inlineTag.tsLinkText = tagName.tsLinkText;
}
block.push(inlineTag);
}

View File

@@ -0,0 +1,2 @@
import { Token } from "./lexer";
export declare function lexCommentString(file: string): Generator<Token, undefined, undefined>;

View File

@@ -0,0 +1,258 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.lexCommentString = void 0;
const lexer_1 = require("./lexer");
function* lexCommentString(file) {
// Wrapper around our real lex function to collapse adjacent text tokens.
let textToken;
for (const token of lexCommentString2(file)) {
if (token.kind === lexer_1.TokenSyntaxKind.Text) {
if (textToken) {
textToken.text += token.text;
}
else {
textToken = token;
}
}
else {
if (textToken) {
yield textToken;
textToken = void 0;
}
yield token;
}
}
if (textToken) {
yield textToken;
}
return;
}
exports.lexCommentString = lexCommentString;
function* lexCommentString2(file) {
let pos = 0;
let end = file.length;
// Skip leading whitespace
while (pos < end && /\s/.test(file[pos])) {
pos++;
}
// Trailing whitespace
while (pos < end && /\s/.test(file[end - 1])) {
end--;
}
let lineStart = true;
let braceStartsType = false;
for (;;) {
if (pos >= end) {
return;
}
if (lineStart) {
lineStart = false;
}
switch (file[pos]) {
case "\n":
yield makeToken(lexer_1.TokenSyntaxKind.NewLine, 1);
lineStart = true;
break;
case "{":
if (braceStartsType && nextNonWs(pos + 1) !== "@") {
yield makeToken(lexer_1.TokenSyntaxKind.TypeAnnotation, findEndOfType(pos) - pos);
braceStartsType = false;
}
else {
yield makeToken(lexer_1.TokenSyntaxKind.OpenBrace, 1);
}
break;
case "}":
yield makeToken(lexer_1.TokenSyntaxKind.CloseBrace, 1);
braceStartsType = false;
break;
case "`": {
// Markdown's code rules are a royal pain. This could be one of several things.
// 1. Inline code: <1-n ticks><text><same number of ticks>
// 2. Code block: <3 ticks><language, no ticks>\n<text>\n<3 ticks>\n
// 3. Unmatched tick(s), not code, but part of some text.
// We don't quite handle #2 correctly yet. PR welcome!
braceStartsType = false;
let tickCount = 1;
let lookahead = pos;
while (lookahead + 1 < end && file[lookahead + 1] === "`") {
tickCount++;
lookahead++;
}
let lookaheadStart = pos;
const codeText = [];
lookahead++;
while (lookahead < end) {
if (lookaheadExactlyNTicks(lookahead, tickCount)) {
lookahead += tickCount;
codeText.push(file.substring(lookaheadStart, lookahead));
yield {
kind: lexer_1.TokenSyntaxKind.Code,
text: codeText.join(""),
pos,
};
pos = lookahead;
break;
}
else if (file[lookahead] === "`") {
while (lookahead < end && file[lookahead] === "`") {
lookahead++;
}
}
else if (file[lookahead] === "\\" &&
lookahead + 1 < end &&
file[lookahead + 1] !== "\n") {
lookahead += 2;
}
else if (file[lookahead] === "\n") {
lookahead++;
codeText.push(file.substring(lookaheadStart, lookahead));
lookaheadStart = lookahead;
}
else {
lookahead++;
}
}
if (lookahead >= end && pos !== lookahead) {
if (tickCount === 3 &&
file.substring(pos, end).includes("\n")) {
codeText.push(file.substring(lookaheadStart, end));
yield {
kind: lexer_1.TokenSyntaxKind.Code,
text: codeText.join(""),
pos,
};
pos = lookahead;
}
else {
yield makeToken(lexer_1.TokenSyntaxKind.Text, tickCount);
}
}
break;
}
case "@": {
let lookahead = pos + 1;
while (lookahead < end && /[a-z]/i.test(file[lookahead])) {
lookahead++;
}
if (lookahead !== pos + 1) {
while (lookahead < end &&
/[a-z0-9]/i.test(file[lookahead])) {
lookahead++;
}
}
if (lookahead !== pos + 1 &&
(lookahead === end || /[\s}]/.test(file[lookahead]))) {
braceStartsType = true;
yield makeToken(lexer_1.TokenSyntaxKind.Tag, lookahead - pos);
break;
}
}
// fall through if we didn't find something that looks like a tag
default: {
const textParts = [];
let lookaheadStart = pos;
let lookahead = pos;
while (lookahead < end) {
if ("{}\n`".includes(file[lookahead]))
break;
if (lookahead !== pos &&
file[lookahead] === "@" &&
/\s/.test(file[lookahead - 1])) {
// Probably the start of a modifier tag
break;
}
if (file[lookahead] === "\\" &&
lookahead + 1 < end &&
"{}@`".includes(file[lookahead + 1])) {
textParts.push(file.substring(lookaheadStart, lookahead), file[lookahead + 1]);
lookahead++;
lookaheadStart = lookahead + 1;
}
lookahead++;
}
textParts.push(file.substring(lookaheadStart, lookahead));
if (textParts.some((part) => /\S/.test(part))) {
braceStartsType = false;
}
// This piece of text had line continuations or escaped text
yield {
kind: lexer_1.TokenSyntaxKind.Text,
text: textParts.join(""),
pos,
};
pos = lookahead;
break;
}
}
}
function makeToken(kind, size) {
const start = pos;
pos += size;
return {
kind,
text: file.substring(start, pos),
pos: start,
};
}
function lookaheadExactlyNTicks(pos, n) {
if (pos + n > end) {
return false;
}
return file.startsWith("`".repeat(n), pos) && file[pos + n] !== "`";
}
function findEndOfType(pos) {
let openBraces = 0;
while (pos < end) {
if (file[pos] === "{") {
openBraces++;
}
else if (file[pos] === "}") {
if (--openBraces === 0) {
break;
}
}
else if ("`'\"".includes(file[pos])) {
pos = findEndOfString(pos);
}
pos++;
}
if (pos < end && file[pos] === "}") {
pos++;
}
return pos;
}
function findEndOfString(pos) {
const endOfString = file[pos];
pos++;
while (pos < end) {
if (file[pos] === endOfString) {
break;
}
else if (file[pos] === "\\") {
pos++; // Skip escaped character
}
else if (endOfString === "`" &&
file[pos] === "$" &&
file[pos + 1] === "{") {
// Template literal with data inside a ${}
while (pos < end && file[pos] !== "}") {
if ("`'\"".includes(file[pos])) {
pos = findEndOfString(pos) + 1;
}
else {
pos++;
}
}
}
pos++;
}
return pos;
}
function nextNonWs(pos) {
while (pos < end && /\s/.test(file[pos])) {
pos++;
}
return file[pos];
}
}

View File

@@ -0,0 +1,8 @@
/**
* Determines the name of the parameter/template/property from the tag content
* when processing `@param x`
*/
export declare function extractTagName(text: string): {
name: string;
newText: string;
};

View File

@@ -0,0 +1,62 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractTagName = void 0;
/**
* Determines the name of the parameter/template/property from the tag content
* when processing `@param x`
*/
function extractTagName(text) {
let pos = skipWs(text, 0);
// Extract the "name" part of the comment, this might also include a default
// value if bracketed.
let nameStart = pos;
let bracketDepth = 0;
let stringChar = "";
while (pos < text.length && (bracketDepth > 0 || /\S/.test(text[pos]))) {
if (stringChar) {
if (text[pos] == stringChar) {
stringChar = "";
++pos;
}
else if (text[pos] == "\\") {
pos += 2;
}
else {
++pos;
}
}
else {
if ("\"'`".includes(text[pos])) {
stringChar = text[pos];
}
else if (text[pos] == "[") {
++bracketDepth;
}
else if (text[pos] == "]") {
--bracketDepth;
}
++pos;
}
}
let nameEnd = pos;
if (text[nameStart] === "[") {
nameStart = skipWs(text, nameStart + 1);
nameEnd = skipWith(text, nameStart, /[^\s=\]]/);
}
// Skip any whitespace & an optional dash before the description
pos = skipWith(text, pos, /[\s-]/);
return {
name: text.substring(nameStart, nameEnd),
newText: text.substring(pos),
};
}
exports.extractTagName = extractTagName;
function skipWs(text, pos) {
return skipWith(text, pos, /\s/);
}
function skipWith(text, pos, reg) {
while (pos < text.length && reg.test(text[pos])) {
++pos;
}
return pos;
}

View File

@@ -0,0 +1,5 @@
import { Component, AbstractComponent } from "../utils/component";
import type { Converter } from "./converter";
export { Component };
export declare abstract class ConverterComponent extends AbstractComponent<Converter> {
}

View File

@@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConverterComponent = exports.Component = void 0;
const component_1 = require("../utils/component");
Object.defineProperty(exports, "Component", { enumerable: true, get: function () { return component_1.Component; } });
class ConverterComponent extends component_1.AbstractComponent {
}
exports.ConverterComponent = ConverterComponent;

87
node_modules/typedoc/dist/lib/converter/context.d.ts generated vendored Normal file
View File

@@ -0,0 +1,87 @@
import ts from "typescript";
import { Reflection, ProjectReflection, DeclarationReflection, ReflectionKind } from "../models/index";
import type { Converter } from "./converter";
/**
* The context describes the current state the converter is in.
*/
export declare class Context {
/**
* The converter instance that has created the context.
*/
readonly converter: Converter;
/**
* The TypeChecker instance returned by the TypeScript compiler.
*/
get checker(): ts.TypeChecker;
/**
* The program currently being converted.
* Accessing this property will throw if a source file is not currently being converted.
*/
get program(): ts.Program;
private _program?;
/**
* All programs being converted.
*/
readonly programs: readonly ts.Program[];
/**
* The project that is currently processed.
*/
readonly project: ProjectReflection;
/**
* The scope or parent reflection that is currently processed.
*/
readonly scope: Reflection;
convertingTypeNode: boolean;
convertingClassOrInterface: boolean;
shouldBeStatic: boolean;
/**
* Create a new Context instance.
*
* @param converter The converter instance that has created the context.
* @internal
*/
constructor(converter: Converter, programs: readonly ts.Program[], project: ProjectReflection, scope?: Context["scope"]);
/** @internal */
get logger(): import("../utils").Logger;
/**
* Return the type declaration of the given node.
*
* @param node The TypeScript node whose type should be resolved.
* @returns The type declaration of the given node.
*/
getTypeAtLocation(node: ts.Node): ts.Type | undefined;
getSymbolAtLocation(node: ts.Node): ts.Symbol | undefined;
expectSymbolAtLocation(node: ts.Node): ts.Symbol;
resolveAliasedSymbol(symbol: ts.Symbol): ts.Symbol;
createDeclarationReflection(kind: ReflectionKind, symbol: ts.Symbol | undefined, exportSymbol: ts.Symbol | undefined, nameOverride?: string): DeclarationReflection;
postReflectionCreation(reflection: Reflection, symbol: ts.Symbol | undefined, exportSymbol: ts.Symbol | undefined): void;
finalizeDeclarationReflection(reflection: DeclarationReflection): void;
addChild(reflection: DeclarationReflection): void;
shouldIgnore(symbol: ts.Symbol): boolean;
/**
* Register a newly generated reflection. All created reflections should be
* passed to this method to ensure that the project helper functions work correctly.
*
* @param reflection The reflection that should be registered.
* @param symbol The symbol the given reflection was resolved from.
*/
registerReflection(reflection: Reflection, symbol: ts.Symbol | undefined): void;
/**
* Trigger a node reflection event.
*
* All events are dispatched on the current converter instance.
*
* @param name The name of the event that should be triggered.
* @param reflection The triggering reflection.
* @param node The triggering TypeScript node if available.
*/
trigger(name: string, reflection: Reflection, node?: ts.Node): void;
/** @internal */
setActiveProgram(program: ts.Program | undefined): void;
getComment(symbol: ts.Symbol, kind: ReflectionKind): import("../models/index").Comment | undefined;
getNodeComment(node: ts.Node, kind: ReflectionKind): import("../models/index").Comment | undefined;
getFileComment(node: ts.SourceFile): import("../models/index").Comment | undefined;
getJsDocComment(declaration: ts.JSDocPropertyLikeTag | ts.JSDocCallbackTag | ts.JSDocTypedefTag | ts.JSDocTemplateTag | ts.JSDocEnumTag): import("../models/index").Comment | undefined;
getSignatureComment(declaration: ts.SignatureDeclaration | ts.JSDocSignature): import("../models/index").Comment | undefined;
withScope(scope: Reflection): Context;
}

197
node_modules/typedoc/dist/lib/converter/context.js generated vendored Normal file
View File

@@ -0,0 +1,197 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Context = void 0;
const assert_1 = require("assert");
const typescript_1 = __importDefault(require("typescript"));
const index_1 = require("../models/index");
const nodes_1 = require("./utils/nodes");
const converter_events_1 = require("./converter-events");
const symbols_1 = require("./utils/symbols");
const comments_1 = require("./comments");
const tsutils_1 = require("../utils/tsutils");
/**
* The context describes the current state the converter is in.
*/
class Context {
/**
* The TypeChecker instance returned by the TypeScript compiler.
*/
get checker() {
return this.program.getTypeChecker();
}
/**
* The program currently being converted.
* Accessing this property will throw if a source file is not currently being converted.
*/
get program() {
(0, assert_1.ok)(this._program, "Tried to access Context.program when not converting a source file");
return this._program;
}
/**
* Create a new Context instance.
*
* @param converter The converter instance that has created the context.
* @internal
*/
constructor(converter, programs, project, scope = project) {
this.convertingTypeNode = false; // Inherited by withScope
this.convertingClassOrInterface = false; // Not inherited
this.shouldBeStatic = false; // Not inherited
this.converter = converter;
this.programs = programs;
this.project = project;
this.scope = scope;
}
/** @internal */
get logger() {
return this.converter.application.logger;
}
/**
* Return the type declaration of the given node.
*
* @param node The TypeScript node whose type should be resolved.
* @returns The type declaration of the given node.
*/
getTypeAtLocation(node) {
let nodeType;
try {
nodeType = this.checker.getTypeAtLocation(node);
}
catch {
// ignore
}
if (!nodeType) {
if (node.symbol) {
nodeType = this.checker.getDeclaredTypeOfSymbol(node.symbol);
}
else if (node.parent?.symbol) {
nodeType = this.checker.getDeclaredTypeOfSymbol(node.parent.symbol);
}
else if (node.parent?.parent?.symbol) {
nodeType = this.checker.getDeclaredTypeOfSymbol(node.parent.parent.symbol);
}
}
return nodeType;
}
getSymbolAtLocation(node) {
let symbol = this.checker.getSymbolAtLocation(node);
if (!symbol && (0, nodes_1.isNamedNode)(node)) {
symbol = this.checker.getSymbolAtLocation(node.name);
}
return symbol;
}
expectSymbolAtLocation(node) {
const symbol = this.getSymbolAtLocation(node);
if (!symbol) {
const { line } = typescript_1.default.getLineAndCharacterOfPosition(node.getSourceFile(), node.pos);
throw new Error(`Expected a symbol for node with kind ${typescript_1.default.SyntaxKind[node.kind]} at ${node.getSourceFile().fileName}:${line + 1}`);
}
return symbol;
}
resolveAliasedSymbol(symbol) {
return (0, symbols_1.resolveAliasedSymbol)(symbol, this.checker);
}
createDeclarationReflection(kind, symbol, exportSymbol,
// We need this because modules don't always have symbols.
nameOverride) {
const name = (0, tsutils_1.getHumanName)(nameOverride ?? exportSymbol?.name ?? symbol?.name ?? "unknown");
if (this.convertingClassOrInterface) {
if (kind === index_1.ReflectionKind.Function) {
kind = index_1.ReflectionKind.Method;
}
if (kind === index_1.ReflectionKind.Variable) {
kind = index_1.ReflectionKind.Property;
}
}
const reflection = new index_1.DeclarationReflection(name, kind, this.scope);
this.postReflectionCreation(reflection, symbol, exportSymbol);
return reflection;
}
postReflectionCreation(reflection, symbol, exportSymbol) {
if (exportSymbol &&
reflection.kind &
(index_1.ReflectionKind.SomeModule | index_1.ReflectionKind.Reference)) {
reflection.comment = this.getComment(exportSymbol, reflection.kind);
}
if (symbol && !reflection.comment) {
reflection.comment = this.getComment(symbol, reflection.kind);
}
if (this.shouldBeStatic) {
reflection.setFlag(index_1.ReflectionFlag.Static);
}
if (reflection instanceof index_1.DeclarationReflection) {
reflection.escapedName = symbol?.escapedName;
this.addChild(reflection);
}
if (symbol && this.converter.isExternal(symbol)) {
reflection.setFlag(index_1.ReflectionFlag.External);
}
if (exportSymbol) {
this.registerReflection(reflection, exportSymbol);
}
this.registerReflection(reflection, symbol);
}
finalizeDeclarationReflection(reflection) {
this.converter.trigger(converter_events_1.ConverterEvents.CREATE_DECLARATION, this, reflection);
}
addChild(reflection) {
if (this.scope instanceof index_1.ContainerReflection) {
this.scope.children ??= [];
this.scope.children.push(reflection);
}
}
shouldIgnore(symbol) {
return this.converter.shouldIgnore(symbol);
}
/**
* Register a newly generated reflection. All created reflections should be
* passed to this method to ensure that the project helper functions work correctly.
*
* @param reflection The reflection that should be registered.
* @param symbol The symbol the given reflection was resolved from.
*/
registerReflection(reflection, symbol) {
this.project.registerReflection(reflection, symbol);
}
/**
* Trigger a node reflection event.
*
* All events are dispatched on the current converter instance.
*
* @param name The name of the event that should be triggered.
* @param reflection The triggering reflection.
* @param node The triggering TypeScript node if available.
*/
trigger(name, reflection, node) {
this.converter.trigger(name, this, reflection, node);
}
/** @internal */
setActiveProgram(program) {
this._program = program;
}
getComment(symbol, kind) {
return (0, comments_1.getComment)(symbol, kind, this.converter.config, this.logger, this.converter.commentStyle, this.converter.useTsLinkResolution ? this.checker : undefined);
}
getNodeComment(node, kind) {
return (0, comments_1.getNodeComment)(node, kind, this.converter.config, this.logger, this.converter.commentStyle, this.converter.useTsLinkResolution ? this.checker : undefined);
}
getFileComment(node) {
return (0, comments_1.getFileComment)(node, this.converter.config, this.logger, this.converter.commentStyle, this.converter.useTsLinkResolution ? this.checker : undefined);
}
getJsDocComment(declaration) {
return (0, comments_1.getJsDocComment)(declaration, this.converter.config, this.logger, this.converter.useTsLinkResolution ? this.checker : undefined);
}
getSignatureComment(declaration) {
return (0, comments_1.getSignatureComment)(declaration, this.converter.config, this.logger, this.converter.commentStyle, this.converter.useTsLinkResolution ? this.checker : undefined);
}
withScope(scope) {
const context = new Context(this.converter, this.programs, this.project, scope);
context.convertingTypeNode = this.convertingTypeNode;
context.setActiveProgram(this._program);
return context;
}
}
exports.Context = Context;

View File

@@ -0,0 +1,9 @@
import ts from "typescript";
/**
* Return the default value of the given node.
*
* @param node The TypeScript node whose default value should be extracted.
* @returns The default value as a string.
*/
export declare function convertDefaultValue(node: ts.Declaration | undefined): string | undefined;
export declare function convertExpression(expression: ts.Expression): string;

View File

@@ -0,0 +1,60 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertExpression = exports.convertDefaultValue = void 0;
const typescript_1 = __importDefault(require("typescript"));
/**
* Return the default value of the given node.
*
* @param node The TypeScript node whose default value should be extracted.
* @returns The default value as a string.
*/
function convertDefaultValue(node) {
const anyNode = node;
if (anyNode?.initializer) {
return convertExpression(anyNode.initializer);
}
else {
return undefined;
}
}
exports.convertDefaultValue = convertDefaultValue;
function convertExpression(expression) {
switch (expression.kind) {
case typescript_1.default.SyntaxKind.StringLiteral:
case typescript_1.default.SyntaxKind.TrueKeyword:
case typescript_1.default.SyntaxKind.FalseKeyword:
case typescript_1.default.SyntaxKind.NullKeyword:
case typescript_1.default.SyntaxKind.NumericLiteral:
case typescript_1.default.SyntaxKind.PrefixUnaryExpression:
case typescript_1.default.SyntaxKind.Identifier:
return expression.getText();
}
if (typescript_1.default.isArrayLiteralExpression(expression) &&
expression.elements.length === 0) {
return "[]";
}
if (typescript_1.default.isObjectLiteralExpression(expression) &&
expression.properties.length === 0) {
return "{}";
}
// a.b.c.d
if (typescript_1.default.isPropertyAccessExpression(expression)) {
const parts = [expression.name.getText()];
let iter = expression.expression;
while (typescript_1.default.isPropertyAccessExpression(iter)) {
parts.unshift(iter.name.getText());
iter = iter.expression;
}
if (typescript_1.default.isIdentifier(iter)) {
parts.unshift(iter.text);
return parts.join(".");
}
}
// More complex expressions are generally not useful in the documentation.
// Show that there was a value, but not specifics.
return "...";
}
exports.convertExpression = convertExpression;

View File

@@ -0,0 +1,11 @@
export declare const ConverterEvents: {
readonly BEGIN: "begin";
readonly END: "end";
readonly CREATE_DECLARATION: "createDeclaration";
readonly CREATE_SIGNATURE: "createSignature";
readonly CREATE_PARAMETER: "createParameter";
readonly CREATE_TYPE_PARAMETER: "createTypeParameter";
readonly RESOLVE_BEGIN: "resolveBegin";
readonly RESOLVE: "resolveReflection";
readonly RESOLVE_END: "resolveEnd";
};

View File

@@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConverterEvents = void 0;
exports.ConverterEvents = {
BEGIN: "begin",
END: "end",
CREATE_DECLARATION: "createDeclaration",
CREATE_SIGNATURE: "createSignature",
CREATE_PARAMETER: "createParameter",
CREATE_TYPE_PARAMETER: "createTypeParameter",
RESOLVE_BEGIN: "resolveBegin",
RESOLVE: "resolveReflection",
RESOLVE_END: "resolveEnd",
};

175
node_modules/typedoc/dist/lib/converter/converter.d.ts generated vendored Normal file
View File

@@ -0,0 +1,175 @@
import ts from "typescript";
import type { Application } from "../application";
import { Comment, CommentDisplayPart, ProjectReflection, Reflection, ReflectionSymbolId, SomeType } from "../models/index";
import { Context } from "./context";
import { ConverterComponent } from "./components";
import { ChildableComponent } from "../utils/component";
import { MinimalSourceFile } from "../utils";
import type { DocumentationEntryPoint } from "../utils/entry-point";
import type { CommentParserConfig } from "./comments";
import type { CommentStyle, ValidationOptions } from "../utils/options/declaration";
import { ExternalSymbolResolver, ExternalResolveResult } from "./comments/linkResolver";
import type { DeclarationReference } from "./comments/declarationReference";
/**
* Compiles source files using TypeScript and converts compiler symbols to reflections.
*/
export declare class Converter extends ChildableComponent<Application, ConverterComponent> {
/** @internal */
accessor externalPattern: string[];
private externalPatternCache?;
private excludeCache?;
/** @internal */
accessor excludeExternals: boolean;
/** @internal */
accessor excludeNotDocumented: boolean;
/** @internal */
accessor excludePrivate: boolean;
/** @internal */
accessor excludeProtected: boolean;
/** @internal */
accessor excludeReferences: boolean;
/** @internal */
accessor commentStyle: CommentStyle;
/** @internal */
accessor validation: ValidationOptions;
/** @internal */
accessor externalSymbolLinkMappings: Record<string, Record<string, string>>;
/** @internal */
accessor useTsLinkResolution: boolean;
/** @internal */
accessor preserveLinkText: boolean;
/** @internal */
accessor maxTypeConversionDepth: number;
private _config?;
private _externalSymbolResolvers;
get config(): CommentParserConfig;
/**
* General events
*/
/**
* Triggered when the converter begins converting a project.
* The listener will be given a {@link Context} object.
* @event
*/
static readonly EVENT_BEGIN: "begin";
/**
* Triggered when the converter has finished converting a project.
* The listener will be given a {@link Context} object.
* @event
*/
static readonly EVENT_END: "end";
/**
* Factory events
*/
/**
* Triggered when the converter has created a declaration reflection.
* The listener will be given {@link Context} and a {@link Models.DeclarationReflection}.
* @event
*/
static readonly EVENT_CREATE_DECLARATION: "createDeclaration";
/**
* Triggered when the converter has created a signature reflection.
* The listener will be given {@link Context}, {@link Models.SignatureReflection} | {@link Models.ProjectReflection} the declaration,
* `ts.SignatureDeclaration | ts.IndexSignatureDeclaration | ts.JSDocSignature | undefined`,
* and `ts.Signature | undefined`. The signature will be undefined if the created signature is an index signature.
* @event
*/
static readonly EVENT_CREATE_SIGNATURE: "createSignature";
/**
* Triggered when the converter has created a parameter reflection.
* The listener will be given {@link Context}, {@link Models.ParameterReflection} and a `ts.Node?`
* @event
*/
static readonly EVENT_CREATE_PARAMETER: "createParameter";
/**
* Triggered when the converter has created a type parameter reflection.
* The listener will be given {@link Context} and a {@link Models.TypeParameterReflection}
* @event
*/
static readonly EVENT_CREATE_TYPE_PARAMETER: "createTypeParameter";
/**
* Resolve events
*/
/**
* Triggered when the converter begins resolving a project.
* The listener will be given {@link Context}.
* @event
*/
static readonly EVENT_RESOLVE_BEGIN: "resolveBegin";
/**
* Triggered when the converter resolves a reflection.
* The listener will be given {@link Context} and a {@link Reflection}.
* @event
*/
static readonly EVENT_RESOLVE: "resolveReflection";
/**
* Triggered when the converter has finished resolving a project.
* The listener will be given {@link Context}.
* @event
*/
static readonly EVENT_RESOLVE_END: "resolveEnd";
constructor(owner: Application);
/**
* Compile the given source files and create a project reflection for them.
*/
convert(entryPoints: readonly DocumentationEntryPoint[]): ProjectReflection;
/** @internal */
convertSymbol(context: Context, symbol: ts.Symbol, exportSymbol?: ts.Symbol): void;
/**
* Convert the given TypeScript type into its TypeDoc type reflection.
*
* @param context The context object describing the current state the converter is in.
* @returns The TypeDoc type reflection representing the given node and type.
* @internal
*/
convertType(context: Context, node: ts.TypeNode | ts.Type | undefined): SomeType;
/**
* Parse the given file into a comment. Intended to be used with markdown files.
*/
parseRawComment(file: MinimalSourceFile): Comment;
/**
* Adds a new resolver that the theme can use to try to figure out how to link to a symbol declared
* by a third-party library which is not included in the documentation.
*
* The resolver function will be passed a declaration reference which it can attempt to resolve. If
* resolution fails, the function should return undefined.
*
* Note: This will be used for both references to types declared in node_modules (in which case the
* reference passed will have the `moduleSource` set and the `symbolReference` will navigate via `.`)
* and user defined \{\@link\} tags which cannot be resolved. If the link being resolved is inferred
* from a type, then no `part` will be passed to the resolver function.
* @since 0.22.14
*/
addUnknownSymbolResolver(resolver: ExternalSymbolResolver): void;
/** @internal */
resolveExternalLink(ref: DeclarationReference, refl: Reflection, part: CommentDisplayPart | undefined, symbolId: ReflectionSymbolId | undefined): ExternalResolveResult | string | undefined;
resolveLinks(comment: Comment, owner: Reflection): void;
resolveLinks(parts: readonly CommentDisplayPart[], owner: Reflection): CommentDisplayPart[];
/**
* Compile the files within the given context and convert the compiler symbols to reflections.
*
* @param context The context object describing the current state the converter is in.
* @returns An array containing all errors generated by the TypeScript compiler.
*/
private compile;
private convertExports;
private convertReExports;
/**
* Resolve the project within the given context.
*
* @param context The context object describing the current state the converter is in.
* @returns The final project reflection.
*/
private resolve;
/**
* Used to determine if we should immediately bail when creating a reflection.
* Note: This should not be used for excludeNotDocumented because we don't have enough
* information at this point since comment discovery hasn't happened.
* @internal
*/
shouldIgnore(symbol: ts.Symbol): boolean;
private isExcluded;
/** @internal */
isExternal(symbol: ts.Symbol): boolean;
private _buildCommentParserConfig;
}

582
node_modules/typedoc/dist/lib/converter/converter.js generated vendored Normal file
View File

@@ -0,0 +1,582 @@
"use strict";
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
var _, done = false;
for (var i = decorators.length - 1; i >= 0; i--) {
var context = {};
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
if (kind === "accessor") {
if (result === void 0) continue;
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
if (_ = accept(result.get)) descriptor.get = _;
if (_ = accept(result.set)) descriptor.set = _;
if (_ = accept(result.init)) initializers.unshift(_);
}
else if (_ = accept(result)) {
if (kind === "field") initializers.unshift(_);
else descriptor[key] = _;
}
}
if (target) Object.defineProperty(target, contextIn.name, descriptor);
done = true;
};
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
var useValue = arguments.length > 2;
for (var i = 0; i < initializers.length; i++) {
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
}
return useValue ? value : void 0;
};
var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Converter = void 0;
const typescript_1 = __importDefault(require("typescript"));
const index_1 = require("../models/index");
const context_1 = require("./context");
const components_1 = require("./components");
const component_1 = require("../utils/component");
const utils_1 = require("../utils");
const types_1 = require("./types");
const converter_events_1 = require("./converter-events");
const symbols_1 = require("./symbols");
const paths_1 = require("../utils/paths");
const enum_1 = require("../utils/enum");
const parser_1 = require("./comments/parser");
const rawLexer_1 = require("./comments/rawLexer");
const linkResolver_1 = require("./comments/linkResolver");
/**
* Compiles source files using TypeScript and converts compiler symbols to reflections.
*/
let Converter = (() => {
var _Converter_externalPattern_accessor_storage, _Converter_excludeExternals_accessor_storage, _Converter_excludeNotDocumented_accessor_storage, _Converter_excludePrivate_accessor_storage, _Converter_excludeProtected_accessor_storage, _Converter_excludeReferences_accessor_storage, _Converter_commentStyle_accessor_storage, _Converter_validation_accessor_storage, _Converter_externalSymbolLinkMappings_accessor_storage, _Converter_useTsLinkResolution_accessor_storage, _Converter_preserveLinkText_accessor_storage, _Converter_maxTypeConversionDepth_accessor_storage;
let _classDecorators = [(0, component_1.Component)({
name: "converter",
internal: true,
childClass: components_1.ConverterComponent,
})];
let _classDescriptor;
let _classExtraInitializers = [];
let _classThis;
let _classSuper = component_1.ChildableComponent;
let _externalPattern_decorators;
let _externalPattern_initializers = [];
let _externalPattern_extraInitializers = [];
let _excludeExternals_decorators;
let _excludeExternals_initializers = [];
let _excludeExternals_extraInitializers = [];
let _excludeNotDocumented_decorators;
let _excludeNotDocumented_initializers = [];
let _excludeNotDocumented_extraInitializers = [];
let _excludePrivate_decorators;
let _excludePrivate_initializers = [];
let _excludePrivate_extraInitializers = [];
let _excludeProtected_decorators;
let _excludeProtected_initializers = [];
let _excludeProtected_extraInitializers = [];
let _excludeReferences_decorators;
let _excludeReferences_initializers = [];
let _excludeReferences_extraInitializers = [];
let _commentStyle_decorators;
let _commentStyle_initializers = [];
let _commentStyle_extraInitializers = [];
let _validation_decorators;
let _validation_initializers = [];
let _validation_extraInitializers = [];
let _externalSymbolLinkMappings_decorators;
let _externalSymbolLinkMappings_initializers = [];
let _externalSymbolLinkMappings_extraInitializers = [];
let _useTsLinkResolution_decorators;
let _useTsLinkResolution_initializers = [];
let _useTsLinkResolution_extraInitializers = [];
let _preserveLinkText_decorators;
let _preserveLinkText_initializers = [];
let _preserveLinkText_extraInitializers = [];
let _maxTypeConversionDepth_decorators;
let _maxTypeConversionDepth_initializers = [];
let _maxTypeConversionDepth_extraInitializers = [];
var Converter = _classThis = class extends _classSuper {
/** @internal */
get externalPattern() { return __classPrivateFieldGet(this, _Converter_externalPattern_accessor_storage, "f"); }
set externalPattern(value) { __classPrivateFieldSet(this, _Converter_externalPattern_accessor_storage, value, "f"); }
/** @internal */
get excludeExternals() { return __classPrivateFieldGet(this, _Converter_excludeExternals_accessor_storage, "f"); }
set excludeExternals(value) { __classPrivateFieldSet(this, _Converter_excludeExternals_accessor_storage, value, "f"); }
/** @internal */
get excludeNotDocumented() { return __classPrivateFieldGet(this, _Converter_excludeNotDocumented_accessor_storage, "f"); }
set excludeNotDocumented(value) { __classPrivateFieldSet(this, _Converter_excludeNotDocumented_accessor_storage, value, "f"); }
/** @internal */
get excludePrivate() { return __classPrivateFieldGet(this, _Converter_excludePrivate_accessor_storage, "f"); }
set excludePrivate(value) { __classPrivateFieldSet(this, _Converter_excludePrivate_accessor_storage, value, "f"); }
/** @internal */
get excludeProtected() { return __classPrivateFieldGet(this, _Converter_excludeProtected_accessor_storage, "f"); }
set excludeProtected(value) { __classPrivateFieldSet(this, _Converter_excludeProtected_accessor_storage, value, "f"); }
/** @internal */
get excludeReferences() { return __classPrivateFieldGet(this, _Converter_excludeReferences_accessor_storage, "f"); }
set excludeReferences(value) { __classPrivateFieldSet(this, _Converter_excludeReferences_accessor_storage, value, "f"); }
/** @internal */
get commentStyle() { return __classPrivateFieldGet(this, _Converter_commentStyle_accessor_storage, "f"); }
set commentStyle(value) { __classPrivateFieldSet(this, _Converter_commentStyle_accessor_storage, value, "f"); }
/** @internal */
get validation() { return __classPrivateFieldGet(this, _Converter_validation_accessor_storage, "f"); }
set validation(value) { __classPrivateFieldSet(this, _Converter_validation_accessor_storage, value, "f"); }
/** @internal */
get externalSymbolLinkMappings() { return __classPrivateFieldGet(this, _Converter_externalSymbolLinkMappings_accessor_storage, "f"); }
set externalSymbolLinkMappings(value) { __classPrivateFieldSet(this, _Converter_externalSymbolLinkMappings_accessor_storage, value, "f"); }
/** @internal */
get useTsLinkResolution() { return __classPrivateFieldGet(this, _Converter_useTsLinkResolution_accessor_storage, "f"); }
set useTsLinkResolution(value) { __classPrivateFieldSet(this, _Converter_useTsLinkResolution_accessor_storage, value, "f"); }
/** @internal */
get preserveLinkText() { return __classPrivateFieldGet(this, _Converter_preserveLinkText_accessor_storage, "f"); }
set preserveLinkText(value) { __classPrivateFieldSet(this, _Converter_preserveLinkText_accessor_storage, value, "f"); }
/** @internal */
get maxTypeConversionDepth() { return __classPrivateFieldGet(this, _Converter_maxTypeConversionDepth_accessor_storage, "f"); }
set maxTypeConversionDepth(value) { __classPrivateFieldSet(this, _Converter_maxTypeConversionDepth_accessor_storage, value, "f"); }
get config() {
return this._config || this._buildCommentParserConfig();
}
constructor(owner) {
super(owner);
_Converter_externalPattern_accessor_storage.set(this, __runInitializers(this, _externalPattern_initializers, void 0));
this.externalPatternCache = __runInitializers(this, _externalPattern_extraInitializers);
_Converter_excludeExternals_accessor_storage.set(this, __runInitializers(this, _excludeExternals_initializers, void 0));
_Converter_excludeNotDocumented_accessor_storage.set(this, (__runInitializers(this, _excludeExternals_extraInitializers), __runInitializers(this, _excludeNotDocumented_initializers, void 0)));
_Converter_excludePrivate_accessor_storage.set(this, (__runInitializers(this, _excludeNotDocumented_extraInitializers), __runInitializers(this, _excludePrivate_initializers, void 0)));
_Converter_excludeProtected_accessor_storage.set(this, (__runInitializers(this, _excludePrivate_extraInitializers), __runInitializers(this, _excludeProtected_initializers, void 0)));
_Converter_excludeReferences_accessor_storage.set(this, (__runInitializers(this, _excludeProtected_extraInitializers), __runInitializers(this, _excludeReferences_initializers, void 0)));
_Converter_commentStyle_accessor_storage.set(this, (__runInitializers(this, _excludeReferences_extraInitializers), __runInitializers(this, _commentStyle_initializers, void 0)));
_Converter_validation_accessor_storage.set(this, (__runInitializers(this, _commentStyle_extraInitializers), __runInitializers(this, _validation_initializers, void 0)));
_Converter_externalSymbolLinkMappings_accessor_storage.set(this, (__runInitializers(this, _validation_extraInitializers), __runInitializers(this, _externalSymbolLinkMappings_initializers, void 0)));
_Converter_useTsLinkResolution_accessor_storage.set(this, (__runInitializers(this, _externalSymbolLinkMappings_extraInitializers), __runInitializers(this, _useTsLinkResolution_initializers, void 0)));
_Converter_preserveLinkText_accessor_storage.set(this, (__runInitializers(this, _useTsLinkResolution_extraInitializers), __runInitializers(this, _preserveLinkText_initializers, void 0)));
_Converter_maxTypeConversionDepth_accessor_storage.set(this, (__runInitializers(this, _preserveLinkText_extraInitializers), __runInitializers(this, _maxTypeConversionDepth_initializers, void 0)));
this._config = __runInitializers(this, _maxTypeConversionDepth_extraInitializers);
this._externalSymbolResolvers = [];
this.addUnknownSymbolResolver((ref) => {
// Require global links, matching local ones will likely hide mistakes where the
// user meant to link to a local type.
if (ref.resolutionStart !== "global" || !ref.symbolReference) {
return;
}
const modLinks = this.externalSymbolLinkMappings[ref.moduleSource ?? "global"];
if (typeof modLinks !== "object") {
return;
}
let name = "";
if (ref.symbolReference.path) {
name += ref.symbolReference.path.map((p) => p.path).join(".");
}
if (ref.symbolReference.meaning) {
name += ":" + ref.symbolReference.meaning;
}
if (typeof modLinks[name] === "string") {
return modLinks[name];
}
if (typeof modLinks["*"] === "string") {
return modLinks["*"];
}
});
}
/**
* Compile the given source files and create a project reflection for them.
*/
convert(entryPoints) {
const programs = (0, utils_1.unique)(entryPoints.map((e) => e.program));
this.externalPatternCache = void 0;
const project = new index_1.ProjectReflection(this.application.options.getValue("name"));
const context = new context_1.Context(this, programs, project);
this.trigger(Converter.EVENT_BEGIN, context);
this.compile(entryPoints, context);
this.resolve(context);
this.trigger(Converter.EVENT_END, context);
this._config = undefined;
return project;
}
/** @internal */
convertSymbol(context, symbol, exportSymbol) {
(0, symbols_1.convertSymbol)(context, symbol, exportSymbol);
}
/**
* Convert the given TypeScript type into its TypeDoc type reflection.
*
* @param context The context object describing the current state the converter is in.
* @returns The TypeDoc type reflection representing the given node and type.
* @internal
*/
convertType(context, node) {
return (0, types_1.convertType)(context, node);
}
/**
* Parse the given file into a comment. Intended to be used with markdown files.
*/
parseRawComment(file) {
return (0, parser_1.parseComment)((0, rawLexer_1.lexCommentString)(file.text), this.config, file, this.application.logger);
}
/**
* Adds a new resolver that the theme can use to try to figure out how to link to a symbol declared
* by a third-party library which is not included in the documentation.
*
* The resolver function will be passed a declaration reference which it can attempt to resolve. If
* resolution fails, the function should return undefined.
*
* Note: This will be used for both references to types declared in node_modules (in which case the
* reference passed will have the `moduleSource` set and the `symbolReference` will navigate via `.`)
* and user defined \{\@link\} tags which cannot be resolved. If the link being resolved is inferred
* from a type, then no `part` will be passed to the resolver function.
* @since 0.22.14
*/
addUnknownSymbolResolver(resolver) {
this._externalSymbolResolvers.push(resolver);
}
/** @internal */
resolveExternalLink(ref, refl, part, symbolId) {
for (const resolver of this._externalSymbolResolvers) {
const resolved = resolver(ref, refl, part, symbolId);
if (resolved)
return resolved;
}
}
resolveLinks(comment, owner) {
if (comment instanceof index_1.Comment) {
(0, linkResolver_1.resolveLinks)(comment, owner, (ref, part, refl, id) => this.resolveExternalLink(ref, part, refl, id), { preserveLinkText: this.preserveLinkText });
}
else {
return (0, linkResolver_1.resolvePartLinks)(owner, comment, (ref, part, refl, id) => this.resolveExternalLink(ref, part, refl, id), { preserveLinkText: this.preserveLinkText });
}
}
/**
* Compile the files within the given context and convert the compiler symbols to reflections.
*
* @param context The context object describing the current state the converter is in.
* @returns An array containing all errors generated by the TypeScript compiler.
*/
compile(entryPoints, context) {
const entries = entryPoints.map((e) => {
return {
entryPoint: e,
context: undefined,
};
});
entries.forEach((e) => {
context.setActiveProgram(e.entryPoint.program);
e.context = this.convertExports(context, e.entryPoint, entries.length === 1);
});
for (const { entryPoint, context } of entries) {
// active program is already set on context
// if we don't have a context, then this entry point is being ignored
if (context) {
this.convertReExports(context, entryPoint.sourceFile);
}
}
context.setActiveProgram(undefined);
}
convertExports(context, entryPoint, singleEntryPoint) {
const node = entryPoint.sourceFile;
const entryName = entryPoint.displayName;
const symbol = getSymbolForModuleLike(context, node);
let moduleContext;
if (singleEntryPoint) {
// Special case for when we're giving a single entry point, we don't need to
// create modules for each entry. Register the project as this module.
context.project.registerReflection(context.project, symbol);
context.project.comment = symbol
? context.getComment(symbol, context.project.kind)
: context.getFileComment(node);
context.trigger(Converter.EVENT_CREATE_DECLARATION, context.project);
moduleContext = context;
}
else {
const reflection = context.createDeclarationReflection(index_1.ReflectionKind.Module, symbol, void 0, entryName);
if (!reflection.comment && !symbol) {
reflection.comment = context.getFileComment(node);
}
if (entryPoint.readmeFile) {
const readme = (0, utils_1.readFile)(entryPoint.readmeFile);
const comment = this.parseRawComment(new utils_1.MinimalSourceFile(readme, entryPoint.readmeFile));
if (comment.blockTags.length || comment.modifierTags.size) {
const ignored = [
...comment.blockTags.map((tag) => tag.tag),
...comment.modifierTags,
];
context.logger.warn(`Block and modifier tags will be ignored within the readme:\n\t${ignored.join("\n\t")}`);
}
reflection.readme = comment.summary;
}
reflection.packageVersion = entryPoint.version;
context.finalizeDeclarationReflection(reflection);
moduleContext = context.withScope(reflection);
}
const allExports = getExports(context, node, symbol);
for (const exp of allExports.filter((exp) => isDirectExport(context.resolveAliasedSymbol(exp), node))) {
this.convertSymbol(moduleContext, exp);
}
return moduleContext;
}
convertReExports(moduleContext, node) {
for (const exp of getExports(moduleContext, node, moduleContext.project.getSymbolFromReflection(moduleContext.scope)).filter((exp) => !isDirectExport(moduleContext.resolveAliasedSymbol(exp), node))) {
this.convertSymbol(moduleContext, exp);
}
}
/**
* Resolve the project within the given context.
*
* @param context The context object describing the current state the converter is in.
* @returns The final project reflection.
*/
resolve(context) {
this.trigger(Converter.EVENT_RESOLVE_BEGIN, context);
const project = context.project;
for (const id in project.reflections) {
this.trigger(Converter.EVENT_RESOLVE, context, project.reflections[id]);
}
this.trigger(Converter.EVENT_RESOLVE_END, context);
}
/**
* Used to determine if we should immediately bail when creating a reflection.
* Note: This should not be used for excludeNotDocumented because we don't have enough
* information at this point since comment discovery hasn't happened.
* @internal
*/
shouldIgnore(symbol) {
if (this.isExcluded(symbol)) {
return true;
}
return this.excludeExternals && this.isExternal(symbol);
}
isExcluded(symbol) {
this.excludeCache ??= (0, paths_1.createMinimatch)(this.application.options.getValue("exclude"));
const cache = this.excludeCache;
return (symbol.getDeclarations() ?? []).some((node) => (0, paths_1.matchesAny)(cache, node.getSourceFile().fileName));
}
/** @internal */
isExternal(symbol) {
this.externalPatternCache ??= (0, paths_1.createMinimatch)(this.externalPattern);
const cache = this.externalPatternCache;
return (symbol.getDeclarations() ?? []).some((node) => (0, paths_1.matchesAny)(cache, node.getSourceFile().fileName));
}
_buildCommentParserConfig() {
this._config = {
blockTags: new Set(this.application.options.getValue("blockTags")),
inlineTags: new Set(this.application.options.getValue("inlineTags")),
modifierTags: new Set(this.application.options.getValue("modifierTags")),
jsDocCompatibility: this.application.options.getValue("jsDocCompatibility"),
};
return this._config;
}
};
_Converter_externalPattern_accessor_storage = new WeakMap();
_Converter_excludeExternals_accessor_storage = new WeakMap();
_Converter_excludeNotDocumented_accessor_storage = new WeakMap();
_Converter_excludePrivate_accessor_storage = new WeakMap();
_Converter_excludeProtected_accessor_storage = new WeakMap();
_Converter_excludeReferences_accessor_storage = new WeakMap();
_Converter_commentStyle_accessor_storage = new WeakMap();
_Converter_validation_accessor_storage = new WeakMap();
_Converter_externalSymbolLinkMappings_accessor_storage = new WeakMap();
_Converter_useTsLinkResolution_accessor_storage = new WeakMap();
_Converter_preserveLinkText_accessor_storage = new WeakMap();
_Converter_maxTypeConversionDepth_accessor_storage = new WeakMap();
__setFunctionName(_classThis, "Converter");
(() => {
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
_externalPattern_decorators = [(0, utils_1.Option)("externalPattern")];
_excludeExternals_decorators = [(0, utils_1.Option)("excludeExternals")];
_excludeNotDocumented_decorators = [(0, utils_1.Option)("excludeNotDocumented")];
_excludePrivate_decorators = [(0, utils_1.Option)("excludePrivate")];
_excludeProtected_decorators = [(0, utils_1.Option)("excludeProtected")];
_excludeReferences_decorators = [(0, utils_1.Option)("excludeReferences")];
_commentStyle_decorators = [(0, utils_1.Option)("commentStyle")];
_validation_decorators = [(0, utils_1.Option)("validation")];
_externalSymbolLinkMappings_decorators = [(0, utils_1.Option)("externalSymbolLinkMappings")];
_useTsLinkResolution_decorators = [(0, utils_1.Option)("useTsLinkResolution")];
_preserveLinkText_decorators = [(0, utils_1.Option)("preserveLinkText")];
_maxTypeConversionDepth_decorators = [(0, utils_1.Option)("maxTypeConversionDepth")];
__esDecorate(_classThis, null, _externalPattern_decorators, { kind: "accessor", name: "externalPattern", static: false, private: false, access: { has: obj => "externalPattern" in obj, get: obj => obj.externalPattern, set: (obj, value) => { obj.externalPattern = value; } }, metadata: _metadata }, _externalPattern_initializers, _externalPattern_extraInitializers);
__esDecorate(_classThis, null, _excludeExternals_decorators, { kind: "accessor", name: "excludeExternals", static: false, private: false, access: { has: obj => "excludeExternals" in obj, get: obj => obj.excludeExternals, set: (obj, value) => { obj.excludeExternals = value; } }, metadata: _metadata }, _excludeExternals_initializers, _excludeExternals_extraInitializers);
__esDecorate(_classThis, null, _excludeNotDocumented_decorators, { kind: "accessor", name: "excludeNotDocumented", static: false, private: false, access: { has: obj => "excludeNotDocumented" in obj, get: obj => obj.excludeNotDocumented, set: (obj, value) => { obj.excludeNotDocumented = value; } }, metadata: _metadata }, _excludeNotDocumented_initializers, _excludeNotDocumented_extraInitializers);
__esDecorate(_classThis, null, _excludePrivate_decorators, { kind: "accessor", name: "excludePrivate", static: false, private: false, access: { has: obj => "excludePrivate" in obj, get: obj => obj.excludePrivate, set: (obj, value) => { obj.excludePrivate = value; } }, metadata: _metadata }, _excludePrivate_initializers, _excludePrivate_extraInitializers);
__esDecorate(_classThis, null, _excludeProtected_decorators, { kind: "accessor", name: "excludeProtected", static: false, private: false, access: { has: obj => "excludeProtected" in obj, get: obj => obj.excludeProtected, set: (obj, value) => { obj.excludeProtected = value; } }, metadata: _metadata }, _excludeProtected_initializers, _excludeProtected_extraInitializers);
__esDecorate(_classThis, null, _excludeReferences_decorators, { kind: "accessor", name: "excludeReferences", static: false, private: false, access: { has: obj => "excludeReferences" in obj, get: obj => obj.excludeReferences, set: (obj, value) => { obj.excludeReferences = value; } }, metadata: _metadata }, _excludeReferences_initializers, _excludeReferences_extraInitializers);
__esDecorate(_classThis, null, _commentStyle_decorators, { kind: "accessor", name: "commentStyle", static: false, private: false, access: { has: obj => "commentStyle" in obj, get: obj => obj.commentStyle, set: (obj, value) => { obj.commentStyle = value; } }, metadata: _metadata }, _commentStyle_initializers, _commentStyle_extraInitializers);
__esDecorate(_classThis, null, _validation_decorators, { kind: "accessor", name: "validation", static: false, private: false, access: { has: obj => "validation" in obj, get: obj => obj.validation, set: (obj, value) => { obj.validation = value; } }, metadata: _metadata }, _validation_initializers, _validation_extraInitializers);
__esDecorate(_classThis, null, _externalSymbolLinkMappings_decorators, { kind: "accessor", name: "externalSymbolLinkMappings", static: false, private: false, access: { has: obj => "externalSymbolLinkMappings" in obj, get: obj => obj.externalSymbolLinkMappings, set: (obj, value) => { obj.externalSymbolLinkMappings = value; } }, metadata: _metadata }, _externalSymbolLinkMappings_initializers, _externalSymbolLinkMappings_extraInitializers);
__esDecorate(_classThis, null, _useTsLinkResolution_decorators, { kind: "accessor", name: "useTsLinkResolution", static: false, private: false, access: { has: obj => "useTsLinkResolution" in obj, get: obj => obj.useTsLinkResolution, set: (obj, value) => { obj.useTsLinkResolution = value; } }, metadata: _metadata }, _useTsLinkResolution_initializers, _useTsLinkResolution_extraInitializers);
__esDecorate(_classThis, null, _preserveLinkText_decorators, { kind: "accessor", name: "preserveLinkText", static: false, private: false, access: { has: obj => "preserveLinkText" in obj, get: obj => obj.preserveLinkText, set: (obj, value) => { obj.preserveLinkText = value; } }, metadata: _metadata }, _preserveLinkText_initializers, _preserveLinkText_extraInitializers);
__esDecorate(_classThis, null, _maxTypeConversionDepth_decorators, { kind: "accessor", name: "maxTypeConversionDepth", static: false, private: false, access: { has: obj => "maxTypeConversionDepth" in obj, get: obj => obj.maxTypeConversionDepth, set: (obj, value) => { obj.maxTypeConversionDepth = value; } }, metadata: _metadata }, _maxTypeConversionDepth_initializers, _maxTypeConversionDepth_extraInitializers);
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
Converter = _classThis = _classDescriptor.value;
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
})();
/**
* General events
*/
/**
* Triggered when the converter begins converting a project.
* The listener will be given a {@link Context} object.
* @event
*/
_classThis.EVENT_BEGIN = converter_events_1.ConverterEvents.BEGIN;
/**
* Triggered when the converter has finished converting a project.
* The listener will be given a {@link Context} object.
* @event
*/
_classThis.EVENT_END = converter_events_1.ConverterEvents.END;
/**
* Factory events
*/
/**
* Triggered when the converter has created a declaration reflection.
* The listener will be given {@link Context} and a {@link Models.DeclarationReflection}.
* @event
*/
_classThis.EVENT_CREATE_DECLARATION = converter_events_1.ConverterEvents.CREATE_DECLARATION;
/**
* Triggered when the converter has created a signature reflection.
* The listener will be given {@link Context}, {@link Models.SignatureReflection} | {@link Models.ProjectReflection} the declaration,
* `ts.SignatureDeclaration | ts.IndexSignatureDeclaration | ts.JSDocSignature | undefined`,
* and `ts.Signature | undefined`. The signature will be undefined if the created signature is an index signature.
* @event
*/
_classThis.EVENT_CREATE_SIGNATURE = converter_events_1.ConverterEvents.CREATE_SIGNATURE;
/**
* Triggered when the converter has created a parameter reflection.
* The listener will be given {@link Context}, {@link Models.ParameterReflection} and a `ts.Node?`
* @event
*/
_classThis.EVENT_CREATE_PARAMETER = converter_events_1.ConverterEvents.CREATE_PARAMETER;
/**
* Triggered when the converter has created a type parameter reflection.
* The listener will be given {@link Context} and a {@link Models.TypeParameterReflection}
* @event
*/
_classThis.EVENT_CREATE_TYPE_PARAMETER = converter_events_1.ConverterEvents.CREATE_TYPE_PARAMETER;
/**
* Resolve events
*/
/**
* Triggered when the converter begins resolving a project.
* The listener will be given {@link Context}.
* @event
*/
_classThis.EVENT_RESOLVE_BEGIN = converter_events_1.ConverterEvents.RESOLVE_BEGIN;
/**
* Triggered when the converter resolves a reflection.
* The listener will be given {@link Context} and a {@link Reflection}.
* @event
*/
_classThis.EVENT_RESOLVE = converter_events_1.ConverterEvents.RESOLVE;
/**
* Triggered when the converter has finished resolving a project.
* The listener will be given {@link Context}.
* @event
*/
_classThis.EVENT_RESOLVE_END = converter_events_1.ConverterEvents.RESOLVE_END;
(() => {
__runInitializers(_classThis, _classExtraInitializers);
})();
return Converter = _classThis;
})();
exports.Converter = Converter;
function getSymbolForModuleLike(context, node) {
const symbol = context.checker.getSymbolAtLocation(node) ?? node.symbol;
if (symbol) {
return symbol;
}
// This is a global file, get all symbols declared in this file...
// this isn't the best solution, it would be nice to have all globals given to a special
// "globals" file, but this is uncommon enough that I'm skipping it for now.
const sourceFile = node.getSourceFile();
const globalSymbols = context.checker
.getSymbolsInScope(node, typescript_1.default.SymbolFlags.ModuleMember)
.filter((s) => s
.getDeclarations()
?.some((d) => d.getSourceFile() === sourceFile));
// Detect declaration files with declare module "foo" as their only export
// and lift that up one level as the source file symbol
if (globalSymbols.length === 1 &&
globalSymbols[0]
.getDeclarations()
?.every((declaration) => typescript_1.default.isModuleDeclaration(declaration) &&
typescript_1.default.isStringLiteral(declaration.name))) {
return globalSymbols[0];
}
}
function getExports(context, node, symbol) {
let result;
// The generated docs aren't great, but you really ought not be using
// this in the first place... so it's better than nothing.
const exportEq = symbol?.exports?.get("export=");
if (exportEq) {
// JS users might also have exported types here.
// We need to filter for types because otherwise static methods can show up as both
// members of the export= class and as functions if a class is directly exported.
result = [exportEq].concat(context.checker
.getExportsOfModule(symbol)
.filter((s) => !(0, enum_1.hasAnyFlag)(s.flags, typescript_1.default.SymbolFlags.Prototype | typescript_1.default.SymbolFlags.Value)));
}
else if (symbol) {
result = context.checker
.getExportsOfModule(symbol)
.filter((s) => !(0, enum_1.hasAllFlags)(s.flags, typescript_1.default.SymbolFlags.Prototype));
if (result.length === 0) {
const globalDecl = node.statements.find((s) => typescript_1.default.isModuleDeclaration(s) &&
s.flags & typescript_1.default.NodeFlags.GlobalAugmentation);
if (globalDecl) {
const globalSymbol = context.getSymbolAtLocation(globalDecl);
if (globalSymbol) {
result = context.checker
.getExportsOfModule(globalSymbol)
.filter((exp) => exp.declarations?.some((d) => d.getSourceFile() === node));
}
}
}
}
else {
// Global file with no inferred top level symbol, get all symbols declared in this file.
const sourceFile = node.getSourceFile();
result = context.checker
.getSymbolsInScope(node, typescript_1.default.SymbolFlags.ModuleMember)
.filter((s) => s
.getDeclarations()
?.some((d) => d.getSourceFile() === sourceFile));
}
// Put symbols named "default" last, #1795
result.sort((a, b) => {
if (a.name === "default") {
return 1;
}
else if (b.name === "default") {
return -1;
}
return 0;
});
return result;
}
function isDirectExport(symbol, file) {
return (symbol
.getDeclarations()
?.every((decl) => decl.getSourceFile() === file) ?? false);
}

View File

@@ -0,0 +1,3 @@
import ts from "typescript";
import type { Context } from "../context";
export declare function convertIndexSignature(context: Context, symbol: ts.Symbol): void;

View File

@@ -0,0 +1,35 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertIndexSignature = void 0;
const assert_1 = __importDefault(require("assert"));
const typescript_1 = __importDefault(require("typescript"));
const models_1 = require("../../models");
const converter_events_1 = require("../converter-events");
function convertIndexSignature(context, symbol) {
(0, assert_1.default)(context.scope instanceof models_1.DeclarationReflection);
const indexSymbol = symbol.members?.get("__index");
if (indexSymbol) {
// Right now TypeDoc models don't have a way to distinguish between string
// and number index signatures... { [x: string]: 1 | 2; [x: number]: 2 }
// will be misrepresented.
const indexDeclaration = indexSymbol.getDeclarations()?.[0];
(0, assert_1.default)(indexDeclaration &&
typescript_1.default.isIndexSignatureDeclaration(indexDeclaration));
const param = indexDeclaration.parameters[0];
(0, assert_1.default)(param && typescript_1.default.isParameter(param));
const index = new models_1.SignatureReflection("__index", models_1.ReflectionKind.IndexSignature, context.scope);
index.comment = context.getComment(indexSymbol, index.kind);
index.parameters = [
new models_1.ParameterReflection(param.name.getText(), models_1.ReflectionKind.Parameter, index),
];
index.parameters[0].type = context.converter.convertType(context.withScope(index.parameters[0]), param.type);
index.type = context.converter.convertType(context.withScope(index), indexDeclaration.type);
context.registerReflection(index, indexSymbol);
context.scope.indexSignature = index;
context.trigger(converter_events_1.ConverterEvents.CREATE_SIGNATURE, index, indexDeclaration);
}
}
exports.convertIndexSignature = convertIndexSignature;

View File

@@ -0,0 +1,12 @@
import ts from "typescript";
import { ParameterReflection, Reflection, ReflectionKind, SignatureReflection, TypeParameterReflection } from "../../models";
import type { Context } from "../context";
export declare function createSignature(context: Context, kind: ReflectionKind.CallSignature | ReflectionKind.ConstructorSignature | ReflectionKind.GetSignature | ReflectionKind.SetSignature, signature: ts.Signature, symbol: ts.Symbol | undefined, declaration?: ts.SignatureDeclaration | ts.JSDocSignature): void;
/**
* Special cased constructor factory for functions tagged with `@class`
*/
export declare function createConstructSignatureWithType(context: Context, signature: ts.Signature, classType: Reflection): void;
export declare function convertParameterNodes(context: Context, sigRef: SignatureReflection, parameters: readonly (ts.JSDocParameterTag | ts.ParameterDeclaration)[]): ParameterReflection[];
export declare function convertTypeParameterNodes(context: Context, parameters: readonly ts.TypeParameterDeclaration[] | undefined): TypeParameterReflection[] | undefined;
export declare function createTypeParamReflection(param: ts.TypeParameterDeclaration, context: Context): TypeParameterReflection;
export declare function convertTemplateParameterNodes(context: Context, nodes: readonly ts.JSDocTemplateTag[] | undefined): TypeParameterReflection[] | undefined;

View File

@@ -0,0 +1,314 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertTemplateParameterNodes = exports.createTypeParamReflection = exports.convertTypeParameterNodes = exports.convertParameterNodes = exports.createConstructSignatureWithType = exports.createSignature = void 0;
const typescript_1 = __importDefault(require("typescript"));
const assert_1 = __importDefault(require("assert"));
const models_1 = require("../../models");
const converter_events_1 = require("../converter-events");
const convert_expression_1 = require("../convert-expression");
const reflections_1 = require("../utils/reflections");
const ReflectionSymbolId_1 = require("../../models/reflections/ReflectionSymbolId");
function createSignature(context, kind, signature, symbol, declaration) {
(0, assert_1.default)(context.scope instanceof models_1.DeclarationReflection);
declaration ||= signature.getDeclaration();
const sigRef = new models_1.SignatureReflection(kind == models_1.ReflectionKind.ConstructorSignature
? `new ${context.scope.parent.name}`
: context.scope.name, kind, context.scope);
// This feels awful, but we need some way to tell if callable signatures on classes
// are "static" (e.g. `Foo()`) or not (e.g. `(new Foo())()`)
if (context.shouldBeStatic) {
sigRef.setFlag(models_1.ReflectionFlag.Static);
}
const sigRefCtx = context.withScope(sigRef);
if (symbol && declaration) {
context.project.registerSymbolId(sigRef, new ReflectionSymbolId_1.ReflectionSymbolId(symbol, declaration));
}
// If we are creating signatures for a variable or property and it has a comment associated with it
// then we should prefer that comment over any comment on the signature. The comment plugin
// will copy the comment down if this signature doesn't have one, so don't set one.
let parentReflection = context.scope;
if (parentReflection.kindOf(models_1.ReflectionKind.TypeLiteral) &&
parentReflection.parent instanceof models_1.DeclarationReflection) {
parentReflection = parentReflection.parent;
}
if (declaration &&
(!parentReflection.comment ||
!(parentReflection.conversionFlags &
models_1.ConversionFlags.VariableOrPropertySource))) {
sigRef.comment = context.getSignatureComment(declaration);
}
sigRef.typeParameters = convertTypeParameters(sigRefCtx, sigRef, signature.typeParameters);
const parameterSymbols = signature.thisParameter
? [signature.thisParameter, ...signature.parameters]
: signature.parameters;
sigRef.parameters = convertParameters(sigRefCtx, sigRef, parameterSymbols, declaration?.parameters);
const predicate = context.checker.getTypePredicateOfSignature(signature);
if (predicate) {
sigRef.type = convertPredicate(predicate, sigRefCtx);
}
else if (kind == models_1.ReflectionKind.SetSignature) {
sigRef.type = new models_1.IntrinsicType("void");
}
else if (declaration?.type?.kind === typescript_1.default.SyntaxKind.ThisType) {
sigRef.type = new models_1.IntrinsicType("this");
}
else {
sigRef.type = context.converter.convertType(sigRefCtx, (declaration?.kind === typescript_1.default.SyntaxKind.FunctionDeclaration &&
declaration.type) ||
signature.getReturnType());
}
context.registerReflection(sigRef, undefined);
switch (kind) {
case models_1.ReflectionKind.GetSignature:
context.scope.getSignature = sigRef;
break;
case models_1.ReflectionKind.SetSignature:
context.scope.setSignature = sigRef;
break;
case models_1.ReflectionKind.CallSignature:
case models_1.ReflectionKind.ConstructorSignature:
context.scope.signatures ??= [];
context.scope.signatures.push(sigRef);
break;
}
context.converter.trigger(converter_events_1.ConverterEvents.CREATE_SIGNATURE, context, sigRef, declaration, signature);
}
exports.createSignature = createSignature;
/**
* Special cased constructor factory for functions tagged with `@class`
*/
function createConstructSignatureWithType(context, signature, classType) {
(0, assert_1.default)(context.scope instanceof models_1.DeclarationReflection);
const declaration = signature.getDeclaration();
const sigRef = new models_1.SignatureReflection(`new ${context.scope.parent.name}`, models_1.ReflectionKind.ConstructorSignature, context.scope);
const sigRefCtx = context.withScope(sigRef);
if (declaration) {
sigRef.comment = context.getSignatureComment(declaration);
}
sigRef.typeParameters = convertTypeParameters(sigRefCtx, sigRef, signature.typeParameters);
sigRef.type = models_1.ReferenceType.createResolvedReference(context.scope.parent.name, classType, context.project);
context.registerReflection(sigRef, undefined);
context.scope.signatures ??= [];
context.scope.signatures.push(sigRef);
context.converter.trigger(converter_events_1.ConverterEvents.CREATE_SIGNATURE, context, sigRef, declaration, signature);
}
exports.createConstructSignatureWithType = createConstructSignatureWithType;
function convertParameters(context, sigRef, parameters, parameterNodes) {
return parameters.map((param, i) => {
const declaration = param.valueDeclaration;
(0, assert_1.default)(!declaration ||
typescript_1.default.isParameter(declaration) ||
typescript_1.default.isJSDocParameterTag(declaration));
const paramRefl = new models_1.ParameterReflection(/__\d+/.test(param.name) ? "__namedParameters" : param.name, models_1.ReflectionKind.Parameter, sigRef);
if (declaration && typescript_1.default.isJSDocParameterTag(declaration)) {
paramRefl.comment = context.getJsDocComment(declaration);
}
paramRefl.comment ||= context.getComment(param, paramRefl.kind);
context.registerReflection(paramRefl, param);
context.trigger(converter_events_1.ConverterEvents.CREATE_PARAMETER, paramRefl);
let type;
if (declaration) {
type = context.checker.getTypeOfSymbolAtLocation(param, declaration);
}
else {
type = param.type;
}
if (declaration &&
typescript_1.default.isParameter(declaration) &&
declaration.type?.kind === typescript_1.default.SyntaxKind.ThisType) {
paramRefl.type = new models_1.IntrinsicType("this");
}
else {
paramRefl.type = context.converter.convertType(context.withScope(paramRefl), type);
}
let isOptional = false;
if (declaration) {
isOptional = typescript_1.default.isParameter(declaration)
? !!declaration.questionToken ||
typescript_1.default
.getJSDocParameterTags(declaration)
.some((tag) => tag.isBracketed)
: declaration.isBracketed;
}
if (isOptional) {
paramRefl.type = (0, reflections_1.removeUndefined)(paramRefl.type);
}
paramRefl.defaultValue = (0, convert_expression_1.convertDefaultValue)(parameterNodes?.[i]);
paramRefl.setFlag(models_1.ReflectionFlag.Optional, isOptional);
// If we have no declaration, then this is an implicitly defined parameter in JS land
// because the method body uses `arguments`... which is always a rest argument
let isRest = true;
if (declaration) {
isRest = typescript_1.default.isParameter(declaration)
? !!declaration.dotDotDotToken
: !!declaration.typeExpression &&
typescript_1.default.isJSDocVariadicType(declaration.typeExpression.type);
}
paramRefl.setFlag(models_1.ReflectionFlag.Rest, isRest);
checkForDestructuredParameterDefaults(paramRefl, parameterNodes?.[i]);
return paramRefl;
});
}
function convertParameterNodes(context, sigRef, parameters) {
return parameters.map((param) => {
const paramRefl = new models_1.ParameterReflection(/__\d+/.test(param.name.getText())
? "__namedParameters"
: param.name.getText(), models_1.ReflectionKind.Parameter, sigRef);
if (typescript_1.default.isJSDocParameterTag(param)) {
paramRefl.comment = context.getJsDocComment(param);
}
context.registerReflection(paramRefl, context.getSymbolAtLocation(param));
context.trigger(converter_events_1.ConverterEvents.CREATE_PARAMETER, paramRefl);
paramRefl.type = context.converter.convertType(context.withScope(paramRefl), typescript_1.default.isParameter(param) ? param.type : param.typeExpression?.type);
const isOptional = typescript_1.default.isParameter(param)
? !!param.questionToken
: param.isBracketed;
if (isOptional) {
paramRefl.type = (0, reflections_1.removeUndefined)(paramRefl.type);
}
paramRefl.defaultValue = (0, convert_expression_1.convertDefaultValue)(param);
paramRefl.setFlag(models_1.ReflectionFlag.Optional, isOptional);
paramRefl.setFlag(models_1.ReflectionFlag.Rest, typescript_1.default.isParameter(param)
? !!param.dotDotDotToken
: !!param.typeExpression &&
typescript_1.default.isJSDocVariadicType(param.typeExpression.type));
checkForDestructuredParameterDefaults(paramRefl, param);
return paramRefl;
});
}
exports.convertParameterNodes = convertParameterNodes;
function checkForDestructuredParameterDefaults(param, decl) {
if (!decl || !typescript_1.default.isParameter(decl))
return;
if (param.name !== "__namedParameters")
return;
if (!typescript_1.default.isObjectBindingPattern(decl.name))
return;
if (param.type?.type !== "reflection")
return;
for (const child of param.type.declaration.children || []) {
const tsChild = decl.name.elements.find((el) => (el.propertyName || el.name).getText() === child.name);
if (tsChild) {
child.defaultValue = (0, convert_expression_1.convertDefaultValue)(tsChild);
}
}
}
function convertTypeParameters(context, parent, parameters) {
return parameters?.map((param) => {
const constraintT = param.getConstraint();
const defaultT = param.getDefault();
// There's no way to determine directly from a ts.TypeParameter what it's variance modifiers are
// so unfortunately we have to go back to the node for this...
const declaration = param
.getSymbol()
?.declarations?.find(typescript_1.default.isTypeParameterDeclaration);
const variance = getVariance(declaration?.modifiers);
const paramRefl = new models_1.TypeParameterReflection(param.symbol.name, parent, variance);
const paramCtx = context.withScope(paramRefl);
paramRefl.type = constraintT
? context.converter.convertType(paramCtx, constraintT)
: void 0;
paramRefl.default = defaultT
? context.converter.convertType(paramCtx, defaultT)
: void 0;
// No way to determine this from the type parameter itself, need to go back to the declaration
if (declaration?.modifiers?.some((m) => m.kind === typescript_1.default.SyntaxKind.ConstKeyword)) {
paramRefl.flags.setFlag(models_1.ReflectionFlag.Const, true);
}
context.registerReflection(paramRefl, param.getSymbol());
context.trigger(converter_events_1.ConverterEvents.CREATE_TYPE_PARAMETER, paramRefl);
return paramRefl;
});
}
function convertTypeParameterNodes(context, parameters) {
return parameters?.map((param) => createTypeParamReflection(param, context));
}
exports.convertTypeParameterNodes = convertTypeParameterNodes;
function createTypeParamReflection(param, context) {
const paramRefl = new models_1.TypeParameterReflection(param.name.text, context.scope, getVariance(param.modifiers));
const paramScope = context.withScope(paramRefl);
paramRefl.type = param.constraint
? context.converter.convertType(paramScope, param.constraint)
: void 0;
paramRefl.default = param.default
? context.converter.convertType(paramScope, param.default)
: void 0;
if (param.modifiers?.some((m) => m.kind === typescript_1.default.SyntaxKind.ConstKeyword)) {
paramRefl.flags.setFlag(models_1.ReflectionFlag.Const, true);
}
context.registerReflection(paramRefl, param.symbol);
if (typescript_1.default.isJSDocTemplateTag(param.parent)) {
paramRefl.comment = context.getJsDocComment(param.parent);
}
context.trigger(converter_events_1.ConverterEvents.CREATE_TYPE_PARAMETER, paramRefl, param);
return paramRefl;
}
exports.createTypeParamReflection = createTypeParamReflection;
function convertTemplateParameterNodes(context, nodes) {
return nodes?.flatMap((node) => {
return node.typeParameters.map((param, index) => {
const paramRefl = new models_1.TypeParameterReflection(param.name.text, context.scope, getVariance(param.modifiers));
const paramScope = context.withScope(paramRefl);
paramRefl.type =
index || !node.constraint
? void 0
: context.converter.convertType(paramScope, node.constraint.type);
paramRefl.default = param.default
? context.converter.convertType(paramScope, param.default)
: void 0;
if (param.modifiers?.some((m) => m.kind === typescript_1.default.SyntaxKind.ConstKeyword)) {
paramRefl.flags.setFlag(models_1.ReflectionFlag.Const, true);
}
context.registerReflection(paramRefl, param.symbol);
if (typescript_1.default.isJSDocTemplateTag(param.parent)) {
paramRefl.comment = context.getJsDocComment(param.parent);
}
context.trigger(converter_events_1.ConverterEvents.CREATE_TYPE_PARAMETER, paramRefl, param);
return paramRefl;
});
});
}
exports.convertTemplateParameterNodes = convertTemplateParameterNodes;
function getVariance(modifiers) {
const hasIn = modifiers?.some((mod) => mod.kind === typescript_1.default.SyntaxKind.InKeyword);
const hasOut = modifiers?.some((mod) => mod.kind === typescript_1.default.SyntaxKind.OutKeyword);
if (hasIn && hasOut) {
return models_1.VarianceModifier.inOut;
}
if (hasIn) {
return models_1.VarianceModifier.in;
}
if (hasOut) {
return models_1.VarianceModifier.out;
}
}
function convertPredicate(predicate, context) {
let name;
switch (predicate.kind) {
case typescript_1.default.TypePredicateKind.This:
case typescript_1.default.TypePredicateKind.AssertsThis:
name = "this";
break;
case typescript_1.default.TypePredicateKind.Identifier:
case typescript_1.default.TypePredicateKind.AssertsIdentifier:
name = predicate.parameterName;
break;
}
let asserts;
switch (predicate.kind) {
case typescript_1.default.TypePredicateKind.This:
case typescript_1.default.TypePredicateKind.Identifier:
asserts = false;
break;
case typescript_1.default.TypePredicateKind.AssertsThis:
case typescript_1.default.TypePredicateKind.AssertsIdentifier:
asserts = true;
break;
}
return new models_1.PredicateType(name, asserts, predicate.type
? context.converter.convertType(context, predicate.type)
: void 0);
}

7
node_modules/typedoc/dist/lib/converter/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,7 @@
export { Context } from "./context";
export { Converter } from "./converter";
export type { CommentParserConfig } from "./comments/index";
export { convertDefaultValue, convertExpression } from "./convert-expression";
export type { DeclarationReference, SymbolReference, ComponentPath, Meaning, MeaningKeyword, } from "./comments/declarationReference";
export type { ExternalSymbolResolver, ExternalResolveResult, } from "./comments/linkResolver";
import "./plugins/index";

11
node_modules/typedoc/dist/lib/converter/index.js generated vendored Normal file
View File

@@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertExpression = exports.convertDefaultValue = exports.Converter = exports.Context = void 0;
var context_1 = require("./context");
Object.defineProperty(exports, "Context", { enumerable: true, get: function () { return context_1.Context; } });
var converter_1 = require("./converter");
Object.defineProperty(exports, "Converter", { enumerable: true, get: function () { return converter_1.Converter; } });
var convert_expression_1 = require("./convert-expression");
Object.defineProperty(exports, "convertDefaultValue", { enumerable: true, get: function () { return convert_expression_1.convertDefaultValue; } });
Object.defineProperty(exports, "convertExpression", { enumerable: true, get: function () { return convert_expression_1.convertExpression; } });
require("./plugins/index");

4
node_modules/typedoc/dist/lib/converter/jsdoc.d.ts generated vendored Normal file
View File

@@ -0,0 +1,4 @@
import ts from "typescript";
import type { Context } from "./context";
export declare function convertJsDocAlias(context: Context, symbol: ts.Symbol, declaration: ts.JSDocTypedefTag | ts.JSDocEnumTag, exportSymbol?: ts.Symbol): void;
export declare function convertJsDocCallback(context: Context, symbol: ts.Symbol, declaration: ts.JSDocCallbackTag, exportSymbol?: ts.Symbol): void;

112
node_modules/typedoc/dist/lib/converter/jsdoc.js generated vendored Normal file
View File

@@ -0,0 +1,112 @@
"use strict";
// Converter functions for JSDoc defined types
// @typedef
// @callback
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertJsDocCallback = exports.convertJsDocAlias = void 0;
const assert_1 = require("assert");
const typescript_1 = __importDefault(require("typescript"));
const models_1 = require("../models");
const ReflectionSymbolId_1 = require("../models/reflections/ReflectionSymbolId");
const converter_events_1 = require("./converter-events");
const signature_1 = require("./factories/signature");
function convertJsDocAlias(context, symbol, declaration, exportSymbol) {
if (declaration.typeExpression &&
typescript_1.default.isJSDocTypeLiteral(declaration.typeExpression)) {
convertJsDocInterface(context, declaration, symbol, exportSymbol);
return;
}
// If the typedef tag is just referring to another type-space symbol, with no type parameters
// or appropriate forwarding type parameters, then we treat it as a re-export instead of creating
// a type alias with an import type.
const aliasedSymbol = getTypedefReExportTarget(context, declaration);
if (aliasedSymbol) {
context.converter.convertSymbol(context, aliasedSymbol, exportSymbol ?? symbol);
return;
}
const reflection = context.createDeclarationReflection(models_1.ReflectionKind.TypeAlias, symbol, exportSymbol);
reflection.comment = context.getJsDocComment(declaration);
reflection.type = context.converter.convertType(context.withScope(reflection), declaration.typeExpression?.type);
convertTemplateParameters(context.withScope(reflection), declaration.parent);
context.finalizeDeclarationReflection(reflection);
}
exports.convertJsDocAlias = convertJsDocAlias;
function convertJsDocCallback(context, symbol, declaration, exportSymbol) {
const alias = context.createDeclarationReflection(models_1.ReflectionKind.TypeAlias, symbol, exportSymbol);
alias.comment = context.getJsDocComment(declaration);
context.finalizeDeclarationReflection(alias);
const ac = context.withScope(alias);
alias.type = convertJsDocSignature(ac, declaration.typeExpression);
convertTemplateParameters(ac, declaration.parent);
}
exports.convertJsDocCallback = convertJsDocCallback;
function convertJsDocInterface(context, declaration, symbol, exportSymbol) {
const reflection = context.createDeclarationReflection(models_1.ReflectionKind.Interface, symbol, exportSymbol);
reflection.comment = context.getJsDocComment(declaration);
context.finalizeDeclarationReflection(reflection);
const rc = context.withScope(reflection);
const type = context.checker.getDeclaredTypeOfSymbol(symbol);
for (const s of type.getProperties()) {
context.converter.convertSymbol(rc, s);
}
convertTemplateParameters(rc, declaration.parent);
}
function convertJsDocSignature(context, node) {
const symbol = context.getSymbolAtLocation(node) ?? node.symbol;
const type = context.getTypeAtLocation(node);
if (!symbol || !type) {
return new models_1.IntrinsicType("Function");
}
const reflection = new models_1.DeclarationReflection("__type", models_1.ReflectionKind.TypeLiteral, context.scope);
context.registerReflection(reflection, symbol);
context.trigger(converter_events_1.ConverterEvents.CREATE_DECLARATION, reflection);
const signature = new models_1.SignatureReflection("__type", models_1.ReflectionKind.CallSignature, reflection);
context.project.registerSymbolId(signature, new ReflectionSymbolId_1.ReflectionSymbolId(symbol, node));
context.registerReflection(signature, void 0);
const signatureCtx = context.withScope(signature);
reflection.signatures = [signature];
signature.type = context.converter.convertType(signatureCtx, node.type?.typeExpression?.type);
signature.parameters = (0, signature_1.convertParameterNodes)(signatureCtx, signature, node.parameters);
signature.typeParameters = (0, signature_1.convertTemplateParameterNodes)(context.withScope(reflection), node.typeParameters);
return new models_1.ReflectionType(reflection);
}
function convertTemplateParameters(context, node) {
(0, assert_1.ok)(context.scope instanceof models_1.DeclarationReflection);
context.scope.typeParameters = (0, signature_1.convertTemplateParameterNodes)(context, node.tags?.filter(typescript_1.default.isJSDocTemplateTag));
}
function getTypedefReExportTarget(context, declaration) {
const typeExpression = declaration.typeExpression;
if (!typescript_1.default.isJSDocTypedefTag(declaration) ||
!typeExpression ||
typescript_1.default.isJSDocTypeLiteral(typeExpression) ||
!typescript_1.default.isImportTypeNode(typeExpression.type) ||
!typeExpression.type.qualifier ||
!typescript_1.default.isIdentifier(typeExpression.type.qualifier)) {
return;
}
const targetSymbol = context.expectSymbolAtLocation(typeExpression.type.qualifier);
const decl = targetSymbol.declarations?.[0];
if (!decl ||
!(typescript_1.default.isTypeAliasDeclaration(decl) ||
typescript_1.default.isInterfaceDeclaration(decl) ||
typescript_1.default.isJSDocTypedefTag(decl) ||
typescript_1.default.isJSDocCallbackTag(decl))) {
return;
}
const targetParams = typescript_1.default.getEffectiveTypeParameterDeclarations(decl);
const localParams = typescript_1.default.getEffectiveTypeParameterDeclarations(declaration);
const localArgs = typeExpression.type.typeArguments || [];
// If we have type parameters, ensure they are forwarding parameters with no transformations.
// This doesn't check constraints since they aren't checked in JSDoc types.
if (targetParams.length !== localParams.length ||
localArgs.some((arg, i) => !typescript_1.default.isTypeReferenceNode(arg) ||
!typescript_1.default.isIdentifier(arg.typeName) ||
arg.typeArguments ||
localParams[i]?.name.text !== arg.typeName.text)) {
return;
}
return targetSymbol;
}

View File

@@ -0,0 +1,62 @@
import { DeclarationReflection } from "../../models";
import { ConverterComponent } from "../components";
/**
* A handler that sorts and categorizes the found reflections in the resolving phase.
*
* The handler sets the ´category´ property of all reflections.
*/
export declare class CategoryPlugin extends ConverterComponent {
sortFunction: (reflections: DeclarationReflection[]) => void;
accessor defaultCategory: string;
accessor categoryOrder: string[];
accessor categorizeByGroup: boolean;
accessor boosts: Record<string, number>;
usedBoosts: Set<string>;
static defaultCategory: string;
static WEIGHTS: string[];
/**
* Create a new CategoryPlugin instance.
*/
initialize(): void;
/**
* Triggered when the converter begins converting a project.
*/
private onBegin;
/**
* Triggered when the converter has finished resolving a project.
*
* @param context The context object describing the current state the converter is in.
*/
private onEndResolve;
private categorize;
private groupCategorize;
private lumpCategorize;
/**
* Create a categorized representation of the given list of reflections.
*
* @param reflections The reflections that should be categorized.
* @param categorySearchBoosts A user-supplied map of category titles, for computing a
* relevance boost to be used when searching
* @returns An array containing all children of the given reflection categorized
*/
private getReflectionCategories;
/**
* Return the category of a given reflection.
*
* @param reflection The reflection.
* @returns The category the reflection belongs to
*
* @privateRemarks
* If you change this, also update getGroups in GroupPlugin accordingly.
*/
private extractCategories;
/**
* Callback used to sort categories by name.
*
* @param a The left reflection to sort.
* @param b The right reflection to sort.
* @returns The sorting weight.
*/
private static sortCatCallback;
static getCategories(reflection: DeclarationReflection): Set<string>;
}

View File

@@ -0,0 +1,343 @@
"use strict";
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
var _, done = false;
for (var i = decorators.length - 1; i >= 0; i--) {
var context = {};
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
if (kind === "accessor") {
if (result === void 0) continue;
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
if (_ = accept(result.get)) descriptor.get = _;
if (_ = accept(result.set)) descriptor.set = _;
if (_ = accept(result.init)) initializers.unshift(_);
}
else if (_ = accept(result)) {
if (kind === "field") initializers.unshift(_);
else descriptor[key] = _;
}
}
if (target) Object.defineProperty(target, contextIn.name, descriptor);
done = true;
};
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
var useValue = arguments.length > 2;
for (var i = 0; i < initializers.length; i++) {
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
}
return useValue ? value : void 0;
};
var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CategoryPlugin = void 0;
const models_1 = require("../../models");
const models_2 = require("../../models");
const components_1 = require("../components");
const converter_1 = require("../converter");
const utils_1 = require("../../utils");
/**
* A handler that sorts and categorizes the found reflections in the resolving phase.
*
* The handler sets the ´category´ property of all reflections.
*/
let CategoryPlugin = (() => {
var _CategoryPlugin_defaultCategory_accessor_storage, _CategoryPlugin_categoryOrder_accessor_storage, _CategoryPlugin_categorizeByGroup_accessor_storage, _CategoryPlugin_boosts_accessor_storage;
let _classDecorators = [(0, components_1.Component)({ name: "category" })];
let _classDescriptor;
let _classExtraInitializers = [];
let _classThis;
let _classSuper = components_1.ConverterComponent;
let _defaultCategory_decorators;
let _defaultCategory_initializers = [];
let _defaultCategory_extraInitializers = [];
let _categoryOrder_decorators;
let _categoryOrder_initializers = [];
let _categoryOrder_extraInitializers = [];
let _categorizeByGroup_decorators;
let _categorizeByGroup_initializers = [];
let _categorizeByGroup_extraInitializers = [];
let _boosts_decorators;
let _boosts_initializers = [];
let _boosts_extraInitializers = [];
var CategoryPlugin = _classThis = class extends _classSuper {
constructor() {
super(...arguments);
_CategoryPlugin_defaultCategory_accessor_storage.set(this, __runInitializers(this, _defaultCategory_initializers, void 0));
_CategoryPlugin_categoryOrder_accessor_storage.set(this, (__runInitializers(this, _defaultCategory_extraInitializers), __runInitializers(this, _categoryOrder_initializers, void 0)));
_CategoryPlugin_categorizeByGroup_accessor_storage.set(this, (__runInitializers(this, _categoryOrder_extraInitializers), __runInitializers(this, _categorizeByGroup_initializers, void 0)));
_CategoryPlugin_boosts_accessor_storage.set(this, (__runInitializers(this, _categorizeByGroup_extraInitializers), __runInitializers(this, _boosts_initializers, void 0)));
this.usedBoosts = (__runInitializers(this, _boosts_extraInitializers), new Set());
}
get defaultCategory() { return __classPrivateFieldGet(this, _CategoryPlugin_defaultCategory_accessor_storage, "f"); }
set defaultCategory(value) { __classPrivateFieldSet(this, _CategoryPlugin_defaultCategory_accessor_storage, value, "f"); }
get categoryOrder() { return __classPrivateFieldGet(this, _CategoryPlugin_categoryOrder_accessor_storage, "f"); }
set categoryOrder(value) { __classPrivateFieldSet(this, _CategoryPlugin_categoryOrder_accessor_storage, value, "f"); }
get categorizeByGroup() { return __classPrivateFieldGet(this, _CategoryPlugin_categorizeByGroup_accessor_storage, "f"); }
set categorizeByGroup(value) { __classPrivateFieldSet(this, _CategoryPlugin_categorizeByGroup_accessor_storage, value, "f"); }
get boosts() { return __classPrivateFieldGet(this, _CategoryPlugin_boosts_accessor_storage, "f"); }
set boosts(value) { __classPrivateFieldSet(this, _CategoryPlugin_boosts_accessor_storage, value, "f"); }
/**
* Create a new CategoryPlugin instance.
*/
initialize() {
this.listenTo(this.owner, {
[converter_1.Converter.EVENT_BEGIN]: this.onBegin,
[converter_1.Converter.EVENT_RESOLVE_END]: this.onEndResolve,
}, undefined, -200);
}
/**
* Triggered when the converter begins converting a project.
*/
onBegin(_context) {
this.sortFunction = (0, utils_1.getSortFunction)(this.application.options);
// Set up static properties
if (this.defaultCategory) {
CategoryPlugin.defaultCategory = this.defaultCategory;
}
if (this.categoryOrder) {
CategoryPlugin.WEIGHTS = this.categoryOrder;
}
}
/**
* Triggered when the converter has finished resolving a project.
*
* @param context The context object describing the current state the converter is in.
*/
onEndResolve(context) {
const project = context.project;
this.categorize(project);
for (const id in project.reflections) {
const reflection = project.reflections[id];
if (reflection instanceof models_1.ContainerReflection) {
this.categorize(reflection);
}
}
const unusedBoosts = new Set(Object.keys(this.boosts));
for (const boost of this.usedBoosts) {
unusedBoosts.delete(boost);
}
this.usedBoosts.clear();
if (unusedBoosts.size) {
context.logger.warn(`Not all categories specified in searchCategoryBoosts were used in the documentation.` +
` The unused categories were:\n\t${Array.from(unusedBoosts).join("\n\t")}`);
}
}
categorize(obj) {
if (this.categorizeByGroup) {
this.groupCategorize(obj);
}
else {
this.lumpCategorize(obj);
}
}
groupCategorize(obj) {
if (!obj.groups || obj.groups.length === 0) {
return;
}
obj.groups.forEach((group) => {
if (group.categories)
return;
group.categories = this.getReflectionCategories(obj, group.children);
if (group.categories && group.categories.length > 1) {
group.categories.sort(CategoryPlugin.sortCatCallback);
}
else if (group.categories.length === 1 &&
group.categories[0].title === CategoryPlugin.defaultCategory) {
// no categories if everything is uncategorized
group.categories = undefined;
}
});
}
lumpCategorize(obj) {
if (!obj.children || obj.children.length === 0 || obj.categories) {
return;
}
obj.categories = this.getReflectionCategories(obj, obj.children);
if (obj.categories && obj.categories.length > 1) {
obj.categories.sort(CategoryPlugin.sortCatCallback);
}
else if (obj.categories.length === 1 &&
obj.categories[0].title === CategoryPlugin.defaultCategory) {
// no categories if everything is uncategorized
obj.categories = undefined;
}
}
/**
* Create a categorized representation of the given list of reflections.
*
* @param reflections The reflections that should be categorized.
* @param categorySearchBoosts A user-supplied map of category titles, for computing a
* relevance boost to be used when searching
* @returns An array containing all children of the given reflection categorized
*/
getReflectionCategories(parent, reflections) {
const categories = new Map();
for (const child of reflections) {
const childCategories = this.extractCategories(child);
if (childCategories.size === 0) {
childCategories.add(CategoryPlugin.defaultCategory);
}
for (const childCat of childCategories) {
const category = categories.get(childCat);
if (category) {
category.children.push(child);
}
else {
const cat = new models_2.ReflectionCategory(childCat);
cat.children.push(child);
categories.set(childCat, cat);
}
}
}
if (parent.comment) {
(0, utils_1.removeIf)(parent.comment.blockTags, (tag) => {
if (tag.tag === "@categoryDescription") {
const { header, body } = models_1.Comment.splitPartsToHeaderAndBody(tag.content);
const cat = categories.get(header);
if (cat) {
cat.description = body;
}
else {
this.application.logger.warn(`Comment for ${parent.getFriendlyFullName()} includes @categoryDescription for "${header}", but no child is placed in that category.`);
}
return true;
}
return false;
});
}
for (const cat of categories.values()) {
this.sortFunction(cat.children);
}
return Array.from(categories.values());
}
/**
* Return the category of a given reflection.
*
* @param reflection The reflection.
* @returns The category the reflection belongs to
*
* @privateRemarks
* If you change this, also update getGroups in GroupPlugin accordingly.
*/
extractCategories(reflection) {
const categories = CategoryPlugin.getCategories(reflection);
reflection.comment?.removeTags("@category");
for (const sig of reflection.getNonIndexSignatures()) {
sig.comment?.removeTags("@category");
}
if (reflection.type?.type === "reflection") {
reflection.type.declaration.comment?.removeTags("@category");
for (const sig of reflection.type.declaration.getNonIndexSignatures()) {
sig.comment?.removeTags("@category");
}
}
categories.delete("");
for (const cat of categories) {
if (cat in this.boosts) {
this.usedBoosts.add(cat);
reflection.relevanceBoost =
(reflection.relevanceBoost ?? 1) * this.boosts[cat];
}
}
return categories;
}
/**
* Callback used to sort categories by name.
*
* @param a The left reflection to sort.
* @param b The right reflection to sort.
* @returns The sorting weight.
*/
static sortCatCallback(a, b) {
let aWeight = CategoryPlugin.WEIGHTS.indexOf(a.title);
let bWeight = CategoryPlugin.WEIGHTS.indexOf(b.title);
if (aWeight === -1 || bWeight === -1) {
let asteriskIndex = CategoryPlugin.WEIGHTS.indexOf("*");
if (asteriskIndex === -1) {
asteriskIndex = CategoryPlugin.WEIGHTS.length;
}
if (aWeight === -1) {
aWeight = asteriskIndex;
}
if (bWeight === -1) {
bWeight = asteriskIndex;
}
}
if (aWeight === bWeight) {
return a.title > b.title ? 1 : -1;
}
return aWeight - bWeight;
}
static getCategories(reflection) {
const categories = new Set();
function discoverCategories(comment) {
if (!comment)
return;
for (const tag of comment.blockTags) {
if (tag.tag === "@category") {
categories.add(models_1.Comment.combineDisplayParts(tag.content).trim());
}
}
}
discoverCategories(reflection.comment);
for (const sig of reflection.getNonIndexSignatures()) {
discoverCategories(sig.comment);
}
if (reflection.type?.type === "reflection") {
discoverCategories(reflection.type.declaration.comment);
for (const sig of reflection.type.declaration.getNonIndexSignatures()) {
discoverCategories(sig.comment);
}
}
categories.delete("");
return categories;
}
};
_CategoryPlugin_defaultCategory_accessor_storage = new WeakMap();
_CategoryPlugin_categoryOrder_accessor_storage = new WeakMap();
_CategoryPlugin_categorizeByGroup_accessor_storage = new WeakMap();
_CategoryPlugin_boosts_accessor_storage = new WeakMap();
__setFunctionName(_classThis, "CategoryPlugin");
(() => {
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
_defaultCategory_decorators = [(0, utils_1.Option)("defaultCategory")];
_categoryOrder_decorators = [(0, utils_1.Option)("categoryOrder")];
_categorizeByGroup_decorators = [(0, utils_1.Option)("categorizeByGroup")];
_boosts_decorators = [(0, utils_1.Option)("searchCategoryBoosts")];
__esDecorate(_classThis, null, _defaultCategory_decorators, { kind: "accessor", name: "defaultCategory", static: false, private: false, access: { has: obj => "defaultCategory" in obj, get: obj => obj.defaultCategory, set: (obj, value) => { obj.defaultCategory = value; } }, metadata: _metadata }, _defaultCategory_initializers, _defaultCategory_extraInitializers);
__esDecorate(_classThis, null, _categoryOrder_decorators, { kind: "accessor", name: "categoryOrder", static: false, private: false, access: { has: obj => "categoryOrder" in obj, get: obj => obj.categoryOrder, set: (obj, value) => { obj.categoryOrder = value; } }, metadata: _metadata }, _categoryOrder_initializers, _categoryOrder_extraInitializers);
__esDecorate(_classThis, null, _categorizeByGroup_decorators, { kind: "accessor", name: "categorizeByGroup", static: false, private: false, access: { has: obj => "categorizeByGroup" in obj, get: obj => obj.categorizeByGroup, set: (obj, value) => { obj.categorizeByGroup = value; } }, metadata: _metadata }, _categorizeByGroup_initializers, _categorizeByGroup_extraInitializers);
__esDecorate(_classThis, null, _boosts_decorators, { kind: "accessor", name: "boosts", static: false, private: false, access: { has: obj => "boosts" in obj, get: obj => obj.boosts, set: (obj, value) => { obj.boosts = value; } }, metadata: _metadata }, _boosts_initializers, _boosts_extraInitializers);
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
CategoryPlugin = _classThis = _classDescriptor.value;
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
})();
// For use in static methods
_classThis.defaultCategory = "Other";
_classThis.WEIGHTS = [];
(() => {
__runInitializers(_classThis, _classExtraInitializers);
})();
return CategoryPlugin = _classThis;
})();
exports.CategoryPlugin = CategoryPlugin;

View File

@@ -0,0 +1,125 @@
import { ConverterComponent } from "../components";
/**
* Handles most behavior triggered by comments. `@group` and `@category` are handled by their respective plugins, but everything else is here.
*
* How it works today
* ==================
* During conversion:
* - Handle visibility flags (`@private`, `@protected`. `@public`)
* - Handle module renames (`@module`)
* - Remove excluded tags & comment discovery tags (`@module`, `@packageDocumentation`)
* - Copy comments for type parameters from the parent container (for classes/interfaces)
*
* Resolve begin:
* - Remove hidden reflections
*
* Resolve:
* - Apply `@label` tag
* - Copy comments on signature containers to the signature if signatures don't already have a comment
* and then remove the comment on the container.
* - Copy comments to parameters and type parameters (for signatures)
* - Apply `@group` and `@category` tags
*
* Resolve end:
* - Copy auto inherited comments from heritage clauses
* - Handle `@inheritDoc`
* - Resolve `@link` tags to point to target reflections
*
* How it should work
* ==================
* During conversion:
* - Handle visibility flags (`@private`, `@protected`. `@public`)
* - Handle module renames (`@module`)
* - Remove excluded tags & comment discovery tags (`@module`, `@packageDocumentation`)
*
* Resolve begin (100):
* - Copy auto inherited comments from heritage clauses
* - Apply `@label` tag
*
* Resolve begin (75)
* - Handle `@inheritDoc`
*
* Resolve begin (50)
* - Copy comments on signature containers to the signature if signatures don't already have a comment
* and then remove the comment on the container.
* - Copy comments for type parameters from the parent container (for classes/interfaces)
*
* Resolve begin (25)
* - Remove hidden reflections
*
* Resolve:
* - Copy comments to parameters and type parameters (for signatures)
* - Apply `@group` and `@category` tags
*
* Resolve end:
* - Resolve `@link` tags to point to target reflections
*
*/
export declare class CommentPlugin extends ConverterComponent {
accessor excludeTags: `@${string}`[];
accessor excludeInternal: boolean;
accessor excludePrivate: boolean;
accessor excludeProtected: boolean;
accessor excludeNotDocumented: boolean;
accessor excludeCategories: string[];
accessor defaultCategory: string;
private _excludeKinds;
private get excludeNotDocumentedKinds();
/**
* Create a new CommentPlugin instance.
*/
initialize(): void;
/**
* Apply all comment tag modifiers to the given reflection.
*
* @param reflection The reflection the modifiers should be applied to.
* @param comment The comment that should be searched for modifiers.
*/
private applyModifiers;
/**
* Triggered when the converter has created a type parameter reflection.
*
* @param context The context object describing the current state the converter is in.
* @param reflection The reflection that is currently processed.
*/
private onCreateTypeParameter;
/**
* Triggered when the converter has created a declaration or signature reflection.
*
* Invokes the comment parser.
*
* @param context The context object describing the current state the converter is in.
* @param reflection The reflection that is currently processed.
* @param node The node that is currently processed if available.
*/
private onDeclaration;
/**
* Triggered when the converter begins resolving a project.
*
* @param context The context object describing the current state the converter is in.
*/
private onBeginResolve;
/**
* Triggered when the converter resolves a reflection.
*
* Cleans up comment tags related to signatures like `@param` or `@returns`
* and moves their data to the corresponding parameter reflections.
*
* This hook also copies over the comment of function implementations to their
* signatures.
*
* @param context The context object describing the current state the converter is in.
* @param reflection The reflection that is currently resolved.
*/
private onResolve;
private moveCommentToSignatures;
private removeExcludedTags;
/**
* Determines whether or not a reflection has been hidden
*
* @param reflection Reflection to check if hidden
*/
private isHidden;
private excludedByCategory;
private validateParamTags;
}

View File

@@ -0,0 +1,654 @@
"use strict";
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
var _, done = false;
for (var i = decorators.length - 1; i >= 0; i--) {
var context = {};
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
if (kind === "accessor") {
if (result === void 0) continue;
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
if (_ = accept(result.get)) descriptor.get = _;
if (_ = accept(result.set)) descriptor.set = _;
if (_ = accept(result.init)) initializers.unshift(_);
}
else if (_ = accept(result)) {
if (kind === "field") initializers.unshift(_);
else descriptor[key] = _;
}
}
if (target) Object.defineProperty(target, contextIn.name, descriptor);
done = true;
};
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
var useValue = arguments.length > 2;
for (var i = 0; i < initializers.length; i++) {
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
}
return useValue ? value : void 0;
};
var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CommentPlugin = void 0;
const components_1 = require("../components");
const converter_1 = require("../converter");
const models_1 = require("../../models");
const utils_1 = require("../../utils");
const CategoryPlugin_1 = require("./CategoryPlugin");
/**
* These tags are not useful to display in the generated documentation.
* They should be ignored when parsing comments. Any relevant type information
* (for JS users) will be consumed by TypeScript and need not be preserved
* in the comment.
*
* Note that param/arg/argument/return/returns are not present.
* These tags will have their type information stripped when parsing, but still
* provide useful information for documentation.
*/
const NEVER_RENDERED = [
"@augments",
"@callback",
"@class",
"@constructor",
"@enum",
"@extends",
"@this",
"@type",
"@typedef",
];
/**
* Handles most behavior triggered by comments. `@group` and `@category` are handled by their respective plugins, but everything else is here.
*
* How it works today
* ==================
* During conversion:
* - Handle visibility flags (`@private`, `@protected`. `@public`)
* - Handle module renames (`@module`)
* - Remove excluded tags & comment discovery tags (`@module`, `@packageDocumentation`)
* - Copy comments for type parameters from the parent container (for classes/interfaces)
*
* Resolve begin:
* - Remove hidden reflections
*
* Resolve:
* - Apply `@label` tag
* - Copy comments on signature containers to the signature if signatures don't already have a comment
* and then remove the comment on the container.
* - Copy comments to parameters and type parameters (for signatures)
* - Apply `@group` and `@category` tags
*
* Resolve end:
* - Copy auto inherited comments from heritage clauses
* - Handle `@inheritDoc`
* - Resolve `@link` tags to point to target reflections
*
* How it should work
* ==================
* During conversion:
* - Handle visibility flags (`@private`, `@protected`. `@public`)
* - Handle module renames (`@module`)
* - Remove excluded tags & comment discovery tags (`@module`, `@packageDocumentation`)
*
* Resolve begin (100):
* - Copy auto inherited comments from heritage clauses
* - Apply `@label` tag
*
* Resolve begin (75)
* - Handle `@inheritDoc`
*
* Resolve begin (50)
* - Copy comments on signature containers to the signature if signatures don't already have a comment
* and then remove the comment on the container.
* - Copy comments for type parameters from the parent container (for classes/interfaces)
*
* Resolve begin (25)
* - Remove hidden reflections
*
* Resolve:
* - Copy comments to parameters and type parameters (for signatures)
* - Apply `@group` and `@category` tags
*
* Resolve end:
* - Resolve `@link` tags to point to target reflections
*
*/
let CommentPlugin = (() => {
var _CommentPlugin_excludeTags_accessor_storage, _CommentPlugin_excludeInternal_accessor_storage, _CommentPlugin_excludePrivate_accessor_storage, _CommentPlugin_excludeProtected_accessor_storage, _CommentPlugin_excludeNotDocumented_accessor_storage, _CommentPlugin_excludeCategories_accessor_storage, _CommentPlugin_defaultCategory_accessor_storage;
let _classDecorators = [(0, components_1.Component)({ name: "comment" })];
let _classDescriptor;
let _classExtraInitializers = [];
let _classThis;
let _classSuper = components_1.ConverterComponent;
let _excludeTags_decorators;
let _excludeTags_initializers = [];
let _excludeTags_extraInitializers = [];
let _excludeInternal_decorators;
let _excludeInternal_initializers = [];
let _excludeInternal_extraInitializers = [];
let _excludePrivate_decorators;
let _excludePrivate_initializers = [];
let _excludePrivate_extraInitializers = [];
let _excludeProtected_decorators;
let _excludeProtected_initializers = [];
let _excludeProtected_extraInitializers = [];
let _excludeNotDocumented_decorators;
let _excludeNotDocumented_initializers = [];
let _excludeNotDocumented_extraInitializers = [];
let _excludeCategories_decorators;
let _excludeCategories_initializers = [];
let _excludeCategories_extraInitializers = [];
let _defaultCategory_decorators;
let _defaultCategory_initializers = [];
let _defaultCategory_extraInitializers = [];
var CommentPlugin = _classThis = class extends _classSuper {
constructor() {
super(...arguments);
_CommentPlugin_excludeTags_accessor_storage.set(this, __runInitializers(this, _excludeTags_initializers, void 0));
_CommentPlugin_excludeInternal_accessor_storage.set(this, (__runInitializers(this, _excludeTags_extraInitializers), __runInitializers(this, _excludeInternal_initializers, void 0)));
_CommentPlugin_excludePrivate_accessor_storage.set(this, (__runInitializers(this, _excludeInternal_extraInitializers), __runInitializers(this, _excludePrivate_initializers, void 0)));
_CommentPlugin_excludeProtected_accessor_storage.set(this, (__runInitializers(this, _excludePrivate_extraInitializers), __runInitializers(this, _excludeProtected_initializers, void 0)));
_CommentPlugin_excludeNotDocumented_accessor_storage.set(this, (__runInitializers(this, _excludeProtected_extraInitializers), __runInitializers(this, _excludeNotDocumented_initializers, void 0)));
_CommentPlugin_excludeCategories_accessor_storage.set(this, (__runInitializers(this, _excludeNotDocumented_extraInitializers), __runInitializers(this, _excludeCategories_initializers, void 0)));
_CommentPlugin_defaultCategory_accessor_storage.set(this, (__runInitializers(this, _excludeCategories_extraInitializers), __runInitializers(this, _defaultCategory_initializers, void 0)));
this._excludeKinds = __runInitializers(this, _defaultCategory_extraInitializers);
}
get excludeTags() { return __classPrivateFieldGet(this, _CommentPlugin_excludeTags_accessor_storage, "f"); }
set excludeTags(value) { __classPrivateFieldSet(this, _CommentPlugin_excludeTags_accessor_storage, value, "f"); }
get excludeInternal() { return __classPrivateFieldGet(this, _CommentPlugin_excludeInternal_accessor_storage, "f"); }
set excludeInternal(value) { __classPrivateFieldSet(this, _CommentPlugin_excludeInternal_accessor_storage, value, "f"); }
get excludePrivate() { return __classPrivateFieldGet(this, _CommentPlugin_excludePrivate_accessor_storage, "f"); }
set excludePrivate(value) { __classPrivateFieldSet(this, _CommentPlugin_excludePrivate_accessor_storage, value, "f"); }
get excludeProtected() { return __classPrivateFieldGet(this, _CommentPlugin_excludeProtected_accessor_storage, "f"); }
set excludeProtected(value) { __classPrivateFieldSet(this, _CommentPlugin_excludeProtected_accessor_storage, value, "f"); }
get excludeNotDocumented() { return __classPrivateFieldGet(this, _CommentPlugin_excludeNotDocumented_accessor_storage, "f"); }
set excludeNotDocumented(value) { __classPrivateFieldSet(this, _CommentPlugin_excludeNotDocumented_accessor_storage, value, "f"); }
get excludeCategories() { return __classPrivateFieldGet(this, _CommentPlugin_excludeCategories_accessor_storage, "f"); }
set excludeCategories(value) { __classPrivateFieldSet(this, _CommentPlugin_excludeCategories_accessor_storage, value, "f"); }
get defaultCategory() { return __classPrivateFieldGet(this, _CommentPlugin_defaultCategory_accessor_storage, "f"); }
set defaultCategory(value) { __classPrivateFieldSet(this, _CommentPlugin_defaultCategory_accessor_storage, value, "f"); }
get excludeNotDocumentedKinds() {
this._excludeKinds ??= this.application.options
.getValue("excludeNotDocumentedKinds")
.reduce((a, b) => a | models_1.ReflectionKind[b], 0);
return this._excludeKinds;
}
/**
* Create a new CommentPlugin instance.
*/
initialize() {
this.listenTo(this.owner, {
[converter_1.Converter.EVENT_CREATE_DECLARATION]: this.onDeclaration,
[converter_1.Converter.EVENT_CREATE_SIGNATURE]: this.onDeclaration,
[converter_1.Converter.EVENT_CREATE_TYPE_PARAMETER]: this.onCreateTypeParameter,
[converter_1.Converter.EVENT_RESOLVE_BEGIN]: this.onBeginResolve,
[converter_1.Converter.EVENT_RESOLVE]: this.onResolve,
[converter_1.Converter.EVENT_END]: () => {
this._excludeKinds = undefined;
},
});
}
/**
* Apply all comment tag modifiers to the given reflection.
*
* @param reflection The reflection the modifiers should be applied to.
* @param comment The comment that should be searched for modifiers.
*/
applyModifiers(reflection, comment) {
if (reflection.kindOf(models_1.ReflectionKind.SomeModule)) {
comment.removeModifier("@namespace");
}
if (reflection.kindOf(models_1.ReflectionKind.Interface)) {
comment.removeModifier("@interface");
}
if (comment.hasModifier("@private")) {
reflection.setFlag(models_1.ReflectionFlag.Private);
if (reflection.kindOf(models_1.ReflectionKind.CallSignature)) {
reflection.parent?.setFlag(models_1.ReflectionFlag.Private);
}
comment.removeModifier("@private");
}
if (comment.hasModifier("@protected")) {
reflection.setFlag(models_1.ReflectionFlag.Protected);
if (reflection.kindOf(models_1.ReflectionKind.CallSignature)) {
reflection.parent?.setFlag(models_1.ReflectionFlag.Protected);
}
comment.removeModifier("@protected");
}
if (comment.hasModifier("@public")) {
reflection.setFlag(models_1.ReflectionFlag.Public);
if (reflection.kindOf(models_1.ReflectionKind.CallSignature)) {
reflection.parent?.setFlag(models_1.ReflectionFlag.Public);
}
comment.removeModifier("@public");
}
if (comment.hasModifier("@readonly")) {
const target = reflection.kindOf(models_1.ReflectionKind.GetSignature)
? reflection.parent
: reflection;
target.setFlag(models_1.ReflectionFlag.Readonly);
comment.removeModifier("@readonly");
}
if (comment.hasModifier("@event") ||
comment.hasModifier("@eventProperty")) {
comment.blockTags.push(new models_1.CommentTag("@group", [{ kind: "text", text: "Events" }]));
comment.removeModifier("@event");
comment.removeModifier("@eventProperty");
}
if (reflection.kindOf(models_1.ReflectionKind.Module | models_1.ReflectionKind.Namespace) ||
reflection.kind === models_1.ReflectionKind.Project) {
comment.removeTags("@module");
comment.removeModifier("@packageDocumentation");
}
}
/**
* Triggered when the converter has created a type parameter reflection.
*
* @param context The context object describing the current state the converter is in.
* @param reflection The reflection that is currently processed.
*/
onCreateTypeParameter(_context, reflection) {
const comment = reflection.parent?.comment;
if (comment) {
let tag = comment.getIdentifiedTag(reflection.name, "@typeParam");
if (!tag) {
tag = comment.getIdentifiedTag(reflection.name, "@template");
}
if (!tag) {
tag = comment.getIdentifiedTag(`<${reflection.name}>`, "@param");
}
if (!tag) {
tag = comment.getIdentifiedTag(reflection.name, "@param");
}
if (tag) {
reflection.comment = new models_1.Comment(tag.content);
(0, utils_1.removeIfPresent)(comment.blockTags, tag);
}
}
}
/**
* Triggered when the converter has created a declaration or signature reflection.
*
* Invokes the comment parser.
*
* @param context The context object describing the current state the converter is in.
* @param reflection The reflection that is currently processed.
* @param node The node that is currently processed if available.
*/
onDeclaration(_context, reflection) {
const comment = reflection.comment;
if (!comment)
return;
if (reflection.kindOf(models_1.ReflectionKind.SomeModule)) {
const tag = comment.getTag("@module");
if (tag) {
// If no name is specified, this is a flag to mark a comment as a module comment
// and should not result in a reflection rename.
const newName = models_1.Comment.combineDisplayParts(tag.content).trim();
if (newName.length && !newName.includes("\n")) {
reflection.name = newName;
}
(0, utils_1.removeIfPresent)(comment.blockTags, tag);
}
}
this.applyModifiers(reflection, comment);
this.removeExcludedTags(comment);
}
/**
* Triggered when the converter begins resolving a project.
*
* @param context The context object describing the current state the converter is in.
*/
onBeginResolve(context) {
const project = context.project;
const reflections = Object.values(project.reflections);
// Remove hidden reflections
const hidden = new Set();
for (const ref of reflections) {
if (ref.kindOf(models_1.ReflectionKind.Accessor) && ref.flags.isReadonly) {
const decl = ref;
if (decl.setSignature) {
hidden.add(decl.setSignature);
}
// Clear flag set by @readonly since it shouldn't be rendered.
ref.setFlag(models_1.ReflectionFlag.Readonly, false);
}
if (this.isHidden(ref)) {
hidden.add(ref);
}
}
hidden.forEach((reflection) => project.removeReflection(reflection));
// remove functions with empty signatures after their signatures have been removed
const [allRemoved, someRemoved] = (0, utils_1.partition)((0, utils_1.unique)((0, utils_1.filterMap)(hidden, (reflection) => reflection.parent?.kindOf(models_1.ReflectionKind.SignatureContainer)
? reflection.parent
: void 0)), (method) => method.getNonIndexSignatures().length === 0);
allRemoved.forEach((reflection) => {
project.removeReflection(reflection);
});
someRemoved.forEach((reflection) => {
reflection.sources = reflection
.getNonIndexSignatures()
.flatMap((s) => s.sources ?? []);
});
}
/**
* Triggered when the converter resolves a reflection.
*
* Cleans up comment tags related to signatures like `@param` or `@returns`
* and moves their data to the corresponding parameter reflections.
*
* This hook also copies over the comment of function implementations to their
* signatures.
*
* @param context The context object describing the current state the converter is in.
* @param reflection The reflection that is currently resolved.
*/
onResolve(context, reflection) {
if (reflection.comment) {
if (reflection.comment.label &&
!/[A-Z_][A-Z0-9_]/.test(reflection.comment.label)) {
context.logger.warn(`The label "${reflection.comment.label}" for ${reflection.getFriendlyFullName()} cannot be referenced with a declaration reference. ` +
`Labels may only contain A-Z, 0-9, and _, and may not start with a number.`);
}
mergeSeeTags(reflection.comment);
movePropertyTags(reflection.comment, reflection);
}
if (!(reflection instanceof models_1.DeclarationReflection)) {
return;
}
if (reflection.type instanceof models_1.ReflectionType) {
this.moveCommentToSignatures(reflection, reflection.type.declaration.getNonIndexSignatures());
}
else {
this.moveCommentToSignatures(reflection, reflection.getNonIndexSignatures());
}
}
moveCommentToSignatures(reflection, signatures) {
if (!signatures.length) {
return;
}
const comment = reflection.kindOf(models_1.ReflectionKind.ClassOrInterface)
? undefined
: reflection.comment;
for (const signature of signatures) {
const signatureHadOwnComment = !!signature.comment;
const childComment = (signature.comment ||= comment?.clone());
if (!childComment)
continue;
signature.parameters?.forEach((parameter, index) => {
if (parameter.name === "__namedParameters") {
const commentParams = childComment.blockTags.filter((tag) => tag.tag === "@param" && !tag.name?.includes("."));
if (signature.parameters?.length === commentParams.length &&
commentParams[index].name) {
parameter.name = commentParams[index].name;
}
}
const tag = childComment.getIdentifiedTag(parameter.name, "@param");
if (tag) {
parameter.comment = new models_1.Comment(models_1.Comment.cloneDisplayParts(tag.content));
}
});
for (const parameter of signature.typeParameters || []) {
const tag = childComment.getIdentifiedTag(parameter.name, "@typeParam") ||
childComment.getIdentifiedTag(parameter.name, "@template") ||
childComment.getIdentifiedTag(`<${parameter.name}>`, "@param");
if (tag) {
parameter.comment = new models_1.Comment(models_1.Comment.cloneDisplayParts(tag.content));
}
}
this.validateParamTags(signature, childComment, signature.parameters || [], signatureHadOwnComment);
childComment?.removeTags("@param");
childComment?.removeTags("@typeParam");
childComment?.removeTags("@template");
}
// Since this reflection has signatures, we need to remove the comment from the non-primary
// declaration location. For functions/methods/constructors, this means removing it from
// the wrapping reflection. For type aliases, classes, and interfaces, this means removing
// it from the contained signatures... if it's the same as what is on the signature.
// This is important so that in type aliases we don't end up with a comment rendered twice.
if (reflection.kindOf(models_1.ReflectionKind.SignatureContainer)) {
delete reflection.comment;
}
else {
reflection.comment?.removeTags("@param");
reflection.comment?.removeTags("@typeParam");
reflection.comment?.removeTags("@template");
const parentComment = models_1.Comment.combineDisplayParts(reflection.comment?.summary);
for (const sig of signatures) {
if (models_1.Comment.combineDisplayParts(sig.comment?.summary) ===
parentComment) {
delete sig.comment;
}
}
}
}
removeExcludedTags(comment) {
for (const tag of NEVER_RENDERED) {
comment.removeTags(tag);
comment.removeModifier(tag);
}
for (const tag of this.excludeTags) {
comment.removeTags(tag);
comment.removeModifier(tag);
}
}
/**
* Determines whether or not a reflection has been hidden
*
* @param reflection Reflection to check if hidden
*/
isHidden(reflection) {
const comment = reflection.comment;
if (reflection.flags.hasFlag(models_1.ReflectionFlag.Private) &&
this.excludePrivate) {
return true;
}
if (reflection.flags.hasFlag(models_1.ReflectionFlag.Protected) &&
this.excludeProtected) {
return true;
}
if (this.excludedByCategory(reflection)) {
return true;
}
if (!comment) {
// We haven't moved comments from the parent for signatures without a direct
// comment, so don't exclude those due to not being documented.
if (reflection.kindOf(models_1.ReflectionKind.CallSignature |
models_1.ReflectionKind.ConstructorSignature) &&
reflection.parent?.comment) {
return false;
}
if (this.excludeNotDocumented) {
// Don't let excludeNotDocumented remove parameters.
if (!(reflection instanceof models_1.DeclarationReflection) &&
!(reflection instanceof models_1.SignatureReflection)) {
return false;
}
if (!reflection.kindOf(this.excludeNotDocumentedKinds)) {
return false;
}
// excludeNotDocumented should hide a module only if it has no visible children
if (reflection.kindOf(models_1.ReflectionKind.SomeModule)) {
if (!reflection.children) {
return true;
}
return reflection.children.every((child) => this.isHidden(child));
}
// signature containers should only be hidden if all their signatures are hidden
if (reflection.kindOf(models_1.ReflectionKind.SignatureContainer)) {
return reflection
.getAllSignatures()
.every((child) => this.isHidden(child));
}
// excludeNotDocumented should never hide parts of "type" reflections
return inTypeLiteral(reflection) === false;
}
return false;
}
const isHidden = comment.hasModifier("@hidden") ||
comment.hasModifier("@ignore") ||
(comment.hasModifier("@internal") && this.excludeInternal);
if (isHidden &&
reflection.kindOf(models_1.ReflectionKind.ContainsCallSignatures)) {
return reflection
.getNonIndexSignatures()
.every((sig) => {
return !sig.comment || this.isHidden(sig);
});
}
return isHidden;
}
excludedByCategory(reflection) {
const excludeCategories = this.excludeCategories;
let target;
if (reflection instanceof models_1.DeclarationReflection) {
target = reflection;
}
else if (reflection instanceof models_1.SignatureReflection) {
target = reflection.parent;
}
if (!target || !excludeCategories.length)
return false;
const categories = CategoryPlugin_1.CategoryPlugin.getCategories(target);
if (categories.size === 0) {
categories.add(this.defaultCategory);
}
return excludeCategories.some((cat) => categories.has(cat));
}
validateParamTags(signature, comment, params, signatureHadOwnComment) {
const paramTags = comment.blockTags.filter((tag) => tag.tag === "@param");
(0, utils_1.removeIf)(paramTags, (tag) => params.some((param) => param.name === tag.name));
moveNestedParamTags(/* in-out */ paramTags, params);
if (signatureHadOwnComment && paramTags.length) {
for (const tag of paramTags) {
this.application.logger.warn(`The signature ${signature.getFriendlyFullName()} has an @param with name "${tag.name}", which was not used.`);
}
}
}
};
_CommentPlugin_excludeTags_accessor_storage = new WeakMap();
_CommentPlugin_excludeInternal_accessor_storage = new WeakMap();
_CommentPlugin_excludePrivate_accessor_storage = new WeakMap();
_CommentPlugin_excludeProtected_accessor_storage = new WeakMap();
_CommentPlugin_excludeNotDocumented_accessor_storage = new WeakMap();
_CommentPlugin_excludeCategories_accessor_storage = new WeakMap();
_CommentPlugin_defaultCategory_accessor_storage = new WeakMap();
__setFunctionName(_classThis, "CommentPlugin");
(() => {
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
_excludeTags_decorators = [(0, utils_1.Option)("excludeTags")];
_excludeInternal_decorators = [(0, utils_1.Option)("excludeInternal")];
_excludePrivate_decorators = [(0, utils_1.Option)("excludePrivate")];
_excludeProtected_decorators = [(0, utils_1.Option)("excludeProtected")];
_excludeNotDocumented_decorators = [(0, utils_1.Option)("excludeNotDocumented")];
_excludeCategories_decorators = [(0, utils_1.Option)("excludeCategories")];
_defaultCategory_decorators = [(0, utils_1.Option)("defaultCategory")];
__esDecorate(_classThis, null, _excludeTags_decorators, { kind: "accessor", name: "excludeTags", static: false, private: false, access: { has: obj => "excludeTags" in obj, get: obj => obj.excludeTags, set: (obj, value) => { obj.excludeTags = value; } }, metadata: _metadata }, _excludeTags_initializers, _excludeTags_extraInitializers);
__esDecorate(_classThis, null, _excludeInternal_decorators, { kind: "accessor", name: "excludeInternal", static: false, private: false, access: { has: obj => "excludeInternal" in obj, get: obj => obj.excludeInternal, set: (obj, value) => { obj.excludeInternal = value; } }, metadata: _metadata }, _excludeInternal_initializers, _excludeInternal_extraInitializers);
__esDecorate(_classThis, null, _excludePrivate_decorators, { kind: "accessor", name: "excludePrivate", static: false, private: false, access: { has: obj => "excludePrivate" in obj, get: obj => obj.excludePrivate, set: (obj, value) => { obj.excludePrivate = value; } }, metadata: _metadata }, _excludePrivate_initializers, _excludePrivate_extraInitializers);
__esDecorate(_classThis, null, _excludeProtected_decorators, { kind: "accessor", name: "excludeProtected", static: false, private: false, access: { has: obj => "excludeProtected" in obj, get: obj => obj.excludeProtected, set: (obj, value) => { obj.excludeProtected = value; } }, metadata: _metadata }, _excludeProtected_initializers, _excludeProtected_extraInitializers);
__esDecorate(_classThis, null, _excludeNotDocumented_decorators, { kind: "accessor", name: "excludeNotDocumented", static: false, private: false, access: { has: obj => "excludeNotDocumented" in obj, get: obj => obj.excludeNotDocumented, set: (obj, value) => { obj.excludeNotDocumented = value; } }, metadata: _metadata }, _excludeNotDocumented_initializers, _excludeNotDocumented_extraInitializers);
__esDecorate(_classThis, null, _excludeCategories_decorators, { kind: "accessor", name: "excludeCategories", static: false, private: false, access: { has: obj => "excludeCategories" in obj, get: obj => obj.excludeCategories, set: (obj, value) => { obj.excludeCategories = value; } }, metadata: _metadata }, _excludeCategories_initializers, _excludeCategories_extraInitializers);
__esDecorate(_classThis, null, _defaultCategory_decorators, { kind: "accessor", name: "defaultCategory", static: false, private: false, access: { has: obj => "defaultCategory" in obj, get: obj => obj.defaultCategory, set: (obj, value) => { obj.defaultCategory = value; } }, metadata: _metadata }, _defaultCategory_initializers, _defaultCategory_extraInitializers);
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
CommentPlugin = _classThis = _classDescriptor.value;
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
__runInitializers(_classThis, _classExtraInitializers);
})();
return CommentPlugin = _classThis;
})();
exports.CommentPlugin = CommentPlugin;
function inTypeLiteral(refl) {
while (refl) {
if (refl.kind === models_1.ReflectionKind.TypeLiteral) {
return true;
}
refl = refl.parent;
}
return false;
}
// Moves tags like `@param foo.bar docs for bar` into the `bar` property of the `foo` parameter.
function moveNestedParamTags(
/* in-out */ paramTags, parameters) {
const used = new Set();
for (const param of parameters) {
const visitor = {
reflection(target) {
const tags = paramTags.filter((t) => t.name?.startsWith(`${param.name}.`));
for (const tag of tags) {
const path = tag.name.split(".");
path.shift();
const child = target.declaration.getChildByName(path);
if (child && !child.comment) {
child.comment = new models_1.Comment(models_1.Comment.cloneDisplayParts(tag.content));
used.add(paramTags.indexOf(tag));
}
}
},
// #1876, also do this for unions/intersections.
union(u) {
u.types.forEach((t) => t.visit(visitor));
},
intersection(i) {
i.types.forEach((t) => t.visit(visitor));
},
};
param.type?.visit(visitor);
}
const toRemove = Array.from(used)
.sort((a, b) => a - b)
.reverse();
for (const index of toRemove) {
paramTags.splice(index, 1);
}
}
function movePropertyTags(comment, container) {
const propTags = comment.blockTags.filter((tag) => tag.tag === "@prop" || tag.tag === "@property");
comment.removeTags("@prop");
comment.removeTags("@property");
for (const prop of propTags) {
if (!prop.name)
continue;
const child = container.getChildByName(prop.name);
if (child) {
child.comment = new models_1.Comment(models_1.Comment.cloneDisplayParts(prop.content));
if (child instanceof models_1.DeclarationReflection && child.signatures) {
for (const sig of child.signatures) {
sig.comment = new models_1.Comment(models_1.Comment.cloneDisplayParts(prop.content));
}
}
}
}
}
function mergeSeeTags(comment) {
const see = comment.getTags("@see");
if (see.length < 2)
return;
const index = comment.blockTags.indexOf(see[0]);
comment.removeTags("@see");
see[0].content = see.flatMap((part) => [
{ kind: "text", text: " - " },
...part.content,
{ kind: "text", text: "\n" },
]);
comment.blockTags.splice(index, 0, see[0]);
}

View File

@@ -0,0 +1,47 @@
import { ContainerReflection, DeclarationReflection } from "../../models/reflections/index";
import { ReflectionGroup } from "../../models/ReflectionGroup";
import { ConverterComponent } from "../components";
/**
* A handler that sorts and groups the found reflections in the resolving phase.
*
* The handler sets the `groups` property of all container reflections.
*/
export declare class GroupPlugin extends ConverterComponent {
sortFunction: (reflections: DeclarationReflection[]) => void;
accessor boosts: Record<string, number>;
accessor groupOrder: string[];
accessor sortEntryPoints: boolean;
usedBoosts: Set<string>;
static WEIGHTS: string[];
/**
* Create a new GroupPlugin instance.
*/
initialize(): void;
/**
* Triggered when the converter has finished resolving a project.
*
* @param context The context object describing the current state the converter is in.
*/
private onEndResolve;
private group;
/**
* Extracts the groups for a given reflection.
*
* @privateRemarks
* If you change this, also update extractCategories in CategoryPlugin accordingly.
*/
getGroups(reflection: DeclarationReflection): Set<string>;
/**
* Create a grouped representation of the given list of reflections.
*
* Reflections are grouped by kind and sorted by weight and name.
*
* @param reflections The reflections that should be grouped.
* @returns An array containing all children of the given reflection grouped by their kind.
*/
getReflectionGroups(parent: ContainerReflection, reflections: DeclarationReflection[]): ReflectionGroup[];
/**
* Callback used to sort groups by name.
*/
static sortGroupCallback(a: ReflectionGroup, b: ReflectionGroup): number;
}

View File

@@ -0,0 +1,268 @@
"use strict";
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
var _, done = false;
for (var i = decorators.length - 1; i >= 0; i--) {
var context = {};
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
if (kind === "accessor") {
if (result === void 0) continue;
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
if (_ = accept(result.get)) descriptor.get = _;
if (_ = accept(result.set)) descriptor.set = _;
if (_ = accept(result.init)) initializers.unshift(_);
}
else if (_ = accept(result)) {
if (kind === "field") initializers.unshift(_);
else descriptor[key] = _;
}
}
if (target) Object.defineProperty(target, contextIn.name, descriptor);
done = true;
};
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
var useValue = arguments.length > 2;
for (var i = 0; i < initializers.length; i++) {
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
}
return useValue ? value : void 0;
};
var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.GroupPlugin = void 0;
const index_1 = require("../../models/reflections/index");
const ReflectionGroup_1 = require("../../models/ReflectionGroup");
const components_1 = require("../components");
const converter_1 = require("../converter");
const sort_1 = require("../../utils/sort");
const utils_1 = require("../../utils");
const models_1 = require("../../models");
/**
* A handler that sorts and groups the found reflections in the resolving phase.
*
* The handler sets the `groups` property of all container reflections.
*/
let GroupPlugin = (() => {
var _GroupPlugin_boosts_accessor_storage, _GroupPlugin_groupOrder_accessor_storage, _GroupPlugin_sortEntryPoints_accessor_storage;
let _classDecorators = [(0, components_1.Component)({ name: "group" })];
let _classDescriptor;
let _classExtraInitializers = [];
let _classThis;
let _classSuper = components_1.ConverterComponent;
let _boosts_decorators;
let _boosts_initializers = [];
let _boosts_extraInitializers = [];
let _groupOrder_decorators;
let _groupOrder_initializers = [];
let _groupOrder_extraInitializers = [];
let _sortEntryPoints_decorators;
let _sortEntryPoints_initializers = [];
let _sortEntryPoints_extraInitializers = [];
var GroupPlugin = _classThis = class extends _classSuper {
constructor() {
super(...arguments);
_GroupPlugin_boosts_accessor_storage.set(this, __runInitializers(this, _boosts_initializers, void 0));
_GroupPlugin_groupOrder_accessor_storage.set(this, (__runInitializers(this, _boosts_extraInitializers), __runInitializers(this, _groupOrder_initializers, void 0)));
_GroupPlugin_sortEntryPoints_accessor_storage.set(this, (__runInitializers(this, _groupOrder_extraInitializers), __runInitializers(this, _sortEntryPoints_initializers, void 0)));
this.usedBoosts = (__runInitializers(this, _sortEntryPoints_extraInitializers), new Set());
}
get boosts() { return __classPrivateFieldGet(this, _GroupPlugin_boosts_accessor_storage, "f"); }
set boosts(value) { __classPrivateFieldSet(this, _GroupPlugin_boosts_accessor_storage, value, "f"); }
get groupOrder() { return __classPrivateFieldGet(this, _GroupPlugin_groupOrder_accessor_storage, "f"); }
set groupOrder(value) { __classPrivateFieldSet(this, _GroupPlugin_groupOrder_accessor_storage, value, "f"); }
get sortEntryPoints() { return __classPrivateFieldGet(this, _GroupPlugin_sortEntryPoints_accessor_storage, "f"); }
set sortEntryPoints(value) { __classPrivateFieldSet(this, _GroupPlugin_sortEntryPoints_accessor_storage, value, "f"); }
/**
* Create a new GroupPlugin instance.
*/
initialize() {
this.listenTo(this.owner, {
[converter_1.Converter.EVENT_RESOLVE_BEGIN]: () => {
this.sortFunction = (0, sort_1.getSortFunction)(this.application.options);
GroupPlugin.WEIGHTS = this.groupOrder;
},
[converter_1.Converter.EVENT_RESOLVE_END]: this.onEndResolve,
}, undefined, -100);
}
/**
* Triggered when the converter has finished resolving a project.
*
* @param context The context object describing the current state the converter is in.
*/
onEndResolve(context) {
this.group(context.project);
for (const id in context.project.reflections) {
const reflection = context.project.reflections[id];
if (reflection instanceof index_1.ContainerReflection) {
this.group(reflection);
}
}
const unusedBoosts = new Set(Object.keys(this.boosts));
for (const boost of this.usedBoosts) {
unusedBoosts.delete(boost);
}
this.usedBoosts.clear();
if (unusedBoosts.size &&
this.application.options.isSet("searchGroupBoosts")) {
context.logger.warn(`Not all groups specified in searchGroupBoosts were used in the documentation.` +
` The unused groups were:\n\t${Array.from(unusedBoosts).join("\n\t")}`);
}
}
group(reflection) {
if (reflection.children &&
reflection.children.length > 0 &&
!reflection.groups) {
if (this.sortEntryPoints ||
!reflection.children.some((c) => c.kindOf(index_1.ReflectionKind.Module))) {
this.sortFunction(reflection.children);
}
reflection.groups = this.getReflectionGroups(reflection, reflection.children);
}
}
/**
* Extracts the groups for a given reflection.
*
* @privateRemarks
* If you change this, also update extractCategories in CategoryPlugin accordingly.
*/
getGroups(reflection) {
const groups = new Set();
function extractGroupTags(comment) {
if (!comment)
return;
(0, utils_1.removeIf)(comment.blockTags, (tag) => {
if (tag.tag === "@group") {
groups.add(models_1.Comment.combineDisplayParts(tag.content).trim());
return true;
}
return false;
});
}
extractGroupTags(reflection.comment);
for (const sig of reflection.getNonIndexSignatures()) {
extractGroupTags(sig.comment);
}
if (reflection.type?.type === "reflection") {
extractGroupTags(reflection.type.declaration.comment);
for (const sig of reflection.type.declaration.getNonIndexSignatures()) {
extractGroupTags(sig.comment);
}
}
groups.delete("");
if (groups.size === 0) {
groups.add(index_1.ReflectionKind.pluralString(reflection.kind));
}
for (const group of groups) {
if (group in this.boosts) {
this.usedBoosts.add(group);
reflection.relevanceBoost =
(reflection.relevanceBoost ?? 1) * this.boosts[group];
}
}
return groups;
}
/**
* Create a grouped representation of the given list of reflections.
*
* Reflections are grouped by kind and sorted by weight and name.
*
* @param reflections The reflections that should be grouped.
* @returns An array containing all children of the given reflection grouped by their kind.
*/
getReflectionGroups(parent, reflections) {
const groups = new Map();
reflections.forEach((child) => {
for (const name of this.getGroups(child)) {
let group = groups.get(name);
if (!group) {
group = new ReflectionGroup_1.ReflectionGroup(name, child);
groups.set(name, group);
}
group.children.push(child);
}
});
if (parent.comment) {
(0, utils_1.removeIf)(parent.comment.blockTags, (tag) => {
if (tag.tag === "@groupDescription") {
const { header, body } = models_1.Comment.splitPartsToHeaderAndBody(tag.content);
const cat = groups.get(header);
if (cat) {
cat.description = body;
}
else {
this.application.logger.warn(`Comment for ${parent.getFriendlyFullName()} includes @groupDescription for "${header}", but no child is placed in that group.`);
}
return true;
}
return false;
});
}
return Array.from(groups.values()).sort(GroupPlugin.sortGroupCallback);
}
/**
* Callback used to sort groups by name.
*/
static sortGroupCallback(a, b) {
let aWeight = GroupPlugin.WEIGHTS.indexOf(a.title);
let bWeight = GroupPlugin.WEIGHTS.indexOf(b.title);
if (aWeight === -1 || bWeight === -1) {
let asteriskIndex = GroupPlugin.WEIGHTS.indexOf("*");
if (asteriskIndex === -1) {
asteriskIndex = GroupPlugin.WEIGHTS.length;
}
if (aWeight === -1) {
aWeight = asteriskIndex;
}
if (bWeight === -1) {
bWeight = asteriskIndex;
}
}
if (aWeight === bWeight) {
return a.title > b.title ? 1 : -1;
}
return aWeight - bWeight;
}
};
_GroupPlugin_boosts_accessor_storage = new WeakMap();
_GroupPlugin_groupOrder_accessor_storage = new WeakMap();
_GroupPlugin_sortEntryPoints_accessor_storage = new WeakMap();
__setFunctionName(_classThis, "GroupPlugin");
(() => {
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
_boosts_decorators = [(0, utils_1.Option)("searchGroupBoosts")];
_groupOrder_decorators = [(0, utils_1.Option)("groupOrder")];
_sortEntryPoints_decorators = [(0, utils_1.Option)("sortEntryPoints")];
__esDecorate(_classThis, null, _boosts_decorators, { kind: "accessor", name: "boosts", static: false, private: false, access: { has: obj => "boosts" in obj, get: obj => obj.boosts, set: (obj, value) => { obj.boosts = value; } }, metadata: _metadata }, _boosts_initializers, _boosts_extraInitializers);
__esDecorate(_classThis, null, _groupOrder_decorators, { kind: "accessor", name: "groupOrder", static: false, private: false, access: { has: obj => "groupOrder" in obj, get: obj => obj.groupOrder, set: (obj, value) => { obj.groupOrder = value; } }, metadata: _metadata }, _groupOrder_initializers, _groupOrder_extraInitializers);
__esDecorate(_classThis, null, _sortEntryPoints_decorators, { kind: "accessor", name: "sortEntryPoints", static: false, private: false, access: { has: obj => "sortEntryPoints" in obj, get: obj => obj.sortEntryPoints, set: (obj, value) => { obj.sortEntryPoints = value; } }, metadata: _metadata }, _sortEntryPoints_initializers, _sortEntryPoints_extraInitializers);
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
GroupPlugin = _classThis = _classDescriptor.value;
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
})();
_classThis.WEIGHTS = [];
(() => {
__runInitializers(_classThis, _classExtraInitializers);
})();
return GroupPlugin = _classThis;
})();
exports.GroupPlugin = GroupPlugin;

View File

@@ -0,0 +1,31 @@
import { ConverterComponent } from "../components";
/**
* A plugin that detects interface implementations of functions and
* properties on classes and links them.
*/
export declare class ImplementsPlugin extends ConverterComponent {
private resolved;
private postponed;
/**
* Create a new ImplementsPlugin instance.
*/
initialize(): void;
/**
* Mark all members of the given class to be the implementation of the matching interface member.
*/
private analyzeImplements;
private analyzeInheritance;
private onResolveEnd;
private resolve;
private tryResolve;
private doResolve;
private getExtensionInfo;
private onSignature;
/**
* Responsible for setting the {@link DeclarationReflection.inheritedFrom},
* {@link DeclarationReflection.overwrites}, and {@link DeclarationReflection.implementationOf}
* properties on the provided reflection temporarily, these links will be replaced
* during the resolve step with links which actually point to the right place.
*/
private onDeclaration;
}

View File

@@ -0,0 +1,400 @@
"use strict";
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
var _, done = false;
for (var i = decorators.length - 1; i >= 0; i--) {
var context = {};
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
if (kind === "accessor") {
if (result === void 0) continue;
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
if (_ = accept(result.get)) descriptor.get = _;
if (_ = accept(result.set)) descriptor.set = _;
if (_ = accept(result.init)) initializers.unshift(_);
}
else if (_ = accept(result)) {
if (kind === "field") initializers.unshift(_);
else descriptor[key] = _;
}
}
if (target) Object.defineProperty(target, contextIn.name, descriptor);
done = true;
};
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
var useValue = arguments.length > 2;
for (var i = 0; i < initializers.length; i++) {
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
}
return useValue ? value : void 0;
};
var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ImplementsPlugin = void 0;
const typescript_1 = __importDefault(require("typescript"));
const application_events_1 = require("../../application-events");
const index_1 = require("../../models/reflections/index");
const types_1 = require("../../models/types");
const array_1 = require("../../utils/array");
const components_1 = require("../components");
const converter_1 = require("../converter");
const utils_1 = require("../../utils");
/**
* A plugin that detects interface implementations of functions and
* properties on classes and links them.
*/
let ImplementsPlugin = (() => {
let _classDecorators = [(0, components_1.Component)({ name: "implements" })];
let _classDescriptor;
let _classExtraInitializers = [];
let _classThis;
let _classSuper = components_1.ConverterComponent;
var ImplementsPlugin = _classThis = class extends _classSuper {
constructor() {
super(...arguments);
this.resolved = new WeakSet();
this.postponed = new WeakMap();
}
/**
* Create a new ImplementsPlugin instance.
*/
initialize() {
this.listenTo(this.owner, converter_1.Converter.EVENT_RESOLVE_END, this.onResolveEnd);
this.listenTo(this.owner, converter_1.Converter.EVENT_CREATE_DECLARATION, this.onDeclaration, -1000);
this.listenTo(this.owner, converter_1.Converter.EVENT_CREATE_SIGNATURE, this.onSignature, 1000);
this.listenTo(this.application, application_events_1.ApplicationEvents.REVIVE, this.resolve);
}
/**
* Mark all members of the given class to be the implementation of the matching interface member.
*/
analyzeImplements(project, classReflection, interfaceReflection) {
handleInheritedComments(classReflection, interfaceReflection);
if (!interfaceReflection.children) {
return;
}
interfaceReflection.children.forEach((interfaceMember) => {
const classMember = findMatchingMember(interfaceMember, classReflection);
if (!classMember) {
return;
}
const interfaceMemberName = interfaceReflection.name + "." + interfaceMember.name;
classMember.implementationOf =
types_1.ReferenceType.createResolvedReference(interfaceMemberName, interfaceMember, project);
const intSigs = interfaceMember.signatures ||
interfaceMember.type?.visit({
reflection: (r) => r.declaration.signatures,
});
const clsSigs = classMember.signatures ||
classMember.type?.visit({
reflection: (r) => r.declaration.signatures,
});
if (intSigs && clsSigs) {
for (const [clsSig, intSig] of (0, array_1.zip)(clsSigs, intSigs)) {
if (clsSig.implementationOf) {
const target = intSig.parent.kindOf(index_1.ReflectionKind.FunctionOrMethod)
? intSig
: intSig.parent.parent;
clsSig.implementationOf =
types_1.ReferenceType.createResolvedReference(clsSig.implementationOf.name, target, project);
}
}
}
handleInheritedComments(classMember, interfaceMember);
});
}
analyzeInheritance(project, reflection) {
const extendedTypes = (0, array_1.filterMap)(reflection.extendedTypes ?? [], (type) => {
return type instanceof types_1.ReferenceType &&
type.reflection instanceof index_1.DeclarationReflection
? type
: void 0;
});
for (const parent of extendedTypes) {
handleInheritedComments(reflection, parent.reflection);
for (const parentMember of parent.reflection.children ?? []) {
const child = findMatchingMember(parentMember, reflection);
if (child) {
const key = child.overwrites
? "overwrites"
: "inheritedFrom";
for (const [childSig, parentSig] of (0, array_1.zip)(child.signatures ?? [], parentMember.signatures ?? [])) {
childSig[key] = types_1.ReferenceType.createResolvedReference(`${parent.name}.${parentMember.name}`, parentSig, project);
}
child[key] = types_1.ReferenceType.createResolvedReference(`${parent.name}.${parentMember.name}`, parentMember, project);
handleInheritedComments(child, parentMember);
}
}
}
}
onResolveEnd(context) {
this.resolve(context.project);
}
resolve(project) {
for (const id in project.reflections) {
const refl = project.reflections[id];
if (refl instanceof index_1.DeclarationReflection) {
this.tryResolve(project, refl);
}
}
}
tryResolve(project, reflection) {
const requirements = (0, array_1.filterMap)([
...(reflection.implementedTypes ?? []),
...(reflection.extendedTypes ?? []),
], (type) => {
return type instanceof types_1.ReferenceType ? type.reflection : void 0;
});
if (requirements.every((req) => this.resolved.has(req))) {
this.doResolve(project, reflection);
this.resolved.add(reflection);
for (const refl of this.postponed.get(reflection) ?? []) {
this.tryResolve(project, refl);
}
this.postponed.delete(reflection);
}
else {
for (const req of requirements) {
const future = this.postponed.get(req) ?? new Set();
future.add(reflection);
this.postponed.set(req, future);
}
}
}
doResolve(project, reflection) {
if (reflection.kindOf(index_1.ReflectionKind.Class) &&
reflection.implementedTypes) {
reflection.implementedTypes.forEach((type) => {
if (!(type instanceof types_1.ReferenceType)) {
return;
}
if (type.reflection &&
type.reflection.kindOf(index_1.ReflectionKind.ClassOrInterface)) {
this.analyzeImplements(project, reflection, type.reflection);
}
});
}
if (reflection.kindOf(index_1.ReflectionKind.ClassOrInterface) &&
reflection.extendedTypes) {
this.analyzeInheritance(project, reflection);
}
}
getExtensionInfo(context, reflection) {
if (!reflection || !reflection.kindOf(index_1.ReflectionKind.Inheritable)) {
return;
}
// Need this because we re-use reflections for type literals.
if (!reflection.parent?.kindOf(index_1.ReflectionKind.ClassOrInterface)) {
return;
}
const symbol = context.project.getSymbolFromReflection(reflection.parent);
if (!symbol) {
return;
}
const declaration = symbol
.getDeclarations()
?.find((n) => typescript_1.default.isClassDeclaration(n) || typescript_1.default.isInterfaceDeclaration(n));
if (!declaration) {
return;
}
return { symbol, declaration };
}
onSignature(context, reflection) {
this.onDeclaration(context, reflection.parent);
}
/**
* Responsible for setting the {@link DeclarationReflection.inheritedFrom},
* {@link DeclarationReflection.overwrites}, and {@link DeclarationReflection.implementationOf}
* properties on the provided reflection temporarily, these links will be replaced
* during the resolve step with links which actually point to the right place.
*/
onDeclaration(context, reflection) {
const info = this.getExtensionInfo(context, reflection);
if (!info) {
return;
}
if (reflection.kind === index_1.ReflectionKind.Constructor) {
const ctor = info.declaration.members.find(typescript_1.default.isConstructorDeclaration);
constructorInheritance(context, reflection, info.declaration, ctor);
return;
}
const childType = reflection.flags.isStatic
? context.checker.getTypeOfSymbolAtLocation(info.symbol, info.declaration)
: context.checker.getDeclaredTypeOfSymbol(info.symbol);
const property = findProperty(reflection, childType);
if (!property) {
// We're probably broken... but I don't think this should be fatal.
context.logger.warn(`Failed to retrieve${reflection.flags.isStatic ? " static" : ""} member "${reflection.escapedName ?? reflection.name}" of "${reflection.parent
?.name}" for inheritance analysis. Please report a bug.`);
return;
}
// Need to check both extends and implements clauses.
out: for (const clause of info.declaration.heritageClauses ?? []) {
// No point checking implemented types for static members, they won't exist.
if (reflection.flags.isStatic &&
clause.token === typescript_1.default.SyntaxKind.ImplementsKeyword) {
continue;
}
for (const expr of clause.types) {
const parentType = context.checker.getTypeAtLocation(reflection.flags.isStatic ? expr.expression : expr);
const parentProperty = findProperty(reflection, parentType);
if (parentProperty) {
const isInherit = property
.getDeclarations()
?.some((d) => d.parent !== info.declaration) ??
true;
createLink(context, reflection, clause, expr, parentProperty, isInherit);
// Can't always break because we need to also set `implementationOf` if we
// inherit from a base class and also implement an interface.
if (clause.token === typescript_1.default.SyntaxKind.ImplementsKeyword) {
break out;
}
}
}
}
}
};
__setFunctionName(_classThis, "ImplementsPlugin");
(() => {
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
ImplementsPlugin = _classThis = _classDescriptor.value;
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
__runInitializers(_classThis, _classExtraInitializers);
})();
return ImplementsPlugin = _classThis;
})();
exports.ImplementsPlugin = ImplementsPlugin;
function constructorInheritance(context, reflection, childDecl, constructorDecl) {
const extendsClause = childDecl.heritageClauses?.find((cl) => cl.token === typescript_1.default.SyntaxKind.ExtendsKeyword);
if (!extendsClause)
return;
const name = `${extendsClause.types[0].getText()}.constructor`;
const key = constructorDecl ? "overwrites" : "inheritedFrom";
reflection[key] ??= types_1.ReferenceType.createBrokenReference(name, context.project);
for (const sig of reflection.signatures ?? []) {
sig[key] ??= types_1.ReferenceType.createBrokenReference(name, context.project);
}
}
function findProperty(reflection, parent) {
return parent.getProperties().find((prop) => {
return reflection.escapedName
? prop.escapedName === reflection.escapedName
: prop.name === reflection.name;
});
}
function createLink(context, reflection, clause, expr, symbol, isOverwrite) {
const project = context.project;
const name = `${expr.expression.getText()}.${(0, utils_1.getHumanName)(symbol.name)}`;
link(reflection);
link(reflection.getSignature);
link(reflection.setSignature);
link(reflection.indexSignature);
for (const sig of reflection.signatures ?? []) {
link(sig);
}
// Intentionally create broken links here. These will be replaced with real links during
// resolution if we can do so.
function link(target) {
if (!target)
return;
if (clause.token === typescript_1.default.SyntaxKind.ImplementsKeyword) {
target.implementationOf ??= types_1.ReferenceType.createBrokenReference(name, project);
return;
}
if (isOverwrite) {
target.inheritedFrom ??= types_1.ReferenceType.createBrokenReference(name, project);
}
else {
target.overwrites ??= types_1.ReferenceType.createBrokenReference(name, project);
}
}
}
/**
* Responsible for copying comments from "parent" reflections defined
* in either a base class or implemented interface to the child class.
*/
function handleInheritedComments(child, parent) {
copyComment(child, parent);
if (parent.kindOf(index_1.ReflectionKind.Property) &&
child.kindOf(index_1.ReflectionKind.Accessor)) {
if (child.getSignature) {
copyComment(child.getSignature, parent);
child.getSignature.implementationOf = child.implementationOf;
}
if (child.setSignature) {
copyComment(child.setSignature, parent);
child.setSignature.implementationOf = child.implementationOf;
}
}
if (parent.kindOf(index_1.ReflectionKind.Accessor) &&
child.kindOf(index_1.ReflectionKind.Accessor)) {
if (parent.getSignature && child.getSignature) {
copyComment(child.getSignature, parent.getSignature);
}
if (parent.setSignature && child.setSignature) {
copyComment(child.setSignature, parent.setSignature);
}
}
if (parent.kindOf(index_1.ReflectionKind.FunctionOrMethod) &&
parent.signatures &&
child.signatures) {
for (const [cs, ps] of (0, array_1.zip)(child.signatures, parent.signatures)) {
copyComment(cs, ps);
}
}
else if (parent.kindOf(index_1.ReflectionKind.Property) &&
parent.type instanceof types_1.ReflectionType &&
parent.type.declaration.signatures &&
child.signatures) {
for (const [cs, ps] of (0, array_1.zip)(child.signatures, parent.type.declaration.signatures)) {
copyComment(cs, ps);
}
}
}
/**
* Copy the comment of the source reflection to the target reflection with a JSDoc style copy
* function. The TSDoc copy function is in the InheritDocPlugin.
*/
function copyComment(target, source) {
if (target.comment) {
// We might still want to copy, if the child has a JSDoc style inheritDoc tag.
const tag = target.comment.getTag("@inheritDoc");
if (!tag || tag.name) {
return;
}
}
if (!source.comment) {
return;
}
target.comment = source.comment.clone();
if (target instanceof index_1.DeclarationReflection &&
source instanceof index_1.DeclarationReflection) {
for (const [tt, ts] of (0, array_1.zip)(target.typeParameters || [], source.typeParameters || [])) {
copyComment(tt, ts);
}
}
if (target instanceof index_1.SignatureReflection &&
source instanceof index_1.SignatureReflection) {
for (const [tt, ts] of (0, array_1.zip)(target.typeParameters || [], source.typeParameters || [])) {
copyComment(tt, ts);
}
for (const [pt, ps] of (0, array_1.zip)(target.parameters || [], source.parameters || [])) {
copyComment(pt, ps);
}
}
}
function findMatchingMember(toMatch, container) {
return container.children?.find((child) => child.name == toMatch.name &&
child.flags.isStatic === toMatch.flags.isStatic);
}

View File

@@ -0,0 +1,31 @@
import { ConverterComponent } from "../components";
import { ValidationOptions } from "../../utils";
/**
* A plugin that handles `@inheritDoc` tags by copying documentation from another API item.
* It is NOT responsible for handling bare JSDoc style `@inheritDoc` tags which do not specify
* a target to inherit from. Those are handled by the ImplementsPlugin class.
*
* What gets copied:
* - short text
* - text
* - `@remarks` block
* - `@params` block
* - `@typeParam` block
* - `@return` block
*/
export declare class InheritDocPlugin extends ConverterComponent {
accessor validation: ValidationOptions;
private dependencies;
/**
* Create a new InheritDocPlugin instance.
*/
initialize(): void;
/**
* Traverse through reflection descendant to check for `inheritDoc` tag.
* If encountered, the parameter of the tag is used to determine a source reflection
* that will provide actual comment.
*/
private processInheritDoc;
private copyComment;
private createCircularDependencyWarnings;
}

View File

@@ -0,0 +1,252 @@
"use strict";
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
var _, done = false;
for (var i = decorators.length - 1; i >= 0; i--) {
var context = {};
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
if (kind === "accessor") {
if (result === void 0) continue;
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
if (_ = accept(result.get)) descriptor.get = _;
if (_ = accept(result.set)) descriptor.set = _;
if (_ = accept(result.init)) initializers.unshift(_);
}
else if (_ = accept(result)) {
if (kind === "field") initializers.unshift(_);
else descriptor[key] = _;
}
}
if (target) Object.defineProperty(target, contextIn.name, descriptor);
done = true;
};
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
var useValue = arguments.length > 2;
for (var i = 0; i < initializers.length; i++) {
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
}
return useValue ? value : void 0;
};
var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.InheritDocPlugin = void 0;
const models_1 = require("../../models");
const components_1 = require("../components");
const converter_1 = require("../converter");
const utils_1 = require("../../utils");
const array_1 = require("../../utils/array");
const declarationReference_1 = require("../comments/declarationReference");
const declarationReferenceResolver_1 = require("../comments/declarationReferenceResolver");
const application_events_1 = require("../../application-events");
/**
* A plugin that handles `@inheritDoc` tags by copying documentation from another API item.
* It is NOT responsible for handling bare JSDoc style `@inheritDoc` tags which do not specify
* a target to inherit from. Those are handled by the ImplementsPlugin class.
*
* What gets copied:
* - short text
* - text
* - `@remarks` block
* - `@params` block
* - `@typeParam` block
* - `@return` block
*/
let InheritDocPlugin = (() => {
var _InheritDocPlugin_validation_accessor_storage;
let _classDecorators = [(0, components_1.Component)({ name: "inheritDoc" })];
let _classDescriptor;
let _classExtraInitializers = [];
let _classThis;
let _classSuper = components_1.ConverterComponent;
let _validation_decorators;
let _validation_initializers = [];
let _validation_extraInitializers = [];
var InheritDocPlugin = _classThis = class extends _classSuper {
constructor() {
super(...arguments);
_InheritDocPlugin_validation_accessor_storage.set(this, __runInitializers(this, _validation_initializers, void 0));
// Key is depended on by Values
this.dependencies = (__runInitializers(this, _validation_extraInitializers), new utils_1.DefaultMap(() => []));
}
get validation() { return __classPrivateFieldGet(this, _InheritDocPlugin_validation_accessor_storage, "f"); }
set validation(value) { __classPrivateFieldSet(this, _InheritDocPlugin_validation_accessor_storage, value, "f"); }
/**
* Create a new InheritDocPlugin instance.
*/
initialize() {
this.owner.on(converter_1.Converter.EVENT_RESOLVE_END, (context) => this.processInheritDoc(context.project));
this.application.on(application_events_1.ApplicationEvents.REVIVE, this.processInheritDoc, this);
}
/**
* Traverse through reflection descendant to check for `inheritDoc` tag.
* If encountered, the parameter of the tag is used to determine a source reflection
* that will provide actual comment.
*/
processInheritDoc(project) {
for (const id in project.reflections) {
const reflection = project.reflections[id];
const source = extractInheritDocTagReference(reflection);
if (!source)
continue;
const declRef = (0, declarationReference_1.parseDeclarationReference)(source, 0, source.length);
if (!declRef || /\S/.test(source.substring(declRef[1]))) {
this.application.logger.warn(`Declaration reference in @inheritDoc for ${reflection.getFriendlyFullName()} was not fully parsed and may resolve incorrectly.`);
}
let sourceRefl = declRef && (0, declarationReferenceResolver_1.resolveDeclarationReference)(reflection, declRef[0]);
if (reflection instanceof models_1.SignatureReflection) {
// Assumes that if there are overloads, they are declared in the same order as the parent.
// TS doesn't check this, but if a user messes this up then they are almost
// guaranteed to run into bugs where they can't call a method on a child class
// but if they assign (without a type assertion) that child to a variable of the parent class
// then they can call the method.
if (sourceRefl instanceof models_1.DeclarationReflection) {
const index = reflection.parent
.getAllSignatures()
.indexOf(reflection);
sourceRefl =
sourceRefl.getAllSignatures()[index] || sourceRefl;
}
}
if (sourceRefl instanceof models_1.DeclarationReflection &&
sourceRefl.kindOf(models_1.ReflectionKind.Accessor)) {
// Accessors, like functions, never have comments on their actual root reflection.
// If the user didn't specify whether to inherit from the getter or setter, then implicitly
// try to inherit from the getter, #1968.
sourceRefl = sourceRefl.getSignature || sourceRefl.setSignature;
}
if (!sourceRefl) {
if (this.validation.invalidLink) {
this.application.logger.warn(`Failed to find "${source}" to inherit the comment from in the comment for ${reflection.getFullName()}`);
}
continue;
}
this.copyComment(sourceRefl, reflection);
}
this.createCircularDependencyWarnings();
this.dependencies.clear();
}
copyComment(source, target) {
if (!target.comment)
return;
if (!source.comment &&
source instanceof models_1.DeclarationReflection &&
source.signatures) {
source = source.signatures[0];
}
if (!source.comment &&
source instanceof models_1.DeclarationReflection &&
source.type instanceof models_1.ReflectionType &&
source.type.declaration.signatures) {
source = source.type.declaration.signatures[0];
}
if (!source.comment) {
this.application.logger.warn(`${target.getFullName()} tried to copy a comment from ${source.getFullName()} with @inheritDoc, but the source has no associated comment.`);
return;
}
// If the source also has a @inheritDoc tag, we can't do anything yet.
// We'll try again later, once we've resolved the source's @inheritDoc reference.
if (extractInheritDocTagReference(source)) {
this.dependencies.get(source).push(target);
return;
}
target.comment.removeTags("@inheritDoc");
target.comment.summary = models_1.Comment.cloneDisplayParts(source.comment.summary);
const remarks = source.comment.getTag("@remarks");
if (remarks) {
target.comment.blockTags.unshift(remarks.clone());
}
const returns = source.comment.getTag("@returns");
if (returns) {
target.comment.blockTags.push(returns.clone());
}
if (source instanceof models_1.SignatureReflection &&
target instanceof models_1.SignatureReflection) {
copySummaries(source.parameters, target.parameters);
copySummaries(source.typeParameters, target.typeParameters);
}
else if (source instanceof models_1.DeclarationReflection &&
target instanceof models_1.DeclarationReflection) {
copySummaries(source.typeParameters, target.typeParameters);
}
// Now copy the comment for anyone who depends on me.
const dependent = this.dependencies.get(target);
this.dependencies.delete(target);
for (const target2 of dependent) {
this.copyComment(target, target2);
}
}
createCircularDependencyWarnings() {
const unwarned = new Set(this.dependencies.keys());
const generateWarning = (orig) => {
const parts = [orig.name];
unwarned.delete(orig);
let work = orig;
do {
work = this.dependencies.get(work)[0];
unwarned.delete(work);
parts.push(work.name);
} while (!this.dependencies.get(work).includes(orig));
parts.push(orig.name);
this.application.logger.warn(`@inheritDoc specifies a circular inheritance chain: ${parts
.reverse()
.join(" -> ")}`);
};
for (const orig of this.dependencies.keys()) {
if (unwarned.has(orig)) {
generateWarning(orig);
}
}
}
};
_InheritDocPlugin_validation_accessor_storage = new WeakMap();
__setFunctionName(_classThis, "InheritDocPlugin");
(() => {
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
_validation_decorators = [(0, utils_1.Option)("validation")];
__esDecorate(_classThis, null, _validation_decorators, { kind: "accessor", name: "validation", static: false, private: false, access: { has: obj => "validation" in obj, get: obj => obj.validation, set: (obj, value) => { obj.validation = value; } }, metadata: _metadata }, _validation_initializers, _validation_extraInitializers);
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
InheritDocPlugin = _classThis = _classDescriptor.value;
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
__runInitializers(_classThis, _classExtraInitializers);
})();
return InheritDocPlugin = _classThis;
})();
exports.InheritDocPlugin = InheritDocPlugin;
function copySummaries(source, target) {
for (const [s, t] of (0, array_1.zip)(source || [], target || [])) {
t.comment = new models_1.Comment(s.comment?.summary);
}
}
function extractInheritDocTagReference(reflection) {
const comment = reflection.comment;
if (!comment)
return;
const blockTag = comment.blockTags.find((tag) => tag.tag === "@inheritDoc");
if (blockTag) {
return blockTag.name;
}
const inlineTag = comment.summary.find((part) => part.kind === "inline-tag" && part.tag === "@inheritDoc");
if (inlineTag) {
return inlineTag.text;
}
}

View File

@@ -0,0 +1,14 @@
import { ConverterComponent } from "../components";
import type { Context } from "../../converter";
import { ValidationOptions } from "../../utils";
import { ProjectReflection } from "../../models";
/**
* A plugin that resolves `{@link Foo}` tags.
*/
export declare class LinkResolverPlugin extends ConverterComponent {
accessor validation: ValidationOptions;
initialize(): void;
onResolve(context: Context): void;
resolveLinks(project: ProjectReflection): void;
private resolveCategoryLinks;
}

View File

@@ -0,0 +1,154 @@
"use strict";
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
var _, done = false;
for (var i = decorators.length - 1; i >= 0; i--) {
var context = {};
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
if (kind === "accessor") {
if (result === void 0) continue;
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
if (_ = accept(result.get)) descriptor.get = _;
if (_ = accept(result.set)) descriptor.set = _;
if (_ = accept(result.init)) initializers.unshift(_);
}
else if (_ = accept(result)) {
if (kind === "field") initializers.unshift(_);
else descriptor[key] = _;
}
}
if (target) Object.defineProperty(target, contextIn.name, descriptor);
done = true;
};
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
var useValue = arguments.length > 2;
for (var i = 0; i < initializers.length; i++) {
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
}
return useValue ? value : void 0;
};
var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.LinkResolverPlugin = void 0;
const components_1 = require("../components");
const converter_events_1 = require("../converter-events");
const utils_1 = require("../../utils");
const models_1 = require("../../models");
const reflections_1 = require("../../utils/reflections");
const application_events_1 = require("../../application-events");
/**
* A plugin that resolves `{@link Foo}` tags.
*/
let LinkResolverPlugin = (() => {
var _LinkResolverPlugin_validation_accessor_storage;
let _classDecorators = [(0, components_1.Component)({ name: "link-resolver" })];
let _classDescriptor;
let _classExtraInitializers = [];
let _classThis;
let _classSuper = components_1.ConverterComponent;
let _validation_decorators;
let _validation_initializers = [];
let _validation_extraInitializers = [];
var LinkResolverPlugin = _classThis = class extends _classSuper {
get validation() { return __classPrivateFieldGet(this, _LinkResolverPlugin_validation_accessor_storage, "f"); }
set validation(value) { __classPrivateFieldSet(this, _LinkResolverPlugin_validation_accessor_storage, value, "f"); }
initialize() {
super.initialize();
this.owner.on(converter_events_1.ConverterEvents.RESOLVE_END, this.onResolve, this, -300);
this.application.on(application_events_1.ApplicationEvents.REVIVE, this.resolveLinks, this, -300);
}
onResolve(context) {
this.resolveLinks(context.project);
}
resolveLinks(project) {
for (const id in project.reflections) {
const reflection = project.reflections[id];
if (reflection.comment) {
this.owner.resolveLinks(reflection.comment, reflection);
}
if (reflection instanceof models_1.DeclarationReflection &&
reflection.readme) {
reflection.readme = this.owner.resolveLinks(reflection.readme, reflection);
}
if (reflection instanceof models_1.ContainerReflection) {
if (reflection.groups) {
for (const group of reflection.groups) {
if (group.description) {
group.description = this.owner.resolveLinks(group.description, reflection);
}
if (group.categories) {
for (const cat of group.categories) {
this.resolveCategoryLinks(cat, reflection);
}
}
}
}
if (reflection.categories) {
for (const cat of reflection.categories) {
this.resolveCategoryLinks(cat, reflection);
}
}
}
}
if (project.readme) {
project.readme = this.owner.resolveLinks(project.readme, project);
}
for (const { type, owner } of (0, reflections_1.discoverAllReferenceTypes)(project, false)) {
if (!type.reflection) {
const resolveResult = this.owner.resolveExternalLink(type.toDeclarationReference(), owner, undefined, type.symbolId);
switch (typeof resolveResult) {
case "string":
type.externalUrl = resolveResult;
break;
case "object":
type.externalUrl = resolveResult.target;
break;
}
}
}
}
resolveCategoryLinks(category, owner) {
if (category.description) {
category.description = this.owner.resolveLinks(category.description, owner);
}
}
constructor() {
super(...arguments);
_LinkResolverPlugin_validation_accessor_storage.set(this, __runInitializers(this, _validation_initializers, void 0));
__runInitializers(this, _validation_extraInitializers);
}
};
_LinkResolverPlugin_validation_accessor_storage = new WeakMap();
__setFunctionName(_classThis, "LinkResolverPlugin");
(() => {
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
_validation_decorators = [(0, utils_1.Option)("validation")];
__esDecorate(_classThis, null, _validation_decorators, { kind: "accessor", name: "validation", static: false, private: false, access: { has: obj => "validation" in obj, get: obj => obj.validation, set: (obj, value) => { obj.validation = value; } }, metadata: _metadata }, _validation_initializers, _validation_extraInitializers);
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
LinkResolverPlugin = _classThis = _classDescriptor.value;
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
__runInitializers(_classThis, _classExtraInitializers);
})();
return LinkResolverPlugin = _classThis;
})();
exports.LinkResolverPlugin = LinkResolverPlugin;

View File

@@ -0,0 +1,31 @@
import { ConverterComponent } from "../components";
import { EntryPointStrategy } from "../../utils";
/**
* A handler that tries to find the package.json and readme.md files of the
* current project.
*/
export declare class PackagePlugin extends ConverterComponent {
accessor readme: string;
accessor stripYamlFrontmatter: boolean;
accessor entryPointStrategy: EntryPointStrategy;
accessor entryPoints: string[];
accessor includeVersion: boolean;
/**
* The file name of the found readme.md file.
*/
private readmeFile?;
/**
* Contents of the readme.md file discovered, if any
*/
private readmeContents?;
/**
* Contents of package.json for the active project
*/
private packageJson?;
initialize(): void;
private onRevive;
private onBegin;
private processReadmeContents;
private onBeginResolve;
private addEntries;
}

View File

@@ -0,0 +1,250 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
var _, done = false;
for (var i = decorators.length - 1; i >= 0; i--) {
var context = {};
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
if (kind === "accessor") {
if (result === void 0) continue;
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
if (_ = accept(result.get)) descriptor.get = _;
if (_ = accept(result.set)) descriptor.set = _;
if (_ = accept(result.init)) initializers.unshift(_);
}
else if (_ = accept(result)) {
if (kind === "field") initializers.unshift(_);
else descriptor[key] = _;
}
}
if (target) Object.defineProperty(target, contextIn.name, descriptor);
done = true;
};
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
var useValue = arguments.length > 2;
for (var i = 0; i < initializers.length; i++) {
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
}
return useValue ? value : void 0;
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PackagePlugin = void 0;
const Path = __importStar(require("path"));
const components_1 = require("../components");
const converter_1 = require("../converter");
const utils_1 = require("../../utils");
const fs_1 = require("../../utils/fs");
const paths_1 = require("../../utils/paths");
const minimalSourceFile_1 = require("../../utils/minimalSourceFile");
const application_events_1 = require("../../application-events");
const path_1 = require("path");
/**
* A handler that tries to find the package.json and readme.md files of the
* current project.
*/
let PackagePlugin = (() => {
var _PackagePlugin_readme_accessor_storage, _PackagePlugin_stripYamlFrontmatter_accessor_storage, _PackagePlugin_entryPointStrategy_accessor_storage, _PackagePlugin_entryPoints_accessor_storage, _PackagePlugin_includeVersion_accessor_storage;
let _classDecorators = [(0, components_1.Component)({ name: "package" })];
let _classDescriptor;
let _classExtraInitializers = [];
let _classThis;
let _classSuper = components_1.ConverterComponent;
let _readme_decorators;
let _readme_initializers = [];
let _readme_extraInitializers = [];
let _stripYamlFrontmatter_decorators;
let _stripYamlFrontmatter_initializers = [];
let _stripYamlFrontmatter_extraInitializers = [];
let _entryPointStrategy_decorators;
let _entryPointStrategy_initializers = [];
let _entryPointStrategy_extraInitializers = [];
let _entryPoints_decorators;
let _entryPoints_initializers = [];
let _entryPoints_extraInitializers = [];
let _includeVersion_decorators;
let _includeVersion_initializers = [];
let _includeVersion_extraInitializers = [];
var PackagePlugin = _classThis = class extends _classSuper {
constructor() {
super(...arguments);
_PackagePlugin_readme_accessor_storage.set(this, __runInitializers(this, _readme_initializers, void 0));
_PackagePlugin_stripYamlFrontmatter_accessor_storage.set(this, (__runInitializers(this, _readme_extraInitializers), __runInitializers(this, _stripYamlFrontmatter_initializers, void 0)));
_PackagePlugin_entryPointStrategy_accessor_storage.set(this, (__runInitializers(this, _stripYamlFrontmatter_extraInitializers), __runInitializers(this, _entryPointStrategy_initializers, void 0)));
_PackagePlugin_entryPoints_accessor_storage.set(this, (__runInitializers(this, _entryPointStrategy_extraInitializers), __runInitializers(this, _entryPoints_initializers, void 0)));
_PackagePlugin_includeVersion_accessor_storage.set(this, (__runInitializers(this, _entryPoints_extraInitializers), __runInitializers(this, _includeVersion_initializers, void 0)));
/**
* The file name of the found readme.md file.
*/
this.readmeFile = __runInitializers(this, _includeVersion_extraInitializers);
}
get readme() { return __classPrivateFieldGet(this, _PackagePlugin_readme_accessor_storage, "f"); }
set readme(value) { __classPrivateFieldSet(this, _PackagePlugin_readme_accessor_storage, value, "f"); }
get stripYamlFrontmatter() { return __classPrivateFieldGet(this, _PackagePlugin_stripYamlFrontmatter_accessor_storage, "f"); }
set stripYamlFrontmatter(value) { __classPrivateFieldSet(this, _PackagePlugin_stripYamlFrontmatter_accessor_storage, value, "f"); }
get entryPointStrategy() { return __classPrivateFieldGet(this, _PackagePlugin_entryPointStrategy_accessor_storage, "f"); }
set entryPointStrategy(value) { __classPrivateFieldSet(this, _PackagePlugin_entryPointStrategy_accessor_storage, value, "f"); }
get entryPoints() { return __classPrivateFieldGet(this, _PackagePlugin_entryPoints_accessor_storage, "f"); }
set entryPoints(value) { __classPrivateFieldSet(this, _PackagePlugin_entryPoints_accessor_storage, value, "f"); }
get includeVersion() { return __classPrivateFieldGet(this, _PackagePlugin_includeVersion_accessor_storage, "f"); }
set includeVersion(value) { __classPrivateFieldSet(this, _PackagePlugin_includeVersion_accessor_storage, value, "f"); }
initialize() {
this.listenTo(this.owner, {
[converter_1.Converter.EVENT_BEGIN]: this.onBegin,
[converter_1.Converter.EVENT_RESOLVE_BEGIN]: this.onBeginResolve,
[converter_1.Converter.EVENT_END]: () => {
delete this.readmeFile;
delete this.readmeContents;
delete this.packageJson;
},
});
this.listenTo(this.application, {
[application_events_1.ApplicationEvents.REVIVE]: this.onRevive,
});
}
onRevive(project) {
this.onBegin();
this.addEntries(project);
delete this.readmeFile;
delete this.packageJson;
delete this.readmeContents;
}
onBegin() {
this.readmeFile = undefined;
this.readmeContents = undefined;
this.packageJson = undefined;
const entryFiles = this.entryPointStrategy === utils_1.EntryPointStrategy.Packages
? this.entryPoints.map((d) => (0, path_1.join)(d, "package.json"))
: this.entryPoints;
const dirName = this.application.options.packageDir ??
Path.resolve((0, fs_1.deriveRootDir)(entryFiles));
this.application.logger.verbose(`Begin readme.md/package.json search at ${(0, paths_1.nicePath)(dirName)}`);
this.packageJson = (0, fs_1.discoverPackageJson)(dirName)?.content;
// Path will be resolved already. This is kind of ugly, but...
if (this.readme.endsWith("none")) {
return; // No readme, we're done
}
if (this.readme) {
// Readme path provided, read only that file.
try {
this.readmeContents = this.processReadmeContents((0, utils_1.readFile)(this.readme));
this.readmeFile = this.readme;
}
catch {
this.application.logger.error(`Provided README path, ${(0, paths_1.nicePath)(this.readme)} could not be read.`);
}
}
else {
// No readme provided, automatically find the readme
const result = (0, fs_1.discoverInParentDir)("readme.md", dirName, (content) => content);
if (result) {
this.readmeFile = result.file;
this.readmeContents = this.processReadmeContents(result.content);
}
}
}
processReadmeContents(contents) {
if (this.stripYamlFrontmatter) {
return contents.replace(/^\s*---\r?\n[\s\S]*?\r?\n---\s*?\r?\n\s*/, "");
}
return contents;
}
onBeginResolve(context) {
this.addEntries(context.project);
}
addEntries(project) {
if (this.readmeFile && this.readmeContents) {
const comment = this.application.converter.parseRawComment(new minimalSourceFile_1.MinimalSourceFile(this.readmeContents, this.readmeFile));
if (comment.blockTags.length || comment.modifierTags.size) {
const ignored = [
...comment.blockTags.map((tag) => tag.tag),
...comment.modifierTags,
];
this.application.logger.warn(`Block and modifier tags will be ignored within the readme:\n\t${ignored.join("\n\t")}`);
}
project.readme = comment.summary;
}
if (this.packageJson) {
project.packageName = this.packageJson.name;
if (!project.name) {
project.name = project.packageName || "Documentation";
}
if (this.includeVersion) {
project.packageVersion = this.packageJson.version?.replace(/^v/, "");
}
}
else if (!project.name) {
this.application.logger.warn('The --name option was not specified, and no package.json was found. Defaulting project name to "Documentation".');
project.name = "Documentation";
}
}
};
_PackagePlugin_readme_accessor_storage = new WeakMap();
_PackagePlugin_stripYamlFrontmatter_accessor_storage = new WeakMap();
_PackagePlugin_entryPointStrategy_accessor_storage = new WeakMap();
_PackagePlugin_entryPoints_accessor_storage = new WeakMap();
_PackagePlugin_includeVersion_accessor_storage = new WeakMap();
__setFunctionName(_classThis, "PackagePlugin");
(() => {
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
_readme_decorators = [(0, utils_1.Option)("readme")];
_stripYamlFrontmatter_decorators = [(0, utils_1.Option)("stripYamlFrontmatter")];
_entryPointStrategy_decorators = [(0, utils_1.Option)("entryPointStrategy")];
_entryPoints_decorators = [(0, utils_1.Option)("entryPoints")];
_includeVersion_decorators = [(0, utils_1.Option)("includeVersion")];
__esDecorate(_classThis, null, _readme_decorators, { kind: "accessor", name: "readme", static: false, private: false, access: { has: obj => "readme" in obj, get: obj => obj.readme, set: (obj, value) => { obj.readme = value; } }, metadata: _metadata }, _readme_initializers, _readme_extraInitializers);
__esDecorate(_classThis, null, _stripYamlFrontmatter_decorators, { kind: "accessor", name: "stripYamlFrontmatter", static: false, private: false, access: { has: obj => "stripYamlFrontmatter" in obj, get: obj => obj.stripYamlFrontmatter, set: (obj, value) => { obj.stripYamlFrontmatter = value; } }, metadata: _metadata }, _stripYamlFrontmatter_initializers, _stripYamlFrontmatter_extraInitializers);
__esDecorate(_classThis, null, _entryPointStrategy_decorators, { kind: "accessor", name: "entryPointStrategy", static: false, private: false, access: { has: obj => "entryPointStrategy" in obj, get: obj => obj.entryPointStrategy, set: (obj, value) => { obj.entryPointStrategy = value; } }, metadata: _metadata }, _entryPointStrategy_initializers, _entryPointStrategy_extraInitializers);
__esDecorate(_classThis, null, _entryPoints_decorators, { kind: "accessor", name: "entryPoints", static: false, private: false, access: { has: obj => "entryPoints" in obj, get: obj => obj.entryPoints, set: (obj, value) => { obj.entryPoints = value; } }, metadata: _metadata }, _entryPoints_initializers, _entryPoints_extraInitializers);
__esDecorate(_classThis, null, _includeVersion_decorators, { kind: "accessor", name: "includeVersion", static: false, private: false, access: { has: obj => "includeVersion" in obj, get: obj => obj.includeVersion, set: (obj, value) => { obj.includeVersion = value; } }, metadata: _metadata }, _includeVersion_initializers, _includeVersion_extraInitializers);
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
PackagePlugin = _classThis = _classDescriptor.value;
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
__runInitializers(_classThis, _classExtraInitializers);
})();
return PackagePlugin = _classThis;
})();
exports.PackagePlugin = PackagePlugin;

View File

@@ -0,0 +1,52 @@
import { ConverterComponent } from "../components";
/**
* A handler that attaches source file information to reflections.
*/
export declare class SourcePlugin extends ConverterComponent {
accessor disableSources: boolean;
accessor gitRevision: string;
accessor gitRemote: string;
accessor disableGit: boolean;
accessor sourceLinkTemplate: string;
accessor basePath: string;
/**
* All file names to find the base path from.
*/
private fileNames;
/**
* List of known repositories.
*/
private repositories;
/**
* List of paths known to be not under git control.
*/
private ignoredPaths;
/**
* Create a new SourceHandler instance.
*/
initialize(): void;
private onEnd;
/**
* Triggered when the converter has created a declaration reflection.
*
* Attach the current source file to the {@link DeclarationReflection.sources} array.
*
* @param _context The context object describing the current state the converter is in.
* @param reflection The reflection that is currently processed.
*/
private onDeclaration;
private onSignature;
/**
* Triggered when the converter begins resolving a project.
*
* @param context The context object describing the current state the converter is in.
*/
private onBeginResolve;
/**
* Check whether the given file is placed inside a repository.
*
* @param fileName The name of the file a repository should be looked for.
* @returns The found repository info or undefined.
*/
private getRepository;
}

View File

@@ -0,0 +1,303 @@
"use strict";
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
var _, done = false;
for (var i = decorators.length - 1; i >= 0; i--) {
var context = {};
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
if (kind === "accessor") {
if (result === void 0) continue;
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
if (_ = accept(result.get)) descriptor.get = _;
if (_ = accept(result.set)) descriptor.set = _;
if (_ = accept(result.init)) initializers.unshift(_);
}
else if (_ = accept(result)) {
if (kind === "field") initializers.unshift(_);
else descriptor[key] = _;
}
}
if (target) Object.defineProperty(target, contextIn.name, descriptor);
done = true;
};
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
var useValue = arguments.length > 2;
for (var i = 0; i < initializers.length; i++) {
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
}
return useValue ? value : void 0;
};
var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SourcePlugin = void 0;
const typescript_1 = __importDefault(require("typescript"));
const index_1 = require("../../models/reflections/index");
const components_1 = require("../components");
const converter_1 = require("../converter");
const utils_1 = require("../../utils");
const nodes_1 = require("../utils/nodes");
const path_1 = require("path");
const models_1 = require("../../models");
const repository_1 = require("../utils/repository");
const base_path_1 = require("../utils/base-path");
/**
* A handler that attaches source file information to reflections.
*/
let SourcePlugin = (() => {
var _SourcePlugin_disableSources_accessor_storage, _SourcePlugin_gitRevision_accessor_storage, _SourcePlugin_gitRemote_accessor_storage, _SourcePlugin_disableGit_accessor_storage, _SourcePlugin_sourceLinkTemplate_accessor_storage, _SourcePlugin_basePath_accessor_storage;
let _classDecorators = [(0, components_1.Component)({ name: "source" })];
let _classDescriptor;
let _classExtraInitializers = [];
let _classThis;
let _classSuper = components_1.ConverterComponent;
let _disableSources_decorators;
let _disableSources_initializers = [];
let _disableSources_extraInitializers = [];
let _gitRevision_decorators;
let _gitRevision_initializers = [];
let _gitRevision_extraInitializers = [];
let _gitRemote_decorators;
let _gitRemote_initializers = [];
let _gitRemote_extraInitializers = [];
let _disableGit_decorators;
let _disableGit_initializers = [];
let _disableGit_extraInitializers = [];
let _sourceLinkTemplate_decorators;
let _sourceLinkTemplate_initializers = [];
let _sourceLinkTemplate_extraInitializers = [];
let _basePath_decorators;
let _basePath_initializers = [];
let _basePath_extraInitializers = [];
var SourcePlugin = _classThis = class extends _classSuper {
constructor() {
super(...arguments);
_SourcePlugin_disableSources_accessor_storage.set(this, __runInitializers(this, _disableSources_initializers, void 0));
_SourcePlugin_gitRevision_accessor_storage.set(this, (__runInitializers(this, _disableSources_extraInitializers), __runInitializers(this, _gitRevision_initializers, void 0)));
_SourcePlugin_gitRemote_accessor_storage.set(this, (__runInitializers(this, _gitRevision_extraInitializers), __runInitializers(this, _gitRemote_initializers, void 0)));
_SourcePlugin_disableGit_accessor_storage.set(this, (__runInitializers(this, _gitRemote_extraInitializers), __runInitializers(this, _disableGit_initializers, void 0)));
_SourcePlugin_sourceLinkTemplate_accessor_storage.set(this, (__runInitializers(this, _disableGit_extraInitializers), __runInitializers(this, _sourceLinkTemplate_initializers, void 0)));
_SourcePlugin_basePath_accessor_storage.set(this, (__runInitializers(this, _sourceLinkTemplate_extraInitializers), __runInitializers(this, _basePath_initializers, void 0)));
/**
* All file names to find the base path from.
*/
this.fileNames = (__runInitializers(this, _basePath_extraInitializers), new Set());
/**
* List of known repositories.
*/
this.repositories = {};
/**
* List of paths known to be not under git control.
*/
this.ignoredPaths = new Set();
}
get disableSources() { return __classPrivateFieldGet(this, _SourcePlugin_disableSources_accessor_storage, "f"); }
set disableSources(value) { __classPrivateFieldSet(this, _SourcePlugin_disableSources_accessor_storage, value, "f"); }
get gitRevision() { return __classPrivateFieldGet(this, _SourcePlugin_gitRevision_accessor_storage, "f"); }
set gitRevision(value) { __classPrivateFieldSet(this, _SourcePlugin_gitRevision_accessor_storage, value, "f"); }
get gitRemote() { return __classPrivateFieldGet(this, _SourcePlugin_gitRemote_accessor_storage, "f"); }
set gitRemote(value) { __classPrivateFieldSet(this, _SourcePlugin_gitRemote_accessor_storage, value, "f"); }
get disableGit() { return __classPrivateFieldGet(this, _SourcePlugin_disableGit_accessor_storage, "f"); }
set disableGit(value) { __classPrivateFieldSet(this, _SourcePlugin_disableGit_accessor_storage, value, "f"); }
get sourceLinkTemplate() { return __classPrivateFieldGet(this, _SourcePlugin_sourceLinkTemplate_accessor_storage, "f"); }
set sourceLinkTemplate(value) { __classPrivateFieldSet(this, _SourcePlugin_sourceLinkTemplate_accessor_storage, value, "f"); }
get basePath() { return __classPrivateFieldGet(this, _SourcePlugin_basePath_accessor_storage, "f"); }
set basePath(value) { __classPrivateFieldSet(this, _SourcePlugin_basePath_accessor_storage, value, "f"); }
/**
* Create a new SourceHandler instance.
*/
initialize() {
this.listenTo(this.owner, {
[converter_1.Converter.EVENT_END]: this.onEnd,
[converter_1.Converter.EVENT_CREATE_DECLARATION]: this.onDeclaration,
[converter_1.Converter.EVENT_CREATE_SIGNATURE]: this.onSignature,
[converter_1.Converter.EVENT_RESOLVE_BEGIN]: this.onBeginResolve,
});
}
onEnd() {
// Should probably clear repositories/ignoredPaths here, but these aren't likely to change between runs...
this.fileNames.clear();
}
/**
* Triggered when the converter has created a declaration reflection.
*
* Attach the current source file to the {@link DeclarationReflection.sources} array.
*
* @param _context The context object describing the current state the converter is in.
* @param reflection The reflection that is currently processed.
*/
onDeclaration(_context, reflection) {
if (this.disableSources)
return;
const symbol = reflection.project.getSymbolFromReflection(reflection);
for (const node of symbol?.declarations || []) {
const sourceFile = node.getSourceFile();
const fileName = base_path_1.BasePath.normalize(sourceFile.fileName);
this.fileNames.add(fileName);
let position;
if (typescript_1.default.isSourceFile(node)) {
position = { character: 0, line: 0 };
}
else {
position = typescript_1.default.getLineAndCharacterOfPosition(sourceFile, getLocationNode(node).getStart());
}
reflection.sources ||= [];
reflection.sources.push(new models_1.SourceReference(fileName, position.line + 1, position.character));
}
}
onSignature(_context, reflection, sig) {
if (this.disableSources || !sig)
return;
const sourceFile = sig.getSourceFile();
const fileName = base_path_1.BasePath.normalize(sourceFile.fileName);
this.fileNames.add(fileName);
const position = typescript_1.default.getLineAndCharacterOfPosition(sourceFile, getLocationNode(sig).getStart());
reflection.sources ||= [];
reflection.sources.push(new models_1.SourceReference(fileName, position.line + 1, position.character));
}
/**
* Triggered when the converter begins resolving a project.
*
* @param context The context object describing the current state the converter is in.
*/
onBeginResolve(context) {
if (this.disableSources)
return;
if (this.disableGit && !this.sourceLinkTemplate) {
this.application.logger.error(`disableGit is set, but sourceLinkTemplate is not, so source links cannot be produced. Set a sourceLinkTemplate or disableSources to prevent source tracking.`);
return;
}
if (this.disableGit &&
this.sourceLinkTemplate.includes("{gitRevision}") &&
!this.gitRevision) {
this.application.logger.warn(`disableGit is set and sourceLinkTemplate contains {gitRevision}, which will be replaced with an empty string as no revision was provided.`);
}
const basePath = this.basePath || (0, utils_1.getCommonDirectory)([...this.fileNames]);
for (const id in context.project.reflections) {
const refl = context.project.reflections[id];
if (!(refl instanceof index_1.DeclarationReflection ||
refl instanceof index_1.SignatureReflection)) {
continue;
}
if (replaceSourcesWithParentSources(refl)) {
refl.sources = refl.parent.sources;
}
for (const source of refl.sources || []) {
if (this.disableGit || (0, repository_1.gitIsInstalled)()) {
const repo = this.getRepository(basePath, source.fullFileName);
source.url = repo?.getURL(source.fullFileName, source.line);
}
source.fileName = (0, utils_1.normalizePath)((0, path_1.relative)(basePath, source.fullFileName));
}
}
}
/**
* Check whether the given file is placed inside a repository.
*
* @param fileName The name of the file a repository should be looked for.
* @returns The found repository info or undefined.
*/
getRepository(basePath, fileName) {
if (this.disableGit) {
return new repository_1.AssumedRepository(basePath, this.gitRevision, this.sourceLinkTemplate);
}
// Check for known non-repositories
const dirName = (0, path_1.dirname)(fileName);
const segments = dirName.split("/");
for (let i = segments.length; i > 0; i--) {
if (this.ignoredPaths.has(segments.slice(0, i).join("/"))) {
return;
}
}
// Check for known repositories
for (const path of Object.keys(this.repositories)) {
if (fileName.toLowerCase().startsWith(path)) {
return this.repositories[path];
}
}
// Try to create a new repository
const repository = repository_1.GitRepository.tryCreateRepository(dirName, this.sourceLinkTemplate, this.gitRevision, this.gitRemote, this.application.logger);
if (repository) {
this.repositories[repository.path.toLowerCase()] = repository;
return repository;
}
// No repository found, add path to ignored paths
this.ignoredPaths.add(dirName);
}
};
_SourcePlugin_disableSources_accessor_storage = new WeakMap();
_SourcePlugin_gitRevision_accessor_storage = new WeakMap();
_SourcePlugin_gitRemote_accessor_storage = new WeakMap();
_SourcePlugin_disableGit_accessor_storage = new WeakMap();
_SourcePlugin_sourceLinkTemplate_accessor_storage = new WeakMap();
_SourcePlugin_basePath_accessor_storage = new WeakMap();
__setFunctionName(_classThis, "SourcePlugin");
(() => {
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
_disableSources_decorators = [(0, utils_1.Option)("disableSources")];
_gitRevision_decorators = [(0, utils_1.Option)("gitRevision")];
_gitRemote_decorators = [(0, utils_1.Option)("gitRemote")];
_disableGit_decorators = [(0, utils_1.Option)("disableGit")];
_sourceLinkTemplate_decorators = [(0, utils_1.Option)("sourceLinkTemplate")];
_basePath_decorators = [(0, utils_1.Option)("basePath")];
__esDecorate(_classThis, null, _disableSources_decorators, { kind: "accessor", name: "disableSources", static: false, private: false, access: { has: obj => "disableSources" in obj, get: obj => obj.disableSources, set: (obj, value) => { obj.disableSources = value; } }, metadata: _metadata }, _disableSources_initializers, _disableSources_extraInitializers);
__esDecorate(_classThis, null, _gitRevision_decorators, { kind: "accessor", name: "gitRevision", static: false, private: false, access: { has: obj => "gitRevision" in obj, get: obj => obj.gitRevision, set: (obj, value) => { obj.gitRevision = value; } }, metadata: _metadata }, _gitRevision_initializers, _gitRevision_extraInitializers);
__esDecorate(_classThis, null, _gitRemote_decorators, { kind: "accessor", name: "gitRemote", static: false, private: false, access: { has: obj => "gitRemote" in obj, get: obj => obj.gitRemote, set: (obj, value) => { obj.gitRemote = value; } }, metadata: _metadata }, _gitRemote_initializers, _gitRemote_extraInitializers);
__esDecorate(_classThis, null, _disableGit_decorators, { kind: "accessor", name: "disableGit", static: false, private: false, access: { has: obj => "disableGit" in obj, get: obj => obj.disableGit, set: (obj, value) => { obj.disableGit = value; } }, metadata: _metadata }, _disableGit_initializers, _disableGit_extraInitializers);
__esDecorate(_classThis, null, _sourceLinkTemplate_decorators, { kind: "accessor", name: "sourceLinkTemplate", static: false, private: false, access: { has: obj => "sourceLinkTemplate" in obj, get: obj => obj.sourceLinkTemplate, set: (obj, value) => { obj.sourceLinkTemplate = value; } }, metadata: _metadata }, _sourceLinkTemplate_initializers, _sourceLinkTemplate_extraInitializers);
__esDecorate(_classThis, null, _basePath_decorators, { kind: "accessor", name: "basePath", static: false, private: false, access: { has: obj => "basePath" in obj, get: obj => obj.basePath, set: (obj, value) => { obj.basePath = value; } }, metadata: _metadata }, _basePath_initializers, _basePath_extraInitializers);
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
SourcePlugin = _classThis = _classDescriptor.value;
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
__runInitializers(_classThis, _classExtraInitializers);
})();
return SourcePlugin = _classThis;
})();
exports.SourcePlugin = SourcePlugin;
function getLocationNode(node) {
if ((0, nodes_1.isNamedNode)(node))
return node.name;
return node;
}
function replaceSourcesWithParentSources(refl) {
if (refl instanceof index_1.DeclarationReflection || !refl.sources) {
return false;
}
const symbol = refl.project.getSymbolFromReflection(refl.parent);
if (!symbol?.declarations) {
return false;
}
for (const decl of symbol.declarations) {
const file = decl.getSourceFile();
const pos = file.getLineAndCharacterOfPosition(decl.pos);
const end = file.getLineAndCharacterOfPosition(decl.end);
if (refl.sources.some((src) => src.fullFileName === file.fileName &&
pos.line <= src.line - 1 &&
src.line - 1 <= end.line)) {
return false;
}
}
return true;
}

View File

@@ -0,0 +1,18 @@
import { DeclarationReflection } from "../../models/reflections/index";
import { ConverterComponent } from "../components";
/**
* Responsible for adding `implementedBy` / `implementedFrom`
*/
export declare class TypePlugin extends ConverterComponent {
reflections: Set<DeclarationReflection>;
/**
* Create a new TypeHandler instance.
*/
initialize(): void;
private onRevive;
private onResolve;
private resolve;
private postpone;
private onResolveEnd;
private finishResolve;
}

View File

@@ -0,0 +1,176 @@
"use strict";
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
var _, done = false;
for (var i = decorators.length - 1; i >= 0; i--) {
var context = {};
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
if (kind === "accessor") {
if (result === void 0) continue;
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
if (_ = accept(result.get)) descriptor.get = _;
if (_ = accept(result.set)) descriptor.set = _;
if (_ = accept(result.init)) initializers.unshift(_);
}
else if (_ = accept(result)) {
if (kind === "field") initializers.unshift(_);
else descriptor[key] = _;
}
}
if (target) Object.defineProperty(target, contextIn.name, descriptor);
done = true;
};
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
var useValue = arguments.length > 2;
for (var i = 0; i < initializers.length; i++) {
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
}
return useValue ? value : void 0;
};
var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TypePlugin = void 0;
const index_1 = require("../../models/reflections/index");
const types_1 = require("../../models/types");
const components_1 = require("../components");
const converter_1 = require("../converter");
const application_events_1 = require("../../application-events");
/**
* Responsible for adding `implementedBy` / `implementedFrom`
*/
let TypePlugin = (() => {
let _classDecorators = [(0, components_1.Component)({ name: "type" })];
let _classDescriptor;
let _classExtraInitializers = [];
let _classThis;
let _classSuper = components_1.ConverterComponent;
var TypePlugin = _classThis = class extends _classSuper {
constructor() {
super(...arguments);
this.reflections = new Set();
}
/**
* Create a new TypeHandler instance.
*/
initialize() {
this.listenTo(this.owner, {
[converter_1.Converter.EVENT_RESOLVE]: this.onResolve,
[converter_1.Converter.EVENT_RESOLVE_END]: this.onResolveEnd,
[converter_1.Converter.EVENT_END]: () => this.reflections.clear(),
});
this.listenTo(this.application, {
[application_events_1.ApplicationEvents.REVIVE]: this.onRevive,
});
}
onRevive(project) {
for (const id in project.reflections) {
this.resolve(project, project.reflections[id],
/* create links */ false);
}
this.finishResolve(project);
this.reflections.clear();
}
onResolve(context, reflection) {
this.resolve(context.project, reflection);
}
resolve(project, reflection, createLinks = true) {
if (!(reflection instanceof index_1.DeclarationReflection))
return;
if (reflection.kindOf(index_1.ReflectionKind.ClassOrInterface)) {
this.postpone(reflection);
walk(reflection.implementedTypes, (target) => {
this.postpone(target);
target.implementedBy ||= [];
if (createLinks) {
target.implementedBy.push(types_1.ReferenceType.createResolvedReference(reflection.name, reflection, project));
}
});
walk(reflection.extendedTypes, (target) => {
this.postpone(target);
target.extendedBy ||= [];
if (createLinks) {
target.extendedBy.push(types_1.ReferenceType.createResolvedReference(reflection.name, reflection, project));
}
});
}
function walk(types, callback) {
if (!types) {
return;
}
types.forEach((type) => {
if (!(type instanceof types_1.ReferenceType)) {
return;
}
if (!type.reflection ||
!(type.reflection instanceof index_1.DeclarationReflection)) {
return;
}
callback(type.reflection);
});
}
}
postpone(reflection) {
this.reflections.add(reflection);
}
onResolveEnd(context) {
this.finishResolve(context.project);
}
finishResolve(project) {
this.reflections.forEach((reflection) => {
if (reflection.implementedBy) {
reflection.implementedBy.sort((a, b) => {
if (a.name === b.name) {
return 0;
}
return a.name > b.name ? 1 : -1;
});
}
let root;
let hierarchy;
function push(types) {
const level = { types: types };
if (hierarchy) {
hierarchy.next = level;
hierarchy = level;
}
else {
root = hierarchy = level;
}
}
if (reflection.extendedTypes) {
push(reflection.extendedTypes);
}
push([
types_1.ReferenceType.createResolvedReference(reflection.name, reflection, project),
]);
hierarchy.isTarget = true;
if (reflection.extendedBy) {
push(reflection.extendedBy);
}
// No point setting up a hierarchy if there is no hierarchy to display
if (root.next) {
reflection.typeHierarchy = root;
}
});
}
};
__setFunctionName(_classThis, "TypePlugin");
(() => {
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
TypePlugin = _classThis = _classDescriptor.value;
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
__runInitializers(_classThis, _classExtraInitializers);
})();
return TypePlugin = _classThis;
})();
exports.TypePlugin = TypePlugin;

View File

@@ -0,0 +1,9 @@
export { CategoryPlugin } from "./CategoryPlugin";
export { CommentPlugin } from "./CommentPlugin";
export { GroupPlugin } from "./GroupPlugin";
export { ImplementsPlugin } from "./ImplementsPlugin";
export { InheritDocPlugin } from "./InheritDocPlugin";
export { LinkResolverPlugin } from "./LinkResolverPlugin";
export { PackagePlugin } from "./PackagePlugin";
export { SourcePlugin } from "./SourcePlugin";
export { TypePlugin } from "./TypePlugin";

View File

@@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TypePlugin = exports.SourcePlugin = exports.PackagePlugin = exports.LinkResolverPlugin = exports.InheritDocPlugin = exports.ImplementsPlugin = exports.GroupPlugin = exports.CommentPlugin = exports.CategoryPlugin = void 0;
var CategoryPlugin_1 = require("./CategoryPlugin");
Object.defineProperty(exports, "CategoryPlugin", { enumerable: true, get: function () { return CategoryPlugin_1.CategoryPlugin; } });
var CommentPlugin_1 = require("./CommentPlugin");
Object.defineProperty(exports, "CommentPlugin", { enumerable: true, get: function () { return CommentPlugin_1.CommentPlugin; } });
var GroupPlugin_1 = require("./GroupPlugin");
Object.defineProperty(exports, "GroupPlugin", { enumerable: true, get: function () { return GroupPlugin_1.GroupPlugin; } });
var ImplementsPlugin_1 = require("./ImplementsPlugin");
Object.defineProperty(exports, "ImplementsPlugin", { enumerable: true, get: function () { return ImplementsPlugin_1.ImplementsPlugin; } });
var InheritDocPlugin_1 = require("./InheritDocPlugin");
Object.defineProperty(exports, "InheritDocPlugin", { enumerable: true, get: function () { return InheritDocPlugin_1.InheritDocPlugin; } });
var LinkResolverPlugin_1 = require("./LinkResolverPlugin");
Object.defineProperty(exports, "LinkResolverPlugin", { enumerable: true, get: function () { return LinkResolverPlugin_1.LinkResolverPlugin; } });
var PackagePlugin_1 = require("./PackagePlugin");
Object.defineProperty(exports, "PackagePlugin", { enumerable: true, get: function () { return PackagePlugin_1.PackagePlugin; } });
var SourcePlugin_1 = require("./SourcePlugin");
Object.defineProperty(exports, "SourcePlugin", { enumerable: true, get: function () { return SourcePlugin_1.SourcePlugin; } });
var TypePlugin_1 = require("./TypePlugin");
Object.defineProperty(exports, "TypePlugin", { enumerable: true, get: function () { return TypePlugin_1.TypePlugin; } });

3
node_modules/typedoc/dist/lib/converter/symbols.d.ts generated vendored Normal file
View File

@@ -0,0 +1,3 @@
import ts from "typescript";
import type { Context } from "./context";
export declare function convertSymbol(context: Context, symbol: ts.Symbol, exportSymbol?: ts.Symbol): void;

698
node_modules/typedoc/dist/lib/converter/symbols.js generated vendored Normal file
View File

@@ -0,0 +1,698 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertSymbol = void 0;
const assert_1 = __importDefault(require("assert"));
const typescript_1 = __importDefault(require("typescript"));
const models_1 = require("../models");
const enum_1 = require("../utils/enum");
const convert_expression_1 = require("./convert-expression");
const index_signature_1 = require("./factories/index-signature");
const signature_1 = require("./factories/signature");
const jsdoc_1 = require("./jsdoc");
const nodes_1 = require("./utils/nodes");
const reflections_1 = require("./utils/reflections");
const symbolConverters = {
[typescript_1.default.SymbolFlags.RegularEnum]: convertEnum,
[typescript_1.default.SymbolFlags.ConstEnum]: convertEnum,
[typescript_1.default.SymbolFlags.EnumMember]: convertEnumMember,
[typescript_1.default.SymbolFlags.ValueModule]: convertNamespace,
[typescript_1.default.SymbolFlags.NamespaceModule]: convertNamespace,
[typescript_1.default.SymbolFlags.TypeAlias]: convertTypeAlias,
[typescript_1.default.SymbolFlags.Function]: convertFunctionOrMethod,
[typescript_1.default.SymbolFlags.Method]: convertFunctionOrMethod,
[typescript_1.default.SymbolFlags.Interface]: convertClassOrInterface,
[typescript_1.default.SymbolFlags.Property]: convertProperty,
[typescript_1.default.SymbolFlags.Class]: convertClassOrInterface,
[typescript_1.default.SymbolFlags.Constructor]: convertConstructor,
[typescript_1.default.SymbolFlags.Alias]: convertAlias,
[typescript_1.default.SymbolFlags.BlockScopedVariable]: convertVariable,
[typescript_1.default.SymbolFlags.FunctionScopedVariable]: convertVariable,
[typescript_1.default.SymbolFlags.ExportValue]: convertVariable,
[typescript_1.default.SymbolFlags.GetAccessor]: convertAccessor,
[typescript_1.default.SymbolFlags.SetAccessor]: convertAccessor,
};
const allConverterFlags = Object.keys(symbolConverters).reduce((v, k) => v | +k, 0);
// This is kind of a hack, born of resolving references by symbols instead
// of by source location.
const conversionOrder = [
// Do enums before namespaces so that @hidden on a namespace
// merged with an enum works properly.
typescript_1.default.SymbolFlags.RegularEnum,
typescript_1.default.SymbolFlags.ConstEnum,
typescript_1.default.SymbolFlags.EnumMember,
// Before type alias
typescript_1.default.SymbolFlags.BlockScopedVariable,
typescript_1.default.SymbolFlags.FunctionScopedVariable,
typescript_1.default.SymbolFlags.ExportValue,
typescript_1.default.SymbolFlags.Function, // Before NamespaceModule
typescript_1.default.SymbolFlags.TypeAlias,
typescript_1.default.SymbolFlags.Method,
typescript_1.default.SymbolFlags.Interface,
typescript_1.default.SymbolFlags.Property,
typescript_1.default.SymbolFlags.Class,
typescript_1.default.SymbolFlags.Constructor,
typescript_1.default.SymbolFlags.Alias,
typescript_1.default.SymbolFlags.GetAccessor,
typescript_1.default.SymbolFlags.SetAccessor,
typescript_1.default.SymbolFlags.ValueModule,
typescript_1.default.SymbolFlags.NamespaceModule,
];
// Sanity check, if this fails a dev messed up.
for (const key of Object.keys(symbolConverters)) {
if (!Number.isInteger(Math.log2(+key))) {
throw new Error(`Symbol converter for key ${typescript_1.default.SymbolFlags[+key]} does not specify a valid flag value.`);
}
if (!conversionOrder.includes(+key)) {
throw new Error(`Symbol converter for key ${typescript_1.default.SymbolFlags[+key]} is not specified in conversionOrder`);
}
}
if (conversionOrder.reduce((a, b) => a | b, 0) !== allConverterFlags) {
throw new Error("conversionOrder contains a symbol flag that converters do not.");
}
function convertSymbol(context, symbol, exportSymbol) {
if (context.shouldIgnore(symbol)) {
return;
}
// This check can catch symbols which ought to be documented as references
// but aren't aliased symbols because `export *` was used.
const previous = context.project.getReflectionFromSymbol(symbol);
if (previous &&
previous.parent?.kindOf(models_1.ReflectionKind.SomeModule | models_1.ReflectionKind.Project)) {
createAlias(previous, context, symbol, exportSymbol);
return;
}
let flags = (0, enum_1.removeFlag)(symbol.flags, typescript_1.default.SymbolFlags.Transient |
typescript_1.default.SymbolFlags.Assignment |
typescript_1.default.SymbolFlags.Optional |
typescript_1.default.SymbolFlags.Prototype);
// Declaration merging - the only type (excluding enum/enum, ns/ns, etc)
// that TD supports is merging a class and interface. All others are
// represented as multiple reflections
if ((0, enum_1.hasAllFlags)(symbol.flags, typescript_1.default.SymbolFlags.Class)) {
flags = (0, enum_1.removeFlag)(flags, typescript_1.default.SymbolFlags.Interface | typescript_1.default.SymbolFlags.Function);
}
// Kind of declaration merging... we treat this as a property with get/set signatures.
if ((0, enum_1.hasAllFlags)(symbol.flags, typescript_1.default.SymbolFlags.GetAccessor)) {
flags = (0, enum_1.removeFlag)(flags, typescript_1.default.SymbolFlags.SetAccessor);
}
if ((0, enum_1.hasAllFlags)(symbol.flags, typescript_1.default.SymbolFlags.NamespaceModule)) {
// This might be here if a namespace is declared several times.
// Or if it's a namespace-like thing defined on a function
// In the function case, it's important to remove ValueModule so that
// if we convert the children as properties of the function rather than as
// a separate namespace, we skip creating the namespace.
flags = (0, enum_1.removeFlag)(flags, typescript_1.default.SymbolFlags.ValueModule);
}
if ((0, enum_1.hasAnyFlag)(symbol.flags, typescript_1.default.SymbolFlags.Method |
typescript_1.default.SymbolFlags.Interface |
typescript_1.default.SymbolFlags.Class |
typescript_1.default.SymbolFlags.Variable)) {
// This happens when someone declares an object with methods:
// { methodProperty() {} }
flags = (0, enum_1.removeFlag)(flags, typescript_1.default.SymbolFlags.Property);
}
for (const flag of (0, enum_1.getEnumFlags)(flags & ~allConverterFlags)) {
context.logger.verbose(`Missing converter for symbol: ${symbol.name} with flag ${typescript_1.default.SymbolFlags[flag]}`);
}
// Note: This method does not allow skipping earlier converters.
// For now, this is fine... might not be flexible enough in the future.
let skip = 0;
for (const flag of conversionOrder) {
if (!(flag & flags))
continue;
if (skip & flag)
continue;
skip |= symbolConverters[flag]?.(context, symbol, exportSymbol) || 0;
}
}
exports.convertSymbol = convertSymbol;
function convertSymbols(context, symbols) {
for (const symbol of symbols) {
convertSymbol(context, symbol);
}
}
function convertEnum(context, symbol, exportSymbol) {
const reflection = context.createDeclarationReflection(models_1.ReflectionKind.Enum, symbol, exportSymbol);
if (symbol.flags & typescript_1.default.SymbolFlags.ConstEnum) {
reflection.setFlag(models_1.ReflectionFlag.Const);
}
context.finalizeDeclarationReflection(reflection);
convertSymbols(context.withScope(reflection), context.checker
.getExportsOfModule(symbol)
.filter((s) => s.flags & typescript_1.default.SymbolFlags.EnumMember));
}
function convertEnumMember(context, symbol, exportSymbol) {
const reflection = context.createDeclarationReflection(models_1.ReflectionKind.EnumMember, symbol, exportSymbol);
const defaultValue = context.checker.getConstantValue(symbol.getDeclarations()[0]);
if (defaultValue !== undefined) {
reflection.type = new models_1.LiteralType(defaultValue);
}
else {
// We know this has to be a number, because computed values aren't allowed
// in string enums, so otherwise we would have to have the constant value
reflection.type = new models_1.IntrinsicType("number");
}
context.finalizeDeclarationReflection(reflection);
}
function convertNamespace(context, symbol, exportSymbol) {
let exportFlags = typescript_1.default.SymbolFlags.ModuleMember;
// This can happen in JS land where "class" functions get tagged as a namespace too
if (symbol
.getDeclarations()
?.some((d) => typescript_1.default.isModuleDeclaration(d) || typescript_1.default.isSourceFile(d)) !==
true) {
exportFlags = typescript_1.default.SymbolFlags.ClassMember;
if ((0, enum_1.hasAnyFlag)(symbol.flags, typescript_1.default.SymbolFlags.Class)) {
return;
}
}
// #2364, @namespace on a variable might be merged with a namespace containing types.
const existingReflection = context.project.getReflectionFromSymbol(exportSymbol || symbol);
let reflection;
if (existingReflection?.kind === models_1.ReflectionKind.Namespace) {
reflection = existingReflection;
}
else {
reflection = context.createDeclarationReflection(models_1.ReflectionKind.Namespace, symbol, exportSymbol);
context.finalizeDeclarationReflection(reflection);
}
convertSymbols(context.withScope(reflection), context.checker
.getExportsOfModule(symbol)
.filter((s) => s.flags & exportFlags));
}
function convertTypeAlias(context, symbol, exportSymbol) {
const declaration = symbol
?.getDeclarations()
?.find((d) => typescript_1.default.isTypeAliasDeclaration(d) ||
typescript_1.default.isJSDocTypedefTag(d) ||
typescript_1.default.isJSDocCallbackTag(d) ||
typescript_1.default.isJSDocEnumTag(d));
(0, assert_1.default)(declaration);
if (typescript_1.default.isTypeAliasDeclaration(declaration)) {
if (context
.getComment(symbol, models_1.ReflectionKind.TypeAlias)
?.hasModifier("@interface")) {
return convertTypeAliasAsInterface(context, symbol, exportSymbol, declaration);
}
const reflection = context.createDeclarationReflection(models_1.ReflectionKind.TypeAlias, symbol, exportSymbol);
reflection.type = context.converter.convertType(context.withScope(reflection), declaration.type);
context.finalizeDeclarationReflection(reflection);
// Do this after finalization so that the CommentPlugin can get @typeParam tags
// from the parent comment. Ugly, but works for now. Should be cleaned up eventually.
reflection.typeParameters = declaration.typeParameters?.map((param) => (0, signature_1.createTypeParamReflection)(param, context.withScope(reflection)));
}
else if (typescript_1.default.isJSDocTypedefTag(declaration) ||
typescript_1.default.isJSDocEnumTag(declaration)) {
(0, jsdoc_1.convertJsDocAlias)(context, symbol, declaration, exportSymbol);
}
else {
(0, jsdoc_1.convertJsDocCallback)(context, symbol, declaration, exportSymbol);
}
}
function convertTypeAliasAsInterface(context, symbol, exportSymbol, declaration) {
const reflection = context.createDeclarationReflection(models_1.ReflectionKind.Interface, symbol, exportSymbol);
context.finalizeDeclarationReflection(reflection);
const rc = context.withScope(reflection);
const type = context.checker.getTypeAtLocation(declaration);
if (type.getFlags() & typescript_1.default.TypeFlags.Union) {
context.logger.warn(`Using @interface on a union type will discard properties not present on all branches of the union. TypeDoc's output may not accurately describe your source code.`, declaration);
}
// Interfaces have properties
convertSymbols(rc, type.getProperties());
// And type arguments
if (declaration.typeParameters) {
reflection.typeParameters = declaration.typeParameters.map((param) => {
const declaration = param.symbol?.declarations?.[0];
(0, assert_1.default)(declaration && typescript_1.default.isTypeParameterDeclaration(declaration));
return (0, signature_1.createTypeParamReflection)(declaration, rc);
});
}
// And maybe call signatures
context.checker
.getSignaturesOfType(type, typescript_1.default.SignatureKind.Call)
.forEach((sig) => (0, signature_1.createSignature)(rc, models_1.ReflectionKind.CallSignature, sig, symbol));
// And maybe constructor signatures
convertConstructSignatures(rc, symbol);
// And finally, index signatures
(0, index_signature_1.convertIndexSignature)(rc, symbol);
}
function convertFunctionOrMethod(context, symbol, exportSymbol) {
// Can't just check method flag because this might be called for properties as well
// This will *NOT* be called for variables that look like functions, they need a special case.
const isMethod = !!(symbol.flags &
(typescript_1.default.SymbolFlags.Property | typescript_1.default.SymbolFlags.Method));
if (!isMethod) {
const comment = context.getComment(symbol, models_1.ReflectionKind.Function);
if (comment?.hasModifier("@class")) {
return convertSymbolAsClass(context, symbol, exportSymbol);
}
}
const declarations = symbol.getDeclarations()?.filter(typescript_1.default.isFunctionLike) ?? [];
// Don't do anything if we inherited this method and it is private.
if (isMethod &&
isInherited(context, symbol) &&
declarations.length > 0 &&
(0, enum_1.hasAllFlags)(typescript_1.default.getCombinedModifierFlags(declarations[0]), typescript_1.default.ModifierFlags.Private)) {
return;
}
const locationDeclaration = symbol.parent
?.getDeclarations()
?.find((d) => typescript_1.default.isClassDeclaration(d) || typescript_1.default.isInterfaceDeclaration(d)) ??
symbol.parent?.getDeclarations()?.[0]?.getSourceFile() ??
symbol.getDeclarations()?.[0]?.getSourceFile();
(0, assert_1.default)(locationDeclaration, "Missing declaration context");
const type = context.checker.getTypeOfSymbolAtLocation(symbol, locationDeclaration);
// Need to get the non nullable type because interface methods might be declared
// with a question token. See GH1490.
const signatures = type.getNonNullableType().getCallSignatures();
const reflection = context.createDeclarationReflection(context.scope.kindOf(models_1.ReflectionKind.MethodContainer)
? models_1.ReflectionKind.Method
: models_1.ReflectionKind.Function, symbol, exportSymbol, void 0);
if (symbol.declarations?.length && isMethod) {
// All method signatures must have the same modifier flags.
setModifiers(symbol, symbol.declarations[0], reflection);
}
context.finalizeDeclarationReflection(reflection);
const scope = context.withScope(reflection);
// Can't use zip here. We might have less declarations than signatures
// or less signatures than declarations.
for (const sig of signatures) {
(0, signature_1.createSignature)(scope, models_1.ReflectionKind.CallSignature, sig, symbol);
}
return convertFunctionProperties(scope, symbol, type);
}
// getDeclaredTypeOfSymbol gets the INSTANCE type
// getTypeOfSymbolAtLocation gets the STATIC type
function convertClassOrInterface(context, symbol, exportSymbol) {
const reflection = context.createDeclarationReflection(typescript_1.default.SymbolFlags.Class & symbol.flags
? models_1.ReflectionKind.Class
: models_1.ReflectionKind.Interface, symbol, exportSymbol, void 0);
const classDeclaration = symbol
.getDeclarations()
?.find((d) => typescript_1.default.isClassDeclaration(d) || typescript_1.default.isFunctionDeclaration(d));
if (classDeclaration)
setModifiers(symbol, classDeclaration, reflection);
const reflectionContext = context.withScope(reflection);
reflectionContext.convertingClassOrInterface = true;
const instanceType = context.checker.getDeclaredTypeOfSymbol(symbol);
(0, assert_1.default)(instanceType.isClassOrInterface());
// We might do some inheritance - do this first so that it's set when converting properties
const declarations = symbol
.getDeclarations()
?.filter((d) => typescript_1.default.isInterfaceDeclaration(d) || typescript_1.default.isClassDeclaration(d)) ?? [];
const extendedTypes = (0, nodes_1.getHeritageTypes)(declarations, typescript_1.default.SyntaxKind.ExtendsKeyword).map((t) => context.converter.convertType(reflectionContext, t));
if (extendedTypes.length) {
reflection.extendedTypes = extendedTypes;
}
const implementedTypes = (0, nodes_1.getHeritageTypes)(declarations, typescript_1.default.SyntaxKind.ImplementsKeyword).map((t) => context.converter.convertType(reflectionContext, t));
if (implementedTypes.length) {
reflection.implementedTypes = implementedTypes;
}
context.finalizeDeclarationReflection(reflection);
if (classDeclaration) {
// Classes can have static props
const staticType = context.checker.getTypeOfSymbolAtLocation(symbol, classDeclaration);
reflectionContext.shouldBeStatic = true;
for (const prop of context.checker.getPropertiesOfType(staticType)) {
// Don't convert namespace members, or the prototype here.
if (prop.flags &
(typescript_1.default.SymbolFlags.ModuleMember | typescript_1.default.SymbolFlags.Prototype))
continue;
convertSymbol(reflectionContext, prop);
}
reflectionContext.shouldBeStatic = false;
const ctors = staticType.getConstructSignatures();
const constructMember = reflectionContext.createDeclarationReflection(models_1.ReflectionKind.Constructor, ctors?.[0]?.declaration?.symbol, void 0, "constructor");
// Modifiers are the same for all constructors
if (ctors.length && ctors[0].declaration) {
setModifiers(symbol, ctors[0].declaration, constructMember);
}
context.finalizeDeclarationReflection(constructMember);
const constructContext = reflectionContext.withScope(constructMember);
ctors.forEach((sig) => {
(0, signature_1.createSignature)(constructContext, models_1.ReflectionKind.ConstructorSignature, sig, symbol);
});
}
// Classes/interfaces usually just have properties...
convertSymbols(reflectionContext, context.checker.getPropertiesOfType(instanceType));
// And type arguments
if (instanceType.typeParameters) {
reflection.typeParameters = instanceType.typeParameters.map((param) => {
const declaration = param.symbol?.declarations?.[0];
(0, assert_1.default)(declaration && typescript_1.default.isTypeParameterDeclaration(declaration));
return (0, signature_1.createTypeParamReflection)(declaration, reflectionContext);
});
}
// Interfaces might also have call signatures
// Classes might too, because of declaration merging
context.checker
.getSignaturesOfType(instanceType, typescript_1.default.SignatureKind.Call)
.forEach((sig) => (0, signature_1.createSignature)(reflectionContext, models_1.ReflectionKind.CallSignature, sig, symbol));
// We also might have constructor signatures
// This is potentially a problem with classes having multiple "constructor" members...
// but nobody has complained yet.
convertConstructSignatures(reflectionContext, symbol);
// And finally, index signatures
(0, index_signature_1.convertIndexSignature)(reflectionContext, symbol);
// Normally this shouldn't matter, unless someone did something with skipLibCheck on.
return typescript_1.default.SymbolFlags.Alias;
}
function convertProperty(context, symbol, exportSymbol) {
// This might happen if we're converting a function-module created with Object.assign
// or `export default () => {}`
if (context.scope.kindOf(models_1.ReflectionKind.VariableContainer)) {
return convertVariable(context, symbol, exportSymbol);
}
const declarations = symbol.getDeclarations() ?? [];
// Don't do anything if we inherited this property and it is private.
if (isInherited(context, symbol) &&
declarations.length > 0 &&
(0, enum_1.hasAllFlags)(typescript_1.default.getCombinedModifierFlags(declarations[0]), typescript_1.default.ModifierFlags.Private)) {
return;
}
// Special case: We pretend properties are methods if they look like methods.
// This happens with mixins / weird inheritance.
if (declarations.length &&
declarations.every((decl) => typescript_1.default.isMethodSignature(decl) || typescript_1.default.isMethodDeclaration(decl))) {
return convertFunctionOrMethod(context, symbol, exportSymbol);
}
if (declarations.length === 1) {
const declaration = declarations[0];
// Special case: "arrow methods" should be treated as methods.
if (typescript_1.default.isPropertyDeclaration(declaration) &&
!declaration.type &&
declaration.initializer &&
typescript_1.default.isArrowFunction(declaration.initializer)) {
return convertArrowAsMethod(context, symbol, declaration.initializer, exportSymbol);
}
}
const reflection = context.createDeclarationReflection(context.scope.kindOf(models_1.ReflectionKind.VariableContainer)
? models_1.ReflectionKind.Variable
: models_1.ReflectionKind.Property, symbol, exportSymbol);
reflection.conversionFlags |= models_1.ConversionFlags.VariableOrPropertySource;
const declaration = symbol.getDeclarations()?.[0];
let parameterType;
if (declaration &&
(typescript_1.default.isPropertyDeclaration(declaration) ||
typescript_1.default.isPropertySignature(declaration) ||
typescript_1.default.isParameter(declaration) ||
typescript_1.default.isPropertyAccessExpression(declaration) ||
typescript_1.default.isPropertyAssignment(declaration))) {
if (!typescript_1.default.isPropertyAccessExpression(declaration) &&
!typescript_1.default.isPropertyAssignment(declaration)) {
parameterType = declaration.type;
}
setModifiers(symbol, declaration, reflection);
}
reflection.defaultValue = declaration && (0, convert_expression_1.convertDefaultValue)(declaration);
reflection.type = context.converter.convertType(context.withScope(reflection), (context.convertingTypeNode ? parameterType : void 0) ??
context.checker.getTypeOfSymbol(symbol));
if (reflection.flags.isOptional) {
reflection.type = (0, reflections_1.removeUndefined)(reflection.type);
}
context.finalizeDeclarationReflection(reflection);
}
function convertArrowAsMethod(context, symbol, arrow, exportSymbol) {
const reflection = context.createDeclarationReflection(models_1.ReflectionKind.Method, symbol, exportSymbol, void 0);
setModifiers(symbol, arrow.parent, reflection);
context.finalizeDeclarationReflection(reflection);
const rc = context.withScope(reflection);
const locationDeclaration = symbol.parent
?.getDeclarations()
?.find((d) => typescript_1.default.isClassDeclaration(d) || typescript_1.default.isInterfaceDeclaration(d)) ??
symbol.parent?.getDeclarations()?.[0]?.getSourceFile() ??
symbol.getDeclarations()?.[0]?.getSourceFile();
(0, assert_1.default)(locationDeclaration, "Missing declaration context");
const type = context.checker.getTypeOfSymbolAtLocation(symbol, locationDeclaration);
const signatures = type.getNonNullableType().getCallSignatures();
(0, assert_1.default)(signatures.length, "Missing signatures");
(0, signature_1.createSignature)(rc, models_1.ReflectionKind.CallSignature, signatures[0], symbol, arrow);
}
function convertConstructor(context, symbol) {
const reflection = context.createDeclarationReflection(models_1.ReflectionKind.Constructor, symbol, void 0, "constructor");
context.finalizeDeclarationReflection(reflection);
const reflectionContext = context.withScope(reflection);
const declarations = symbol.getDeclarations()?.filter(typescript_1.default.isConstructorDeclaration) ?? [];
const signatures = declarations.map((decl) => {
const sig = context.checker.getSignatureFromDeclaration(decl);
(0, assert_1.default)(sig);
return sig;
});
for (const sig of signatures) {
(0, signature_1.createSignature)(reflectionContext, models_1.ReflectionKind.ConstructorSignature, sig, symbol);
}
}
function convertConstructSignatures(context, symbol) {
const type = context.checker.getDeclaredTypeOfSymbol(symbol);
// These get added as a "constructor" member of this interface. This is a problem... but nobody
// has complained yet. We really ought to have a constructSignatures property on the reflection instead.
const constructSignatures = context.checker.getSignaturesOfType(type, typescript_1.default.SignatureKind.Construct);
if (constructSignatures.length) {
const constructMember = new models_1.DeclarationReflection("constructor", models_1.ReflectionKind.Constructor, context.scope);
context.postReflectionCreation(constructMember, symbol, void 0);
context.finalizeDeclarationReflection(constructMember);
const constructContext = context.withScope(constructMember);
constructSignatures.forEach((sig) => (0, signature_1.createSignature)(constructContext, models_1.ReflectionKind.ConstructorSignature, sig, symbol));
}
}
function convertAlias(context, symbol, exportSymbol) {
const reflection = context.project.getReflectionFromSymbol(context.resolveAliasedSymbol(symbol));
if (!reflection) {
// We don't have this, convert it.
convertSymbol(context, context.resolveAliasedSymbol(symbol), exportSymbol ?? symbol);
}
else {
createAlias(reflection, context, symbol, exportSymbol);
}
}
function createAlias(target, context, symbol, exportSymbol) {
if (context.converter.excludeReferences)
return;
// We already have this. Create a reference.
const ref = new models_1.ReferenceReflection(exportSymbol?.name ?? symbol.name, target, context.scope);
context.postReflectionCreation(ref, symbol, exportSymbol);
context.finalizeDeclarationReflection(ref);
}
function convertVariable(context, symbol, exportSymbol) {
const declaration = symbol.getDeclarations()?.[0];
const comment = context.getComment(symbol, models_1.ReflectionKind.Variable);
const type = declaration
? context.checker.getTypeOfSymbolAtLocation(symbol, declaration)
: context.checker.getTypeOfSymbol(symbol);
if (isEnumLike(context.checker, type, declaration) &&
comment?.hasModifier("@enum")) {
return convertVariableAsEnum(context, symbol, exportSymbol);
}
if (comment?.hasModifier("@namespace")) {
return convertVariableAsNamespace(context, symbol, exportSymbol);
}
if (comment?.hasModifier("@class")) {
return convertSymbolAsClass(context, symbol, exportSymbol);
}
if (type.getCallSignatures().length &&
!type.getConstructSignatures().length) {
return convertVariableAsFunction(context, symbol, exportSymbol);
}
const reflection = context.createDeclarationReflection(context.scope.kindOf(models_1.ReflectionKind.VariableContainer)
? models_1.ReflectionKind.Variable
: models_1.ReflectionKind.Property, symbol, exportSymbol);
let typeNode;
if (declaration && typescript_1.default.isVariableDeclaration(declaration)) {
// Otherwise we might have destructuring
typeNode = declaration.type;
}
reflection.type = context.converter.convertType(context.withScope(reflection), typeNode ?? type);
setModifiers(symbol, declaration, reflection);
reflection.defaultValue = (0, convert_expression_1.convertDefaultValue)(declaration);
context.finalizeDeclarationReflection(reflection);
return typescript_1.default.SymbolFlags.Property;
}
function isEnumLike(checker, type, location) {
if (!location || !(0, enum_1.hasAllFlags)(type.flags, typescript_1.default.TypeFlags.Object)) {
return false;
}
return type.getProperties().every((prop) => {
const propType = checker.getTypeOfSymbolAtLocation(prop, location);
return isValidEnumProperty(propType);
});
}
function isValidEnumProperty(type) {
return (0, enum_1.hasAnyFlag)(type.flags, typescript_1.default.TypeFlags.NumberLike | typescript_1.default.TypeFlags.StringLike);
}
function convertVariableAsEnum(context, symbol, exportSymbol) {
const reflection = context.createDeclarationReflection(models_1.ReflectionKind.Enum, symbol, exportSymbol);
context.finalizeDeclarationReflection(reflection);
const rc = context.withScope(reflection);
const declaration = symbol.declarations[0];
const type = context.checker.getTypeAtLocation(declaration);
for (const prop of type.getProperties()) {
const reflection = rc.createDeclarationReflection(models_1.ReflectionKind.EnumMember, prop, void 0);
const propType = context.checker.getTypeOfSymbolAtLocation(prop, declaration);
reflection.type = context.converter.convertType(context, propType);
rc.finalizeDeclarationReflection(reflection);
}
// Skip converting the type alias, if there is one
return typescript_1.default.SymbolFlags.TypeAlias;
}
function convertVariableAsNamespace(context, symbol, exportSymbol) {
const reflection = context.createDeclarationReflection(models_1.ReflectionKind.Namespace, symbol, exportSymbol);
context.finalizeDeclarationReflection(reflection);
const rc = context.withScope(reflection);
const declaration = symbol.declarations?.find(typescript_1.default.isVariableDeclaration);
(0, assert_1.default)(declaration, "Missing variable declaration");
const type = context.checker.getTypeAtLocation(declaration);
convertSymbols(rc, type.getProperties());
return typescript_1.default.SymbolFlags.Property;
}
function convertVariableAsFunction(context, symbol, exportSymbol) {
const declaration = symbol
.getDeclarations()
?.find(typescript_1.default.isVariableDeclaration);
const accessDeclaration = declaration ?? symbol.valueDeclaration;
const type = accessDeclaration
? context.checker.getTypeOfSymbolAtLocation(symbol, accessDeclaration)
: context.checker.getDeclaredTypeOfSymbol(symbol);
const reflection = context.createDeclarationReflection(context.scope.kindOf(models_1.ReflectionKind.MethodContainer)
? models_1.ReflectionKind.Method
: models_1.ReflectionKind.Function, symbol, exportSymbol);
setModifiers(symbol, accessDeclaration, reflection);
reflection.conversionFlags |= models_1.ConversionFlags.VariableOrPropertySource;
context.finalizeDeclarationReflection(reflection);
const reflectionContext = context.withScope(reflection);
reflection.signatures ??= [];
for (const signature of type.getCallSignatures()) {
(0, signature_1.createSignature)(reflectionContext, models_1.ReflectionKind.CallSignature, signature, symbol);
}
return (convertFunctionProperties(context.withScope(reflection), symbol, type) |
typescript_1.default.SymbolFlags.Property);
}
function convertFunctionProperties(context, symbol, type) {
// #2436/#2461: Functions created with Object.assign on a function likely have properties
// that we should document. We also add properties to the function if they are defined like:
// function f() {}
// f.x = 123;
// rather than creating a separate namespace.
// In the expando case, we'll have both namespace flags.
// In the Object.assign case, we'll have no namespace flags.
const nsFlags = typescript_1.default.SymbolFlags.ValueModule | typescript_1.default.SymbolFlags.NamespaceModule;
if (type.getProperties().length &&
((0, enum_1.hasAllFlags)(symbol.flags, nsFlags) ||
!(0, enum_1.hasAnyFlag)(symbol.flags, nsFlags))) {
convertSymbols(context, type.getProperties());
return typescript_1.default.SymbolFlags.NamespaceModule;
}
return typescript_1.default.SymbolFlags.None;
}
function convertSymbolAsClass(context, symbol, exportSymbol) {
const reflection = context.createDeclarationReflection(models_1.ReflectionKind.Class, symbol, exportSymbol);
const rc = context.withScope(reflection);
context.finalizeDeclarationReflection(reflection);
if (!symbol.valueDeclaration) {
context.logger.error(`No value declaration found when converting ${symbol.name} as a class`, symbol.declarations?.[0]);
return;
}
const type = context.checker.getTypeOfSymbolAtLocation(symbol, symbol.valueDeclaration);
rc.shouldBeStatic = true;
convertSymbols(rc,
// Prototype is implicitly this class, don't document it.
type.getProperties().filter((prop) => prop.name !== "prototype"));
for (const sig of type.getCallSignatures()) {
(0, signature_1.createSignature)(rc, models_1.ReflectionKind.CallSignature, sig, undefined);
}
rc.shouldBeStatic = false;
const ctors = type.getConstructSignatures();
if (ctors.length) {
const constructMember = rc.createDeclarationReflection(models_1.ReflectionKind.Constructor, ctors?.[0]?.declaration?.symbol, void 0, "constructor");
// Modifiers are the same for all constructors
if (ctors.length && ctors[0].declaration) {
setModifiers(symbol, ctors[0].declaration, constructMember);
}
context.finalizeDeclarationReflection(constructMember);
const constructContext = rc.withScope(constructMember);
for (const sig of ctors) {
(0, signature_1.createConstructSignatureWithType)(constructContext, sig, reflection);
}
const instType = ctors[0].getReturnType();
convertSymbols(rc, instType.getProperties());
for (const sig of instType.getCallSignatures()) {
(0, signature_1.createSignature)(rc, models_1.ReflectionKind.CallSignature, sig, undefined);
}
}
else {
context.logger.warn(`${reflection.getFriendlyFullName()} is being converted as a class, but does not have any construct signatures`, symbol.valueDeclaration);
}
return (typescript_1.default.SymbolFlags.TypeAlias |
typescript_1.default.SymbolFlags.Interface |
typescript_1.default.SymbolFlags.Namespace);
}
function convertAccessor(context, symbol, exportSymbol) {
const reflection = context.createDeclarationReflection(models_1.ReflectionKind.Accessor, symbol, exportSymbol);
const rc = context.withScope(reflection);
const declaration = symbol.getDeclarations()?.[0];
if (declaration) {
setModifiers(symbol, declaration, reflection);
}
context.finalizeDeclarationReflection(reflection);
const getDeclaration = symbol.getDeclarations()?.find(typescript_1.default.isGetAccessor);
if (getDeclaration) {
const signature = context.checker.getSignatureFromDeclaration(getDeclaration);
if (signature) {
(0, signature_1.createSignature)(rc, models_1.ReflectionKind.GetSignature, signature, symbol, getDeclaration);
}
}
const setDeclaration = symbol.getDeclarations()?.find(typescript_1.default.isSetAccessor);
if (setDeclaration) {
const signature = context.checker.getSignatureFromDeclaration(setDeclaration);
if (signature) {
(0, signature_1.createSignature)(rc, models_1.ReflectionKind.SetSignature, signature, symbol, setDeclaration);
}
}
}
function isInherited(context, symbol) {
const parentSymbol = context.project.getSymbolFromReflection(context.scope);
// It'd be nice to be able to assert that this is true, but sometimes object
// types don't get symbols if they are inferred.
if (!parentSymbol)
return false;
const parents = parentSymbol.declarations?.slice() || [];
const constructorDecls = parents.flatMap((parent) => typescript_1.default.isClassDeclaration(parent)
? parent.members.filter(typescript_1.default.isConstructorDeclaration)
: []);
parents.push(...constructorDecls);
return (parents.some((d) => symbol.getDeclarations()?.some((d2) => d2.parent === d)) === false);
}
function setModifiers(symbol, declaration, reflection) {
if (!declaration) {
return;
}
const modifiers = typescript_1.default.getCombinedModifierFlags(declaration);
if (typescript_1.default.isMethodDeclaration(declaration) ||
typescript_1.default.isPropertyDeclaration(declaration) ||
typescript_1.default.isAccessor(declaration)) {
if (typescript_1.default.isPrivateIdentifier(declaration.name)) {
reflection.setFlag(models_1.ReflectionFlag.Private);
}
}
if ((0, enum_1.hasAllFlags)(modifiers, typescript_1.default.ModifierFlags.Private)) {
reflection.setFlag(models_1.ReflectionFlag.Private);
}
if ((0, enum_1.hasAllFlags)(modifiers, typescript_1.default.ModifierFlags.Protected)) {
reflection.setFlag(models_1.ReflectionFlag.Protected);
}
if ((0, enum_1.hasAllFlags)(modifiers, typescript_1.default.ModifierFlags.Public)) {
reflection.setFlag(models_1.ReflectionFlag.Public);
}
reflection.setFlag(models_1.ReflectionFlag.Optional, (0, enum_1.hasAllFlags)(symbol.flags, typescript_1.default.SymbolFlags.Optional));
reflection.setFlag(models_1.ReflectionFlag.Readonly, (0, enum_1.hasAllFlags)(typescript_1.default.getCheckFlags(symbol), typescript_1.default.CheckFlags.Readonly) ||
(0, enum_1.hasAllFlags)(modifiers, typescript_1.default.ModifierFlags.Readonly));
reflection.setFlag(models_1.ReflectionFlag.Abstract, (0, enum_1.hasAllFlags)(modifiers, typescript_1.default.ModifierFlags.Abstract));
if (reflection.kindOf(models_1.ReflectionKind.Variable) &&
(0, enum_1.hasAllFlags)(symbol.flags, typescript_1.default.SymbolFlags.BlockScopedVariable)) {
reflection.setFlag(models_1.ReflectionFlag.Const, (0, enum_1.hasAllFlags)(declaration.parent.flags, typescript_1.default.NodeFlags.Const));
}
// ReflectionFlag.Static happens when constructing the reflection.
// We don't have sufficient information here to determine if it ought to be static.
}

10
node_modules/typedoc/dist/lib/converter/types.d.ts generated vendored Normal file
View File

@@ -0,0 +1,10 @@
import ts from "typescript";
import { SomeType } from "../models";
import type { Context } from "./context";
export interface TypeConverter<TNode extends ts.TypeNode = ts.TypeNode, TType extends ts.Type = ts.Type> {
kind: TNode["kind"][];
convert(context: Context, node: TNode): SomeType;
convertType(context: Context, type: TType, node: TNode): SomeType;
}
export declare function loadConverters(): void;
export declare function convertType(context: Context, typeOrNode: ts.Type | ts.TypeNode | undefined): SomeType;

730
node_modules/typedoc/dist/lib/converter/types.js generated vendored Normal file
View File

@@ -0,0 +1,730 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertType = exports.loadConverters = void 0;
const assert_1 = __importDefault(require("assert"));
const typescript_1 = __importDefault(require("typescript"));
const models_1 = require("../models");
const ReflectionSymbolId_1 = require("../models/reflections/ReflectionSymbolId");
const array_1 = require("../utils/array");
const converter_events_1 = require("./converter-events");
const index_signature_1 = require("./factories/index-signature");
const signature_1 = require("./factories/signature");
const symbols_1 = require("./symbols");
const nodes_1 = require("./utils/nodes");
const reflections_1 = require("./utils/reflections");
const converters = new Map();
function loadConverters() {
if (converters.size)
return;
for (const actor of [
arrayConverter,
conditionalConverter,
constructorConverter,
exprWithTypeArgsConverter,
functionTypeConverter,
importType,
indexedAccessConverter,
inferredConverter,
intersectionConverter,
intrinsicConverter,
jsDocVariadicTypeConverter,
keywordConverter,
optionalConverter,
parensConverter,
predicateConverter,
queryConverter,
typeLiteralConverter,
referenceConverter,
restConverter,
namedTupleMemberConverter,
mappedConverter,
literalTypeConverter,
templateLiteralConverter,
thisConverter,
tupleConverter,
typeOperatorConverter,
unionConverter,
// Only used if skipLibCheck: true
jsDocNullableTypeConverter,
jsDocNonNullableTypeConverter,
]) {
for (const key of actor.kind) {
if (key === undefined) {
// Might happen if running on an older TS version.
continue;
}
(0, assert_1.default)(!converters.has(key));
converters.set(key, actor);
}
}
}
exports.loadConverters = loadConverters;
// This ought not be necessary, but we need some way to discover recursively
// typed symbols which do not have type nodes. See the `recursive` symbol in the variables test.
const seenTypes = new Set();
function maybeConvertType(context, typeOrNode) {
if (!typeOrNode) {
return;
}
return convertType(context, typeOrNode);
}
let typeConversionDepth = 0;
function convertType(context, typeOrNode) {
if (!typeOrNode) {
return new models_1.IntrinsicType("any");
}
if (typeConversionDepth > context.converter.maxTypeConversionDepth) {
return new models_1.UnknownType("...");
}
loadConverters();
if ("kind" in typeOrNode) {
const converter = converters.get(typeOrNode.kind);
if (converter) {
++typeConversionDepth;
const result = converter.convert(context, typeOrNode);
--typeConversionDepth;
return result;
}
return requestBugReport(context, typeOrNode);
}
// TS 4.2 added this to enable better tracking of type aliases.
// We need to check it here, not just in the union checker, because typeToTypeNode
// will use the origin when serializing
// aliasSymbol check is important - #2468
if (typeOrNode.isUnion() && typeOrNode.origin && !typeOrNode.aliasSymbol) {
// Don't increment typeConversionDepth as this is a transparent step to the user.
return convertType(context, typeOrNode.origin);
}
// IgnoreErrors is important, without it, we can't assert that we will get a node.
const node = context.checker.typeToTypeNode(typeOrNode, void 0, typescript_1.default.NodeBuilderFlags.IgnoreErrors);
(0, assert_1.default)(node); // According to the TS source of typeToString, this is a bug if it does not hold.
if (seenTypes.has(typeOrNode.id)) {
const typeString = context.checker.typeToString(typeOrNode);
context.logger.verbose(`Refusing to recurse when converting type: ${typeString}`);
return new models_1.UnknownType(typeString);
}
let converter = converters.get(node.kind);
if (converter) {
// Hacky fix for #2011, need to find a better way to choose the converter.
if (converter === intersectionConverter &&
!typeOrNode.isIntersection()) {
converter = typeLiteralConverter;
}
seenTypes.add(typeOrNode.id);
++typeConversionDepth;
const result = converter.convertType(context, typeOrNode, node);
--typeConversionDepth;
seenTypes.delete(typeOrNode.id);
return result;
}
return requestBugReport(context, typeOrNode);
}
exports.convertType = convertType;
const arrayConverter = {
kind: [typescript_1.default.SyntaxKind.ArrayType],
convert(context, node) {
return new models_1.ArrayType(convertType(context, node.elementType));
},
convertType(context, type) {
const params = context.checker.getTypeArguments(type);
// This is *almost* always true... except for when this type is in the constraint of a type parameter see GH#1408
// assert(params.length === 1);
(0, assert_1.default)(params.length > 0);
return new models_1.ArrayType(convertType(context, params[0]));
},
};
const conditionalConverter = {
kind: [typescript_1.default.SyntaxKind.ConditionalType],
convert(context, node) {
return new models_1.ConditionalType(convertType(context, node.checkType), convertType(context, node.extendsType), convertType(context, node.trueType), convertType(context, node.falseType));
},
convertType(context, type) {
return new models_1.ConditionalType(convertType(context, type.checkType), convertType(context, type.extendsType), convertType(context, type.resolvedTrueType), convertType(context, type.resolvedFalseType));
},
};
const constructorConverter = {
kind: [typescript_1.default.SyntaxKind.ConstructorType],
convert(context, node) {
const symbol = context.getSymbolAtLocation(node) ?? node.symbol;
const type = context.getTypeAtLocation(node);
if (!symbol || !type) {
return new models_1.IntrinsicType("Function");
}
const reflection = new models_1.DeclarationReflection("__type", models_1.ReflectionKind.Constructor, context.scope);
const rc = context.withScope(reflection);
rc.convertingTypeNode = true;
context.registerReflection(reflection, symbol);
context.trigger(converter_events_1.ConverterEvents.CREATE_DECLARATION, reflection);
const signature = new models_1.SignatureReflection("__type", models_1.ReflectionKind.ConstructorSignature, reflection);
// This is unfortunate... but seems the obvious place to put this with the current
// architecture. Ideally, this would be a property on a "ConstructorType"... but that
// needs to wait until TypeDoc 0.22 when making other breaking changes.
if (node.modifiers?.some((m) => m.kind === typescript_1.default.SyntaxKind.AbstractKeyword)) {
signature.setFlag(models_1.ReflectionFlag.Abstract);
}
context.project.registerSymbolId(signature, new ReflectionSymbolId_1.ReflectionSymbolId(symbol, node));
context.registerReflection(signature, void 0);
const signatureCtx = rc.withScope(signature);
reflection.signatures = [signature];
signature.type = convertType(signatureCtx, node.type);
signature.parameters = (0, signature_1.convertParameterNodes)(signatureCtx, signature, node.parameters);
signature.typeParameters = (0, signature_1.convertTypeParameterNodes)(signatureCtx, node.typeParameters);
return new models_1.ReflectionType(reflection);
},
convertType(context, type) {
const symbol = type.getSymbol();
if (!symbol) {
return new models_1.IntrinsicType("Function");
}
const reflection = new models_1.DeclarationReflection("__type", models_1.ReflectionKind.Constructor, context.scope);
context.registerReflection(reflection, symbol);
context.trigger(converter_events_1.ConverterEvents.CREATE_DECLARATION, reflection);
(0, signature_1.createSignature)(context.withScope(reflection), models_1.ReflectionKind.ConstructorSignature, type.getConstructSignatures()[0], symbol);
return new models_1.ReflectionType(reflection);
},
};
const exprWithTypeArgsConverter = {
kind: [typescript_1.default.SyntaxKind.ExpressionWithTypeArguments],
convert(context, node) {
const targetSymbol = context.getSymbolAtLocation(node.expression);
// Mixins... we might not have a symbol here.
if (!targetSymbol) {
return convertType(context, context.checker.getTypeAtLocation(node));
}
const parameters = node.typeArguments?.map((type) => convertType(context, type)) ?? [];
const ref = models_1.ReferenceType.createSymbolReference(context.resolveAliasedSymbol(targetSymbol), context);
ref.typeArguments = parameters;
return ref;
},
convertType: requestBugReport,
};
const functionTypeConverter = {
kind: [typescript_1.default.SyntaxKind.FunctionType],
convert(context, node) {
const symbol = context.getSymbolAtLocation(node) ?? node.symbol;
const type = context.getTypeAtLocation(node);
if (!symbol || !type) {
return new models_1.IntrinsicType("Function");
}
const reflection = new models_1.DeclarationReflection("__type", models_1.ReflectionKind.TypeLiteral, context.scope);
const rc = context.withScope(reflection);
context.registerReflection(reflection, symbol);
context.trigger(converter_events_1.ConverterEvents.CREATE_DECLARATION, reflection);
const signature = new models_1.SignatureReflection("__type", models_1.ReflectionKind.CallSignature, reflection);
context.project.registerSymbolId(signature, new ReflectionSymbolId_1.ReflectionSymbolId(symbol, node));
context.registerReflection(signature, void 0);
const signatureCtx = rc.withScope(signature);
reflection.signatures = [signature];
signature.type = convertType(signatureCtx, node.type);
signature.parameters = (0, signature_1.convertParameterNodes)(signatureCtx, signature, node.parameters);
signature.typeParameters = (0, signature_1.convertTypeParameterNodes)(signatureCtx, node.typeParameters);
return new models_1.ReflectionType(reflection);
},
convertType(context, type) {
const symbol = type.getSymbol();
if (!symbol) {
return new models_1.IntrinsicType("Function");
}
const reflection = new models_1.DeclarationReflection("__type", models_1.ReflectionKind.TypeLiteral, context.scope);
context.registerReflection(reflection, symbol);
context.trigger(converter_events_1.ConverterEvents.CREATE_DECLARATION, reflection);
(0, signature_1.createSignature)(context.withScope(reflection), models_1.ReflectionKind.CallSignature, type.getCallSignatures()[0], type.getSymbol());
return new models_1.ReflectionType(reflection);
},
};
const importType = {
kind: [typescript_1.default.SyntaxKind.ImportType],
convert(context, node) {
const name = node.qualifier?.getText() ?? "__module";
const symbol = context.checker.getSymbolAtLocation(node);
(0, assert_1.default)(symbol, "Missing symbol when converting import type node");
return models_1.ReferenceType.createSymbolReference(context.resolveAliasedSymbol(symbol), context, name);
},
convertType(context, type) {
const symbol = type.getSymbol();
(0, assert_1.default)(symbol, "Missing symbol when converting import type"); // Should be a compiler error
return models_1.ReferenceType.createSymbolReference(context.resolveAliasedSymbol(symbol), context, "__module");
},
};
const indexedAccessConverter = {
kind: [typescript_1.default.SyntaxKind.IndexedAccessType],
convert(context, node) {
return new models_1.IndexedAccessType(convertType(context, node.objectType), convertType(context, node.indexType));
},
convertType(context, type) {
return new models_1.IndexedAccessType(convertType(context, type.objectType), convertType(context, type.indexType));
},
};
const inferredConverter = {
kind: [typescript_1.default.SyntaxKind.InferType],
convert(context, node) {
return new models_1.InferredType(node.typeParameter.name.text, maybeConvertType(context, node.typeParameter.constraint));
},
convertType(context, type) {
return new models_1.InferredType(type.getSymbol().name, maybeConvertType(context, type.getConstraint()));
},
};
const intersectionConverter = {
kind: [typescript_1.default.SyntaxKind.IntersectionType],
convert(context, node) {
return new models_1.IntersectionType(node.types.map((type) => convertType(context, type)));
},
convertType(context, type) {
return new models_1.IntersectionType(type.types.map((type) => convertType(context, type)));
},
};
const intrinsicConverter = {
kind: [typescript_1.default.SyntaxKind.IntrinsicKeyword],
convert() {
return new models_1.IntrinsicType("intrinsic");
},
convertType() {
return new models_1.IntrinsicType("intrinsic");
},
};
const jsDocVariadicTypeConverter = {
kind: [typescript_1.default.SyntaxKind.JSDocVariadicType],
convert(context, node) {
return new models_1.ArrayType(convertType(context, node.type));
},
// Should just be an ArrayType
convertType: requestBugReport,
};
const keywordNames = {
[typescript_1.default.SyntaxKind.AnyKeyword]: "any",
[typescript_1.default.SyntaxKind.BigIntKeyword]: "bigint",
[typescript_1.default.SyntaxKind.BooleanKeyword]: "boolean",
[typescript_1.default.SyntaxKind.NeverKeyword]: "never",
[typescript_1.default.SyntaxKind.NumberKeyword]: "number",
[typescript_1.default.SyntaxKind.ObjectKeyword]: "object",
[typescript_1.default.SyntaxKind.StringKeyword]: "string",
[typescript_1.default.SyntaxKind.SymbolKeyword]: "symbol",
[typescript_1.default.SyntaxKind.UndefinedKeyword]: "undefined",
[typescript_1.default.SyntaxKind.UnknownKeyword]: "unknown",
[typescript_1.default.SyntaxKind.VoidKeyword]: "void",
[typescript_1.default.SyntaxKind.IntrinsicKeyword]: "intrinsic",
};
const keywordConverter = {
kind: [
typescript_1.default.SyntaxKind.AnyKeyword,
typescript_1.default.SyntaxKind.BigIntKeyword,
typescript_1.default.SyntaxKind.BooleanKeyword,
typescript_1.default.SyntaxKind.NeverKeyword,
typescript_1.default.SyntaxKind.NumberKeyword,
typescript_1.default.SyntaxKind.ObjectKeyword,
typescript_1.default.SyntaxKind.StringKeyword,
typescript_1.default.SyntaxKind.SymbolKeyword,
typescript_1.default.SyntaxKind.UndefinedKeyword,
typescript_1.default.SyntaxKind.UnknownKeyword,
typescript_1.default.SyntaxKind.VoidKeyword,
],
convert(_context, node) {
return new models_1.IntrinsicType(keywordNames[node.kind]);
},
convertType(_context, _type, node) {
return new models_1.IntrinsicType(keywordNames[node.kind]);
},
};
const optionalConverter = {
kind: [typescript_1.default.SyntaxKind.OptionalType],
convert(context, node) {
return new models_1.OptionalType((0, reflections_1.removeUndefined)(convertType(context, node.type)));
},
// Handled by the tuple converter
convertType: requestBugReport,
};
const parensConverter = {
kind: [typescript_1.default.SyntaxKind.ParenthesizedType],
convert(context, node) {
return convertType(context, node.type);
},
// TS strips these out too... shouldn't run into this.
convertType: requestBugReport,
};
const predicateConverter = {
kind: [typescript_1.default.SyntaxKind.TypePredicate],
convert(context, node) {
const name = typescript_1.default.isThisTypeNode(node.parameterName)
? "this"
: node.parameterName.getText();
const asserts = !!node.assertsModifier;
const targetType = node.type ? convertType(context, node.type) : void 0;
return new models_1.PredicateType(name, asserts, targetType);
},
// Never inferred by TS 4.0, could potentially change in a future TS version.
convertType: requestBugReport,
};
// This is a horrible thing... we're going to want to split this into converters
// for different types at some point.
const typeLiteralConverter = {
kind: [typescript_1.default.SyntaxKind.TypeLiteral],
convert(context, node) {
const symbol = context.getSymbolAtLocation(node) ?? node.symbol;
const type = context.getTypeAtLocation(node);
if (!symbol || !type) {
return new models_1.IntrinsicType("Object");
}
const reflection = new models_1.DeclarationReflection("__type", models_1.ReflectionKind.TypeLiteral, context.scope);
const rc = context.withScope(reflection);
rc.convertingTypeNode = true;
context.registerReflection(reflection, symbol);
context.trigger(converter_events_1.ConverterEvents.CREATE_DECLARATION, reflection);
for (const prop of context.checker.getPropertiesOfType(type)) {
(0, symbols_1.convertSymbol)(rc, prop);
}
for (const signature of type.getCallSignatures()) {
(0, signature_1.createSignature)(rc, models_1.ReflectionKind.CallSignature, signature, symbol);
}
for (const signature of type.getConstructSignatures()) {
(0, signature_1.createSignature)(rc, models_1.ReflectionKind.ConstructorSignature, signature, symbol);
}
(0, index_signature_1.convertIndexSignature)(rc, symbol);
return new models_1.ReflectionType(reflection);
},
convertType(context, type) {
const symbol = type.getSymbol();
const reflection = new models_1.DeclarationReflection("__type", models_1.ReflectionKind.TypeLiteral, context.scope);
context.registerReflection(reflection, symbol);
context.trigger(converter_events_1.ConverterEvents.CREATE_DECLARATION, reflection);
for (const prop of context.checker.getPropertiesOfType(type)) {
(0, symbols_1.convertSymbol)(context.withScope(reflection), prop);
}
for (const signature of type.getCallSignatures()) {
(0, signature_1.createSignature)(context.withScope(reflection), models_1.ReflectionKind.CallSignature, signature, symbol);
}
for (const signature of type.getConstructSignatures()) {
(0, signature_1.createSignature)(context.withScope(reflection), models_1.ReflectionKind.ConstructorSignature, signature, symbol);
}
if (symbol) {
(0, index_signature_1.convertIndexSignature)(context.withScope(reflection), symbol);
}
return new models_1.ReflectionType(reflection);
},
};
const queryConverter = {
kind: [typescript_1.default.SyntaxKind.TypeQuery],
convert(context, node) {
const querySymbol = context.getSymbolAtLocation(node.exprName);
if (!querySymbol) {
// This can happen if someone uses `typeof` on some property
// on a variable typed as `any` with a name that doesn't exist.
return new models_1.QueryType(models_1.ReferenceType.createBrokenReference(node.exprName.getText(), context.project));
}
const ref = models_1.ReferenceType.createSymbolReference(context.resolveAliasedSymbol(querySymbol), context, node.exprName.getText());
ref.preferValues = true;
return new models_1.QueryType(ref);
},
convertType(context, type, node) {
// Order matters here - check the node location first so that if the typeof is targeting
// an instantiation expression we get the user's exprName.
const symbol = context.getSymbolAtLocation(node.exprName) || type.getSymbol();
(0, assert_1.default)(symbol, `Query type failed to get a symbol for: ${context.checker.typeToString(type)}. This is a bug.`);
const ref = models_1.ReferenceType.createSymbolReference(context.resolveAliasedSymbol(symbol), context);
ref.preferValues = true;
return new models_1.QueryType(ref);
},
};
const referenceConverter = {
kind: [typescript_1.default.SyntaxKind.TypeReference],
convert(context, node) {
const isArray = context.checker.typeToTypeNode(context.checker.getTypeAtLocation(node.typeName), void 0, typescript_1.default.NodeBuilderFlags.IgnoreErrors)?.kind === typescript_1.default.SyntaxKind.ArrayType;
if (isArray) {
return new models_1.ArrayType(convertType(context, node.typeArguments?.[0]));
}
const symbol = context.expectSymbolAtLocation(node.typeName);
const name = node.typeName.getText();
const type = models_1.ReferenceType.createSymbolReference(context.resolveAliasedSymbol(symbol), context, name);
type.typeArguments = node.typeArguments?.map((type) => convertType(context, type));
return type;
},
convertType(context, type, node) {
// typeName.symbol handles the case where this is a union which happens to refer
// to an enumeration. TS doesn't put the symbol on the type for some reason, but
// does add it to the constructed type node.
const symbol = type.aliasSymbol ?? type.getSymbol() ?? node.typeName.symbol;
if (!symbol) {
// This happens when we get a reference to a type parameter
// created within a mapped type, `K` in: `{ [K in T]: string }`
const ref = models_1.ReferenceType.createBrokenReference(context.checker.typeToString(type), context.project);
ref.refersToTypeParameter = true;
return ref;
}
const ref = models_1.ReferenceType.createSymbolReference(context.resolveAliasedSymbol(symbol), context);
if (type.flags & typescript_1.default.TypeFlags.Substitution) {
// NoInfer<T>
ref.typeArguments = [
convertType(context, type.baseType),
];
}
else if (type.flags & typescript_1.default.TypeFlags.StringMapping) {
ref.typeArguments = [
convertType(context, type.type),
];
}
else {
ref.typeArguments = (type.aliasSymbol
? type.aliasTypeArguments
: type.typeArguments)?.map((ref) => convertType(context, ref));
}
return ref;
},
};
const restConverter = {
kind: [typescript_1.default.SyntaxKind.RestType],
convert(context, node) {
return new models_1.RestType(convertType(context, node.type));
},
// This is handled in the tuple converter
convertType: requestBugReport,
};
const namedTupleMemberConverter = {
kind: [typescript_1.default.SyntaxKind.NamedTupleMember],
convert(context, node) {
const innerType = convertType(context, node.type);
return new models_1.NamedTupleMember(node.name.getText(), !!node.questionToken, innerType);
},
// This ought to be impossible.
convertType: requestBugReport,
};
// { -readonly [K in string]-?: number}
// ^ readonlyToken
// ^ typeParameter
// ^^^^^^ typeParameter.constraint
// ^ questionToken
// ^^^^^^ type
const mappedConverter = {
kind: [typescript_1.default.SyntaxKind.MappedType],
convert(context, node) {
const optionalModifier = kindToModifier(node.questionToken?.kind);
const templateType = convertType(context, node.type);
return new models_1.MappedType(node.typeParameter.name.text, convertType(context, node.typeParameter.constraint), optionalModifier === "+"
? (0, reflections_1.removeUndefined)(templateType)
: templateType, kindToModifier(node.readonlyToken?.kind), optionalModifier, node.nameType ? convertType(context, node.nameType) : void 0);
},
convertType(context, type, node) {
// This can happen if a generic function does not have a return type annotated.
const optionalModifier = kindToModifier(node.questionToken?.kind);
const templateType = convertType(context, type.templateType);
return new models_1.MappedType(type.typeParameter.symbol?.name, convertType(context, type.typeParameter.getConstraint()), optionalModifier === "+"
? (0, reflections_1.removeUndefined)(templateType)
: templateType, kindToModifier(node.readonlyToken?.kind), optionalModifier, type.nameType ? convertType(context, type.nameType) : void 0);
},
};
const literalTypeConverter = {
kind: [typescript_1.default.SyntaxKind.LiteralType],
convert(context, node) {
switch (node.literal.kind) {
case typescript_1.default.SyntaxKind.TrueKeyword:
case typescript_1.default.SyntaxKind.FalseKeyword:
return new models_1.LiteralType(node.literal.kind === typescript_1.default.SyntaxKind.TrueKeyword);
case typescript_1.default.SyntaxKind.StringLiteral:
return new models_1.LiteralType(node.literal.text);
case typescript_1.default.SyntaxKind.NumericLiteral:
return new models_1.LiteralType(Number(node.literal.text));
case typescript_1.default.SyntaxKind.NullKeyword:
return new models_1.LiteralType(null);
case typescript_1.default.SyntaxKind.PrefixUnaryExpression: {
const operand = node.literal
.operand;
switch (operand.kind) {
case typescript_1.default.SyntaxKind.NumericLiteral:
return new models_1.LiteralType(Number(node.literal.getText()));
case typescript_1.default.SyntaxKind.BigIntLiteral:
return new models_1.LiteralType(BigInt(node.literal.getText().replace("n", "")));
default:
return requestBugReport(context, node.literal);
}
}
case typescript_1.default.SyntaxKind.BigIntLiteral:
return new models_1.LiteralType(BigInt(node.literal.getText().replace("n", "")));
case typescript_1.default.SyntaxKind.NoSubstitutionTemplateLiteral:
return new models_1.LiteralType(node.literal.text);
}
return requestBugReport(context, node.literal);
},
convertType(_context, type, node) {
switch (node.literal.kind) {
case typescript_1.default.SyntaxKind.StringLiteral:
return new models_1.LiteralType(node.literal.text);
case typescript_1.default.SyntaxKind.NumericLiteral:
return new models_1.LiteralType(+node.literal.text);
case typescript_1.default.SyntaxKind.TrueKeyword:
case typescript_1.default.SyntaxKind.FalseKeyword:
return new models_1.LiteralType(node.literal.kind === typescript_1.default.SyntaxKind.TrueKeyword);
case typescript_1.default.SyntaxKind.NullKeyword:
return new models_1.LiteralType(null);
}
if (typeof type.value === "object") {
return new models_1.LiteralType(BigInt(`${type.value.negative ? "-" : ""}${type.value.base10Value}`));
}
return new models_1.LiteralType(type.value);
},
};
const templateLiteralConverter = {
kind: [typescript_1.default.SyntaxKind.TemplateLiteralType],
convert(context, node) {
return new models_1.TemplateLiteralType(node.head.text, node.templateSpans.map((span) => {
return [convertType(context, span.type), span.literal.text];
}));
},
convertType(context, type) {
(0, assert_1.default)(type.texts.length === type.types.length + 1);
const parts = [];
for (const [a, b] of (0, array_1.zip)(type.types, type.texts.slice(1))) {
parts.push([convertType(context, a), b]);
}
return new models_1.TemplateLiteralType(type.texts[0], parts);
},
};
const thisConverter = {
kind: [typescript_1.default.SyntaxKind.ThisType],
convert() {
return new models_1.IntrinsicType("this");
},
convertType() {
return new models_1.IntrinsicType("this");
},
};
const tupleConverter = {
kind: [typescript_1.default.SyntaxKind.TupleType],
convert(context, node) {
const elements = node.elements.map((node) => convertType(context, node));
return new models_1.TupleType(elements);
},
convertType(context, type, node) {
const types = type.typeArguments?.slice(0, node.elements.length);
let elements = types?.map((type) => convertType(context, type));
if (type.target.labeledElementDeclarations) {
const namedDeclarations = type.target.labeledElementDeclarations;
elements = elements?.map((el, i) => {
const namedDecl = namedDeclarations[i];
return namedDecl
? new models_1.NamedTupleMember(namedDecl.name.getText(), !!namedDecl.questionToken, (0, reflections_1.removeUndefined)(el))
: el;
});
}
elements = elements?.map((el, i) => {
if (type.target.elementFlags[i] & typescript_1.default.ElementFlags.Variable) {
// In the node case, we don't need to add the wrapping Array type... but we do here.
if (el instanceof models_1.NamedTupleMember) {
return new models_1.RestType(new models_1.NamedTupleMember(el.name, el.isOptional, new models_1.ArrayType(el.element)));
}
return new models_1.RestType(new models_1.ArrayType(el));
}
if (type.target.elementFlags[i] & typescript_1.default.ElementFlags.Optional &&
!(el instanceof models_1.NamedTupleMember)) {
return new models_1.OptionalType((0, reflections_1.removeUndefined)(el));
}
return el;
});
return new models_1.TupleType(elements ?? []);
},
};
const supportedOperatorNames = {
[typescript_1.default.SyntaxKind.KeyOfKeyword]: "keyof",
[typescript_1.default.SyntaxKind.UniqueKeyword]: "unique",
[typescript_1.default.SyntaxKind.ReadonlyKeyword]: "readonly",
};
const typeOperatorConverter = {
kind: [typescript_1.default.SyntaxKind.TypeOperator],
convert(context, node) {
return new models_1.TypeOperatorType(convertType(context, node.type), supportedOperatorNames[node.operator]);
},
convertType(context, type, node) {
// readonly is only valid on array and tuple literal types.
if (node.operator === typescript_1.default.SyntaxKind.ReadonlyKeyword) {
const resolved = resolveReference(type);
(0, assert_1.default)((0, nodes_1.isObjectType)(resolved));
const args = context.checker
.getTypeArguments(type)
.map((type) => convertType(context, type));
const inner = resolved.objectFlags & typescript_1.default.ObjectFlags.Tuple
? new models_1.TupleType(args)
: new models_1.ArrayType(args[0]);
return new models_1.TypeOperatorType(inner, "readonly");
}
// keyof will only show up with generic functions, otherwise it gets eagerly
// resolved to a union of strings.
if (node.operator === typescript_1.default.SyntaxKind.KeyOfKeyword) {
// There's probably an interface for this somewhere... I couldn't find it.
const targetType = type.type;
return new models_1.TypeOperatorType(convertType(context, targetType), "keyof");
}
// TS drops `unique` in `unique symbol` everywhere. If someone used it, we ought
// to have a type node. This shouldn't ever happen.
return requestBugReport(context, type);
},
};
const unionConverter = {
kind: [typescript_1.default.SyntaxKind.UnionType],
convert(context, node) {
return new models_1.UnionType(node.types.map((type) => convertType(context, type)));
},
convertType(context, type) {
const types = type.types.map((type) => convertType(context, type));
sortLiteralUnion(types);
return new models_1.UnionType(types);
},
};
const jsDocNullableTypeConverter = {
kind: [typescript_1.default.SyntaxKind.JSDocNullableType],
convert(context, node) {
return new models_1.UnionType([
convertType(context, node.type),
new models_1.LiteralType(null),
]);
},
// Should be a UnionType
convertType: requestBugReport,
};
const jsDocNonNullableTypeConverter = {
kind: [typescript_1.default.SyntaxKind.JSDocNonNullableType],
convert(context, node) {
return convertType(context, node.type);
},
// Should be a UnionType
convertType: requestBugReport,
};
function requestBugReport(context, nodeOrType) {
if ("kind" in nodeOrType) {
const kindName = typescript_1.default.SyntaxKind[nodeOrType.kind];
context.logger.warn(`Failed to convert type node with kind: ${kindName} and text ${nodeOrType.getText()}. Please report a bug.`, nodeOrType);
return new models_1.UnknownType(nodeOrType.getText());
}
else {
const typeString = context.checker.typeToString(nodeOrType);
context.logger.warn(`Failed to convert type: ${typeString} when converting ${context.scope.getFullName()}. Please report a bug.`);
return new models_1.UnknownType(typeString);
}
}
function resolveReference(type) {
if ((0, nodes_1.isObjectType)(type) && type.objectFlags & typescript_1.default.ObjectFlags.Reference) {
return type.target;
}
return type;
}
function kindToModifier(kind) {
switch (kind) {
case typescript_1.default.SyntaxKind.ReadonlyKeyword:
case typescript_1.default.SyntaxKind.QuestionToken:
case typescript_1.default.SyntaxKind.PlusToken:
return "+";
case typescript_1.default.SyntaxKind.MinusToken:
return "-";
default:
return undefined;
}
}
function sortLiteralUnion(types) {
if (types.some((t) => t.type !== "literal" || typeof t.value !== "number")) {
return;
}
types.sort((a, b) => {
const aLit = a;
const bLit = b;
return aLit.value - bLit.value;
});
}

View File

@@ -0,0 +1,36 @@
/**
* Helper class that determines the common base path of a set of files.
*
* In the first step all files must be passed to {@link add}. Afterwards {@link trim}
* can be used to retrieve the shortest path relative to the determined base path.
*/
export declare class BasePath {
/**
* List of known base paths.
*/
private basePaths;
/**
* Add the given file path to this set of base paths.
*
* @param fileName The absolute filename that should be added to the base path.
*/
add(fileName: string): void;
/**
* Trim the given filename by the determined base paths.
*
* @param fileName The absolute filename that should be trimmed.
* @returns The trimmed version of the filename.
*/
trim(fileName: string): string;
/**
* Reset this instance, ignore all paths already passed to {@link add}.
*/
reset(): void;
/**
* Normalize the given path.
*
* @param path The path that should be normalized.
* @returns Normalized version of the given path.
*/
static normalize(path: string): string;
}

View File

@@ -0,0 +1,112 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.BasePath = void 0;
const Path = __importStar(require("path"));
/**
* Helper class that determines the common base path of a set of files.
*
* In the first step all files must be passed to {@link add}. Afterwards {@link trim}
* can be used to retrieve the shortest path relative to the determined base path.
*/
class BasePath {
constructor() {
/**
* List of known base paths.
*/
this.basePaths = [];
}
/**
* Add the given file path to this set of base paths.
*
* @param fileName The absolute filename that should be added to the base path.
*/
add(fileName) {
const fileDir = Path.dirname(BasePath.normalize(fileName));
const filePath = fileDir.split("/");
basePaths: for (let n = 0, c = this.basePaths.length; n < c; n++) {
const basePath = this.basePaths[n].split("/");
const mMax = Math.min(basePath.length, filePath.length);
for (let m = 0; m < mMax; m++) {
if (basePath[m] === filePath[m]) {
continue;
}
if (m < 1) {
// No match at all, try next known base path
continue basePaths;
}
else {
// Partial match, trim the known base path
if (m < basePath.length) {
this.basePaths[n] = basePath.slice(0, m).join("/");
}
return;
}
}
// Complete match, exit
this.basePaths[n] = basePath.splice(0, mMax).join("/");
return;
}
// Unknown base path, add it
this.basePaths.push(fileDir);
}
/**
* Trim the given filename by the determined base paths.
*
* @param fileName The absolute filename that should be trimmed.
* @returns The trimmed version of the filename.
*/
trim(fileName) {
fileName = BasePath.normalize(fileName);
for (let n = 0, c = this.basePaths.length; n < c; n++) {
const basePath = this.basePaths[n];
if (fileName.substring(0, basePath.length) === basePath) {
return fileName.substring(basePath.length + 1);
}
}
return fileName;
}
/**
* Reset this instance, ignore all paths already passed to {@link add}.
*/
reset() {
this.basePaths = [];
}
/**
* Normalize the given path.
*
* @param path The path that should be normalized.
* @returns Normalized version of the given path.
*/
static normalize(path) {
// Ensure forward slashes
path = path.replace(/\\/g, "/");
// Remove all surrounding quotes
path = path.replace(/^["']+|["']+$/g, "");
// Make Windows drive letters upper case
return path.replace(/^([^:]+):\//, (_m, m1) => m1.toUpperCase() + ":/");
}
}
exports.BasePath = BasePath;

View File

@@ -0,0 +1,6 @@
import ts from "typescript";
export declare function isNamedNode(node: unknown): node is {
readonly name: ts.Identifier | ts.PrivateIdentifier | ts.ComputedPropertyName;
};
export declare function getHeritageTypes(declarations: readonly (ts.ClassDeclaration | ts.InterfaceDeclaration)[], kind: ts.SyntaxKind.ImplementsKeyword | ts.SyntaxKind.ExtendsKeyword): ts.ExpressionWithTypeArguments[];
export declare function isObjectType(type: ts.Type): type is ts.ObjectType;

31
node_modules/typedoc/dist/lib/converter/utils/nodes.js generated vendored Normal file
View File

@@ -0,0 +1,31 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.isObjectType = exports.getHeritageTypes = exports.isNamedNode = void 0;
const typescript_1 = __importDefault(require("typescript"));
function isNamedNode(node) {
const name = node.name;
return !!name && (typescript_1.default.isMemberName(name) || typescript_1.default.isComputedPropertyName(name));
}
exports.isNamedNode = isNamedNode;
function getHeritageTypes(declarations, kind) {
const exprs = declarations.flatMap((d) => (d.heritageClauses ?? [])
.filter((hc) => hc.token === kind)
.flatMap((hc) => hc.types));
const seenTexts = new Set();
return exprs.filter((expr) => {
const text = expr.getText();
if (seenTexts.has(text)) {
return false;
}
seenTexts.add(text);
return true;
});
}
exports.getHeritageTypes = getHeritageTypes;
function isObjectType(type) {
return typeof type.objectFlags === "number";
}
exports.isObjectType = isObjectType;

View File

@@ -0,0 +1,2 @@
import { SomeType } from "../../models";
export declare function removeUndefined(type: SomeType): SomeType;

View File

@@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.removeUndefined = void 0;
const models_1 = require("../../models");
function removeUndefined(type) {
if (type instanceof models_1.UnionType) {
const types = type.types.filter((t) => {
if (t instanceof models_1.IntrinsicType) {
return t.name !== "undefined";
}
return true;
});
if (types.length === 1) {
return types[0];
}
type.types = types;
return type;
}
return type;
}
exports.removeUndefined = removeUndefined;

View File

@@ -0,0 +1,51 @@
import type { Logger } from "../../utils";
export declare function gitIsInstalled(): boolean;
export interface Repository {
getURL(fileName: string, line: number): string | undefined;
}
export declare class AssumedRepository implements Repository {
readonly path: string;
readonly gitRevision: string;
readonly sourceLinkTemplate: string;
constructor(path: string, gitRevision: string, sourceLinkTemplate: string);
getURL(fileName: string, line: number): string | undefined;
}
/**
* Stores data of a repository.
*/
export declare class GitRepository implements Repository {
/**
* The path of this repository on disk.
*/
path: string;
/**
* All files tracked by the repository.
*/
files: Set<string>;
urlTemplate: string;
gitRevision: string;
/**
* Create a new Repository instance.
*
* @param path The root path of the repository.
*/
constructor(path: string, gitRevision: string, urlTemplate: string);
/**
* Get the URL of the given file on GitHub or Bitbucket.
*
* @param fileName The file whose URL should be determined.
* @returns A URL pointing to the web preview of the given file or undefined.
*/
getURL(fileName: string, line: number): string | undefined;
/**
* Try to create a new repository instance.
*
* Checks whether the given path is the root of a valid repository and if so
* creates a new instance of {@link GitRepository}.
*
* @param path The potential repository root.
* @returns A new instance of {@link GitRepository} or undefined.
*/
static tryCreateRepository(path: string, sourceLinkTemplate: string, gitRevision: string, gitRemote: string, logger: Logger): GitRepository | undefined;
}
export declare function guessSourceUrlTemplate(remotes: string[]): string | undefined;

View File

@@ -0,0 +1,159 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.guessSourceUrlTemplate = exports.GitRepository = exports.AssumedRepository = exports.gitIsInstalled = void 0;
const child_process_1 = require("child_process");
const base_path_1 = require("../utils/base-path");
const TEN_MEGABYTES = 1024 * 10000;
function git(...args) {
return (0, child_process_1.spawnSync)("git", args, {
encoding: "utf-8",
windowsHide: true,
maxBuffer: TEN_MEGABYTES,
});
}
let haveGit;
function gitIsInstalled() {
haveGit ??= git("--version").status === 0;
return haveGit;
}
exports.gitIsInstalled = gitIsInstalled;
class AssumedRepository {
constructor(path, gitRevision, sourceLinkTemplate) {
this.path = path;
this.gitRevision = gitRevision;
this.sourceLinkTemplate = sourceLinkTemplate;
}
getURL(fileName, line) {
const replacements = {
gitRevision: this.gitRevision,
"gitRevision:short": this.gitRevision.substring(0, 8),
path: fileName.substring(this.path.length + 1),
line,
};
return this.sourceLinkTemplate.replace(/\{(gitRevision|gitRevision:short|path|line)\}/g, (_, key) => replacements[key]);
}
}
exports.AssumedRepository = AssumedRepository;
/**
* Stores data of a repository.
*/
class GitRepository {
/**
* Create a new Repository instance.
*
* @param path The root path of the repository.
*/
constructor(path, gitRevision, urlTemplate) {
/**
* All files tracked by the repository.
*/
this.files = new Set();
this.path = path;
this.gitRevision = gitRevision;
this.urlTemplate = urlTemplate;
const out = git("-C", path, "ls-files");
if (out.status === 0) {
out.stdout.split("\n").forEach((file) => {
if (file !== "") {
this.files.add(base_path_1.BasePath.normalize(path + "/" + file));
}
});
}
}
/**
* Get the URL of the given file on GitHub or Bitbucket.
*
* @param fileName The file whose URL should be determined.
* @returns A URL pointing to the web preview of the given file or undefined.
*/
getURL(fileName, line) {
if (!this.files.has(fileName)) {
return;
}
const replacements = {
gitRevision: this.gitRevision,
"gitRevision:short": this.gitRevision.substring(0, 8),
path: fileName.substring(this.path.length + 1),
line,
};
return this.urlTemplate.replace(/\{(gitRevision|gitRevision:short|path|line)\}/g, (_, key) => replacements[key]);
}
/**
* Try to create a new repository instance.
*
* Checks whether the given path is the root of a valid repository and if so
* creates a new instance of {@link GitRepository}.
*
* @param path The potential repository root.
* @returns A new instance of {@link GitRepository} or undefined.
*/
static tryCreateRepository(path, sourceLinkTemplate, gitRevision, gitRemote, logger) {
const topLevel = git("-C", path, "rev-parse", "--show-toplevel");
if (topLevel.status !== 0)
return;
gitRevision ||= git("-C", path, "rev-parse", "HEAD").stdout.trim();
if (!gitRevision)
return; // Will only happen in a repo with no commits.
let urlTemplate;
if (sourceLinkTemplate) {
urlTemplate = sourceLinkTemplate;
}
else {
const remotesOut = git("-C", path, "remote", "get-url", gitRemote);
if (remotesOut.status === 0) {
urlTemplate = guessSourceUrlTemplate(remotesOut.stdout.split("\n"));
}
else {
logger.warn(`The provided git remote "${gitRemote}" was not valid. Source links will be broken.`);
}
}
if (!urlTemplate)
return;
return new GitRepository(base_path_1.BasePath.normalize(topLevel.stdout.replace("\n", "")), gitRevision, urlTemplate);
}
}
exports.GitRepository = GitRepository;
// Should have three capturing groups:
// 1. hostname
// 2. user
// 3. project
const repoExpressions = [
/(github(?!.us)(?:\.[a-z]+)*\.[a-z]{2,})[:/]([^/]+)\/(.*)/,
/(\w+\.githubprivate.com)[:/]([^/]+)\/(.*)/, // GitHub enterprise
/(\w+\.ghe.com)[:/]([^/]+)\/(.*)/, // GitHub enterprise
/(\w+\.github.us)[:/]([^/]+)\/(.*)/, // GitHub enterprise
/(bitbucket.org)[:/]([^/]+)\/(.*)/,
/(gitlab.com)[:/]([^/]+)\/(.*)/,
];
function guessSourceUrlTemplate(remotes) {
let hostname = "";
let user = "";
let project = "";
outer: for (const repoLink of remotes) {
for (const regex of repoExpressions) {
const match = regex.exec(repoLink);
if (match) {
hostname = match[1];
user = match[2];
project = match[3];
break outer;
}
}
}
if (!hostname)
return;
if (project.endsWith(".git")) {
project = project.slice(0, -4);
}
let sourcePath = "blob";
let anchorPrefix = "L";
if (hostname.includes("gitlab")) {
sourcePath = "-/blob";
}
else if (hostname.includes("bitbucket")) {
sourcePath = "src";
anchorPrefix = "lines-";
}
return `https://${hostname}/${user}/${project}/${sourcePath}/{gitRevision}/{path}#${anchorPrefix}{line}`;
}
exports.guessSourceUrlTemplate = guessSourceUrlTemplate;

View File

@@ -0,0 +1,2 @@
import ts from "typescript";
export declare function resolveAliasedSymbol(symbol: ts.Symbol, checker: ts.TypeChecker): ts.Symbol;

View File

@@ -0,0 +1,19 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveAliasedSymbol = void 0;
const typescript_1 = __importDefault(require("typescript"));
function resolveAliasedSymbol(symbol, checker) {
const seen = new Set();
while (typescript_1.default.SymbolFlags.Alias & symbol.flags) {
symbol = checker.getAliasedSymbol(symbol);
// #2438, with declaration files, we might have an aliased symbol which eventually points to itself.
if (seen.has(symbol))
return symbol;
seen.add(symbol);
}
return symbol;
}
exports.resolveAliasedSymbol = resolveAliasedSymbol;

View File

@@ -0,0 +1,35 @@
import type { CommentDisplayPart, DeclarationReflection } from ".";
import type { Serializer, JSONOutput, Deserializer } from "../serialization";
/**
* A category of reflections.
*
* Reflection categories are created by the ´CategoryPlugin´ in the resolving phase
* of the dispatcher. The main purpose of categories is to be able to more easily
* render human readable children lists in templates.
*/
export declare class ReflectionCategory {
/**
* The title, a string representation of this category.
*/
title: string;
/**
* The user specified description, if any, set with `@categoryDescription`
*/
description?: CommentDisplayPart[];
/**
* All reflections of this category.
*/
children: DeclarationReflection[];
/**
* Create a new ReflectionCategory instance.
*
* @param title The title of this category.
*/
constructor(title: string);
/**
* Do all children of this category have a separate document?
*/
allChildrenHaveOwnDocument(): boolean;
toObject(serializer: Serializer): JSONOutput.ReflectionCategory;
fromObject(de: Deserializer, obj: JSONOutput.ReflectionCategory): void;
}

View File

@@ -0,0 +1,58 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ReflectionCategory = void 0;
const comments_1 = require("./comments");
/**
* A category of reflections.
*
* Reflection categories are created by the ´CategoryPlugin´ in the resolving phase
* of the dispatcher. The main purpose of categories is to be able to more easily
* render human readable children lists in templates.
*/
class ReflectionCategory {
/**
* Create a new ReflectionCategory instance.
*
* @param title The title of this category.
*/
constructor(title) {
/**
* All reflections of this category.
*/
this.children = [];
this.title = title;
}
/**
* Do all children of this category have a separate document?
*/
allChildrenHaveOwnDocument() {
return this.children.every((child) => child.hasOwnDocument);
}
toObject(serializer) {
return {
title: this.title,
description: this.description
? comments_1.Comment.serializeDisplayParts(serializer, this.description)
: undefined,
children: this.children.length > 0
? this.children.map((child) => child.id)
: undefined,
};
}
fromObject(de, obj) {
if (obj.description) {
this.description = comments_1.Comment.deserializeDisplayParts(de, obj.description);
}
if (obj.children) {
de.defer((project) => {
for (const childId of obj.children || []) {
const child = project.getReflectionById(de.oldIdToNewId[childId] ?? -1);
if (child?.isDeclaration()) {
this.children.push(child);
}
}
});
}
}
}
exports.ReflectionCategory = ReflectionCategory;

View File

@@ -0,0 +1,42 @@
import { ReflectionCategory } from "./ReflectionCategory";
import type { CommentDisplayPart, DeclarationReflection, Reflection } from ".";
import type { Serializer, JSONOutput, Deserializer } from "../serialization";
/**
* A group of reflections. All reflections in a group are of the same kind.
*
* Reflection groups are created by the ´GroupHandler´ in the resolving phase
* of the dispatcher. The main purpose of groups is to be able to more easily
* render human readable children lists in templates.
*/
export declare class ReflectionGroup {
readonly owningReflection: Reflection;
/**
* The title, a string representation of the typescript kind, of this group.
*/
title: string;
/**
* User specified description via `@groupDescription`, if specified.
*/
description?: CommentDisplayPart[];
/**
* All reflections of this group.
*/
children: DeclarationReflection[];
/**
* Categories contained within this group.
*/
categories?: ReflectionCategory[];
/**
* Create a new ReflectionGroup instance.
*
* @param title The title of this group.
* @param owningReflection The reflection containing this group, useful for changing rendering based on a comment on a reflection.
*/
constructor(title: string, owningReflection: Reflection);
/**
* Do all children of this group have a separate document?
*/
allChildrenHaveOwnDocument(): boolean;
toObject(serializer: Serializer): JSONOutput.ReflectionGroup;
fromObject(de: Deserializer, obj: JSONOutput.ReflectionGroup): void;
}

View File

@@ -0,0 +1,69 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ReflectionGroup = void 0;
const ReflectionCategory_1 = require("./ReflectionCategory");
const comments_1 = require("./comments");
/**
* A group of reflections. All reflections in a group are of the same kind.
*
* Reflection groups are created by the ´GroupHandler´ in the resolving phase
* of the dispatcher. The main purpose of groups is to be able to more easily
* render human readable children lists in templates.
*/
class ReflectionGroup {
/**
* Create a new ReflectionGroup instance.
*
* @param title The title of this group.
* @param owningReflection The reflection containing this group, useful for changing rendering based on a comment on a reflection.
*/
constructor(title, owningReflection) {
this.owningReflection = owningReflection;
/**
* All reflections of this group.
*/
this.children = [];
this.title = title;
}
/**
* Do all children of this group have a separate document?
*/
allChildrenHaveOwnDocument() {
return this.children.every((child) => child.hasOwnDocument);
}
toObject(serializer) {
return {
title: this.title,
description: this.description
? comments_1.Comment.serializeDisplayParts(serializer, this.description)
: undefined,
children: this.children.length > 0
? this.children.map((child) => child.id)
: undefined,
categories: serializer.toObjectsOptional(this.categories),
};
}
fromObject(de, obj) {
if (obj.description) {
this.description = comments_1.Comment.deserializeDisplayParts(de, obj.description);
}
if (obj.categories) {
this.categories = obj.categories.map((catObj) => {
const cat = new ReflectionCategory_1.ReflectionCategory(catObj.title);
de.fromObject(cat, catObj);
return cat;
});
}
if (obj.children) {
de.defer((project) => {
for (const childId of obj.children || []) {
const child = project.getReflectionById(de.oldIdToNewId[childId] ?? -1);
if (child?.isDeclaration()) {
this.children.push(child);
}
}
});
}
}
}
exports.ReflectionGroup = ReflectionGroup;

View File

@@ -0,0 +1,167 @@
import type { Reflection } from "../reflections";
import { ReflectionSymbolId } from "../reflections/ReflectionSymbolId";
import type { Serializer, Deserializer, JSONOutput } from "../../serialization";
/**
* Represents a parsed piece of a comment.
* @category Comments
*/
export type CommentDisplayPart = {
kind: "text";
text: string;
} | {
kind: "code";
text: string;
} | InlineTagDisplayPart;
/**
* The `@link`, `@linkcode`, and `@linkplain` tags may have a `target`
* property set indicating which reflection/url they link to. They may also
* have a `tsLinkText` property which includes the part of the `text` which
* TypeScript thinks should be displayed as the link text.
* @category Comments
*/
export interface InlineTagDisplayPart {
kind: "inline-tag";
tag: `@${string}`;
text: string;
target?: Reflection | string | ReflectionSymbolId;
tsLinkText?: string;
}
/**
* A model that represents a single TypeDoc comment tag.
*
* Tags are stored in the {@link Comment.blockTags} property.
* @category Comments
*/
export declare class CommentTag {
/**
* The name of this tag, e.g. `@returns`, `@example`
*/
tag: `@${string}`;
/**
* Some tags, (`@typedef`, `@param`, `@property`, etc.) may have a user defined identifier associated with them.
* If this tag is one of those, it will be parsed out and included here.
*/
name?: string;
/**
* The actual body text of this tag.
*/
content: CommentDisplayPart[];
/**
* Create a new CommentTag instance.
*/
constructor(tag: `@${string}`, text: CommentDisplayPart[]);
clone(): CommentTag;
toObject(serializer: Serializer): JSONOutput.CommentTag;
fromObject(de: Deserializer, obj: JSONOutput.CommentTag): void;
}
/**
* A model that represents a comment.
*
* Instances of this model are created by the CommentPlugin. You can retrieve comments
* through the {@link DeclarationReflection.comment} property.
* @category Comments
*/
export declare class Comment {
/**
* Debugging utility for combining parts into a simple string. Not suitable for
* rendering, but can be useful in tests.
*/
static combineDisplayParts(parts: readonly CommentDisplayPart[] | undefined): string;
/**
* Helper function to convert an array of comment display parts into markdown suitable for
* passing into Marked. `urlTo` will be used to resolve urls to any reflections linked to with
* `@link` tags.
*/
static displayPartsToMarkdown(parts: readonly CommentDisplayPart[], urlTo: (ref: Reflection) => string): string;
/**
* Helper utility to clone {@link Comment.summary} or {@link CommentTag.content}
*/
static cloneDisplayParts(parts: readonly CommentDisplayPart[]): ({
kind: "text";
text: string;
} | {
kind: "code";
text: string;
} | {
kind: "inline-tag";
tag: `@${string}`;
text: string;
target?: string | Reflection | ReflectionSymbolId | undefined;
tsLinkText?: string | undefined;
})[];
static serializeDisplayParts(serializer: Serializer, parts: CommentDisplayPart[]): JSONOutput.CommentDisplayPart[];
/** @hidden no point in showing this signature in api docs */
static serializeDisplayParts(serializer: Serializer, parts: CommentDisplayPart[] | undefined): JSONOutput.CommentDisplayPart[] | undefined;
static deserializeDisplayParts(de: Deserializer, parts: JSONOutput.CommentDisplayPart[]): CommentDisplayPart[];
/**
* Splits the provided parts into a header (first line, as a string)
* and body (remaining lines). If the header line contains inline tags
* they will be serialized to a string.
*/
static splitPartsToHeaderAndBody(parts: readonly CommentDisplayPart[]): {
header: string;
body: CommentDisplayPart[];
};
/**
* The content of the comment which is not associated with a block tag.
*/
summary: CommentDisplayPart[];
/**
* All associated block level tags.
*/
blockTags: CommentTag[];
/**
* All modifier tags present on the comment, e.g. `@alpha`, `@beta`.
*/
modifierTags: Set<`@${string}`>;
/**
* Label associated with this reflection, if any (https://tsdoc.org/pages/tags/label/)
*/
label?: string;
/**
* Creates a new Comment instance.
*/
constructor(summary?: CommentDisplayPart[], blockTags?: CommentTag[], modifierTags?: Set<`@${string}`>);
/**
* Create a deep clone of this comment.
*/
clone(): Comment;
/**
* Returns true if this comment is completely empty.
* @internal
*/
isEmpty(): boolean;
/**
* Has this comment a visible component?
*
* @returns TRUE when this comment has a visible component.
*/
hasVisibleComponent(): boolean;
/**
* Test whether this comment contains a tag with the given name.
*
* @param tagName The name of the tag to look for.
* @returns TRUE when this comment contains a tag with the given name, otherwise FALSE.
*/
hasModifier(tagName: `@${string}`): boolean;
removeModifier(tagName: `@${string}`): void;
/**
* Return the first tag with the given name.
*
* @param tagName The name of the tag to look for.
* @returns The found tag or undefined.
*/
getTag(tagName: `@${string}`): CommentTag | undefined;
/**
* Get all tags with the given tag name.
*/
getTags(tagName: `@${string}`): CommentTag[];
getIdentifiedTag(identifier: string, tagName: `@${string}`): CommentTag | undefined;
/**
* Removes all block tags with the given tag name from the comment.
* @param tagName
*/
removeTags(tagName: `@${string}`): void;
toObject(serializer: Serializer): JSONOutput.Comment;
fromObject(de: Deserializer, obj: JSONOutput.Comment): void;
}

View File

@@ -0,0 +1,370 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Comment = exports.CommentTag = void 0;
const utils_1 = require("../../utils");
const kind_1 = require("../reflections/kind");
const ReflectionSymbolId_1 = require("../reflections/ReflectionSymbolId");
/**
* A model that represents a single TypeDoc comment tag.
*
* Tags are stored in the {@link Comment.blockTags} property.
* @category Comments
*/
class CommentTag {
/**
* Create a new CommentTag instance.
*/
constructor(tag, text) {
this.tag = tag;
this.content = text;
}
clone() {
const tag = new CommentTag(this.tag, Comment.cloneDisplayParts(this.content));
if (this.name) {
tag.name = this.name;
}
return tag;
}
toObject(serializer) {
return {
tag: this.tag,
name: this.name,
content: Comment.serializeDisplayParts(serializer, this.content),
};
}
fromObject(de, obj) {
// tag already set by Comment.fromObject
this.name = obj.name;
this.content = Comment.deserializeDisplayParts(de, obj.content);
}
}
exports.CommentTag = CommentTag;
/**
* A model that represents a comment.
*
* Instances of this model are created by the CommentPlugin. You can retrieve comments
* through the {@link DeclarationReflection.comment} property.
* @category Comments
*/
class Comment {
/**
* Debugging utility for combining parts into a simple string. Not suitable for
* rendering, but can be useful in tests.
*/
static combineDisplayParts(parts) {
let result = "";
for (const item of parts || []) {
switch (item.kind) {
case "text":
case "code":
result += item.text;
break;
case "inline-tag":
result += `{${item.tag} ${item.text}}`;
break;
default:
(0, utils_1.assertNever)(item);
}
}
return result;
}
/**
* Helper function to convert an array of comment display parts into markdown suitable for
* passing into Marked. `urlTo` will be used to resolve urls to any reflections linked to with
* `@link` tags.
*/
static displayPartsToMarkdown(parts, urlTo) {
const result = [];
for (const part of parts) {
switch (part.kind) {
case "text":
case "code":
result.push(part.text);
break;
case "inline-tag":
switch (part.tag) {
case "@label":
case "@inheritdoc": // Shouldn't happen
break; // Not rendered.
case "@link":
case "@linkcode":
case "@linkplain": {
if (part.target) {
let url;
let kindClass;
if (typeof part.target === "string") {
url = part.target;
}
else if (part.target && "id" in part.target) {
// No point in trying to resolve a ReflectionSymbolId at this point, we've already
// tried and failed during the resolution step.
url = urlTo(part.target);
kindClass = kind_1.ReflectionKind.classString(part.target.kind);
}
const text = part.tag === "@linkcode"
? `<code>${part.text}</code>`
: part.text;
result.push(url
? `<a href="${url}"${kindClass
? ` class="${kindClass}"`
: ""}>${text}</a>`
: part.text);
}
else {
result.push(part.text);
}
break;
}
default:
// Hmm... probably want to be able to render these somehow, so custom inline tags can be given
// special rendering rules. Future capability. For now, just render their text.
result.push(`{${part.tag} ${part.text}}`);
break;
}
break;
default:
(0, utils_1.assertNever)(part);
}
}
return result.join("");
}
/**
* Helper utility to clone {@link Comment.summary} or {@link CommentTag.content}
*/
static cloneDisplayParts(parts) {
return parts.map((p) => ({ ...p }));
}
static serializeDisplayParts(serializer, parts) {
return parts?.map((part) => {
switch (part.kind) {
case "text":
case "code":
return { ...part };
case "inline-tag": {
let target;
if (typeof part.target === "string") {
target = part.target;
}
else if (part.target) {
if ("id" in part.target) {
target = part.target.id;
}
else {
target = part.target.toObject(serializer);
}
}
return {
...part,
target,
};
}
}
});
}
//Since display parts are plain objects, this lives here
static deserializeDisplayParts(de, parts) {
const links = [];
const result = parts.map((part) => {
switch (part.kind) {
case "text":
case "code":
return { ...part };
case "inline-tag": {
if (typeof part.target === "number") {
const part2 = {
kind: part.kind,
tag: part.tag,
text: part.text,
target: undefined,
tsLinkText: part.tsLinkText,
};
links.push([part.target, part2]);
return part2;
}
else if (typeof part.target === "string" ||
part.target === undefined) {
return {
kind: "inline-tag",
tag: part.tag,
text: part.text,
target: part.target,
tsLinkText: part.tsLinkText,
};
}
else if (typeof part.target === "object") {
return {
kind: "inline-tag",
tag: part.tag,
text: part.text,
target: new ReflectionSymbolId_1.ReflectionSymbolId(part.target),
tsLinkText: part.tsLinkText,
};
}
else {
(0, utils_1.assertNever)(part.target);
}
}
}
});
if (links.length) {
de.defer((project) => {
for (const [oldId, part] of links) {
part.target = project.getReflectionById(de.oldIdToNewId[oldId] ?? -1);
if (!part.target) {
de.logger.warn(`Serialized project contained a link to ${oldId} (${part.text}), which was not a part of the project.`);
}
}
});
}
return result;
}
/**
* Splits the provided parts into a header (first line, as a string)
* and body (remaining lines). If the header line contains inline tags
* they will be serialized to a string.
*/
static splitPartsToHeaderAndBody(parts) {
let index = parts.findIndex((part) => {
switch (part.kind) {
case "text":
case "code":
return part.text.includes("\n");
case "inline-tag":
return false;
}
});
if (index === -1) {
return {
header: Comment.combineDisplayParts(parts),
body: [],
};
}
// Do not split a code block, stop the header at the end of the previous block
if (parts[index].kind === "code") {
--index;
}
if (index === -1) {
return { header: "", body: Comment.cloneDisplayParts(parts) };
}
let header = Comment.combineDisplayParts(parts.slice(0, index));
const split = parts[index].text.indexOf("\n");
let body;
if (split === -1) {
header += parts[index].text;
body = Comment.cloneDisplayParts(parts.slice(index + 1));
}
else {
header += parts[index].text.substring(0, split);
body = Comment.cloneDisplayParts(parts.slice(index));
body[0].text = body[0].text.substring(split + 1);
}
if (!body[0].text) {
body.shift();
}
return { header: header.trim(), body };
}
/**
* Creates a new Comment instance.
*/
constructor(summary = [], blockTags = [], modifierTags = new Set()) {
/**
* All associated block level tags.
*/
this.blockTags = [];
/**
* All modifier tags present on the comment, e.g. `@alpha`, `@beta`.
*/
this.modifierTags = new Set();
this.summary = summary;
this.blockTags = blockTags;
this.modifierTags = modifierTags;
extractLabelTag(this);
}
/**
* Create a deep clone of this comment.
*/
clone() {
return new Comment(Comment.cloneDisplayParts(this.summary), this.blockTags.map((tag) => tag.clone()), new Set(this.modifierTags));
}
/**
* Returns true if this comment is completely empty.
* @internal
*/
isEmpty() {
return !this.hasVisibleComponent() && this.modifierTags.size === 0;
}
/**
* Has this comment a visible component?
*
* @returns TRUE when this comment has a visible component.
*/
hasVisibleComponent() {
return (this.summary.some((x) => x.kind !== "text" || x.text !== "") ||
this.blockTags.length > 0);
}
/**
* Test whether this comment contains a tag with the given name.
*
* @param tagName The name of the tag to look for.
* @returns TRUE when this comment contains a tag with the given name, otherwise FALSE.
*/
hasModifier(tagName) {
return this.modifierTags.has(tagName);
}
removeModifier(tagName) {
this.modifierTags.delete(tagName);
}
/**
* Return the first tag with the given name.
*
* @param tagName The name of the tag to look for.
* @returns The found tag or undefined.
*/
getTag(tagName) {
return this.blockTags.find((tag) => tag.tag === tagName);
}
/**
* Get all tags with the given tag name.
*/
getTags(tagName) {
return this.blockTags.filter((tag) => tag.tag === tagName);
}
getIdentifiedTag(identifier, tagName) {
return this.blockTags.find((tag) => tag.tag === tagName && tag.name === identifier);
}
/**
* Removes all block tags with the given tag name from the comment.
* @param tagName
*/
removeTags(tagName) {
(0, utils_1.removeIf)(this.blockTags, (tag) => tag.tag === tagName);
}
toObject(serializer) {
return {
summary: Comment.serializeDisplayParts(serializer, this.summary),
blockTags: serializer.toObjectsOptional(this.blockTags),
modifierTags: this.modifierTags.size > 0
? Array.from(this.modifierTags)
: undefined,
label: this.label,
};
}
fromObject(de, obj) {
this.summary = Comment.deserializeDisplayParts(de, obj.summary);
this.blockTags =
obj.blockTags?.map((tagObj) => {
const tag = new CommentTag(tagObj.tag, []);
de.fromObject(tag, tagObj);
return tag;
}) || [];
this.modifierTags = new Set(obj.modifierTags);
this.label = obj.label;
}
}
exports.Comment = Comment;
function extractLabelTag(comment) {
const index = comment.summary.findIndex((part) => part.kind === "inline-tag" && part.tag === "@label");
if (index !== -1) {
comment.label = comment.summary.splice(index, 1)[0].text;
}
}

View File

@@ -0,0 +1,2 @@
export { Comment, CommentTag } from "./comment";
export type { CommentDisplayPart, InlineTagDisplayPart } from "./comment";

View File

@@ -0,0 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CommentTag = exports.Comment = void 0;
var comment_1 = require("./comment");
Object.defineProperty(exports, "Comment", { enumerable: true, get: function () { return comment_1.Comment; } });
Object.defineProperty(exports, "CommentTag", { enumerable: true, get: function () { return comment_1.CommentTag; } });

6
node_modules/typedoc/dist/lib/models/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,6 @@
export * from "./reflections/index";
export * from "./types";
export * from "./comments/index";
export * from "./sources/index";
export * from "./ReflectionGroup";
export * from "./ReflectionCategory";

22
node_modules/typedoc/dist/lib/models/index.js generated vendored Normal file
View File

@@ -0,0 +1,22 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./reflections/index"), exports);
__exportStar(require("./types"), exports);
__exportStar(require("./comments/index"), exports);
__exportStar(require("./sources/index"), exports);
__exportStar(require("./ReflectionGroup"), exports);
__exportStar(require("./ReflectionCategory"), exports);

View File

@@ -0,0 +1,38 @@
import ts from "typescript";
import type { JSONOutput, Serializer } from "../../serialization/index";
/**
* See {@link ReflectionSymbolId}
*/
export type ReflectionSymbolIdString = string & {
readonly __reflectionSymbolId: unique symbol;
};
/**
* This exists so that TypeDoc can store a unique identifier for a `ts.Symbol` without
* keeping a reference to the `ts.Symbol` itself. This identifier should be stable across
* runs so long as the symbol is exported from the same file.
*/
export declare class ReflectionSymbolId {
readonly fileName: string;
readonly qualifiedName: string;
/**
* Note: This is **not** serialized. It exists for sorting by declaration order, but
* should not be needed when deserializing from JSON.
* Will be set to `Infinity` if the ID was deserialized from JSON.
*/
pos: number;
/**
* Note: This is **not** serialized. It exists to support detection of the differences between
* symbols which share declarations, but are instantiated with different type parameters.
* This will be `NaN` if the symbol reference is not transient.
* Note: This can only be non-NaN if {@link pos} is finite.
*/
transientId: number;
constructor(symbol: ts.Symbol, declaration?: ts.Declaration);
constructor(json: JSONOutput.ReflectionSymbolId);
getStableKey(): ReflectionSymbolIdString;
toObject(serializer: Serializer): {
sourceFileName: string;
qualifiedName: string;
};
}
export declare function addInferredDeclarationMapPaths(opts: ts.CompilerOptions, files: readonly string[]): void;

View File

@@ -0,0 +1,112 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.addInferredDeclarationMapPaths = exports.ReflectionSymbolId = void 0;
const fs_1 = require("fs");
const path_1 = require("path");
const typescript_1 = __importDefault(require("typescript"));
const fs_2 = require("../../utils/fs");
const paths_1 = require("../../utils/paths");
const tsutils_1 = require("../../utils/tsutils");
const validation_1 = require("../../utils/validation");
let transientCount = 0;
const transientIds = new WeakMap();
/**
* This exists so that TypeDoc can store a unique identifier for a `ts.Symbol` without
* keeping a reference to the `ts.Symbol` itself. This identifier should be stable across
* runs so long as the symbol is exported from the same file.
*/
class ReflectionSymbolId {
constructor(symbol, declaration) {
if ("name" in symbol) {
declaration ??= symbol?.declarations?.[0];
this.fileName = (0, paths_1.normalizePath)(declaration?.getSourceFile().fileName ?? "");
if (symbol.declarations?.some(typescript_1.default.isSourceFile)) {
this.qualifiedName = "";
}
else {
this.qualifiedName = (0, tsutils_1.getQualifiedName)(symbol, symbol.name);
}
this.pos = declaration?.pos ?? Infinity;
if (symbol.flags & typescript_1.default.SymbolFlags.Transient) {
this.transientId = transientIds.get(symbol) ?? ++transientCount;
transientIds.set(symbol, this.transientId);
}
else {
this.transientId = NaN;
}
}
else {
this.fileName = symbol.sourceFileName;
this.qualifiedName = symbol.qualifiedName;
this.pos = Infinity;
this.transientId = NaN;
}
}
getStableKey() {
if (Number.isFinite(this.pos)) {
return `${this.fileName}\0${this.qualifiedName}\0${this.pos}\0${this.transientId}`;
}
else {
return `${this.fileName}\0${this.qualifiedName}`;
}
}
toObject(serializer) {
const sourceFileName = (0, path_1.isAbsolute)(this.fileName)
? (0, paths_1.normalizePath)((0, path_1.relative)(serializer.projectRoot, resolveDeclarationMaps(this.fileName)))
: this.fileName;
return {
sourceFileName,
qualifiedName: this.qualifiedName,
};
}
}
exports.ReflectionSymbolId = ReflectionSymbolId;
const declarationMapCache = new Map();
function resolveDeclarationMaps(file) {
if (!/\.d\.[cm]?ts$/.test(file))
return file;
if (declarationMapCache.has(file))
return declarationMapCache.get(file);
const mapFile = file + ".map";
if (!(0, fs_1.existsSync)(mapFile))
return file;
let sourceMap;
try {
sourceMap = JSON.parse((0, fs_2.readFile)(mapFile));
}
catch {
return file;
}
if ((0, validation_1.validate)({
file: String,
sourceRoot: (0, validation_1.optional)(String),
sources: [Array, String],
}, sourceMap)) {
// There's a pretty large assumption in here that we only have
// 1 source file per js file. This is a pretty standard typescript approach,
// but people might do interesting things with transpilation that could break this.
let source = sourceMap.sources[0];
// If we have a sourceRoot, trim any leading slash from the source, and join them
// Similar to how it's done at https://github.com/mozilla/source-map/blob/58819f09018d56ef84dc41ba9c93f554e0645169/lib/util.js#L412
if (sourceMap.sourceRoot !== undefined) {
source = source.replace(/^\//, "");
source = (0, path_1.join)(sourceMap.sourceRoot, source);
}
const result = (0, path_1.resolve)(mapFile, "..", source);
declarationMapCache.set(file, result);
return result;
}
return file;
}
function addInferredDeclarationMapPaths(opts, files) {
const rootDir = opts.rootDir || (0, fs_2.getCommonDirectory)(files);
const declDir = opts.declarationDir || opts.outDir || rootDir;
for (const file of files) {
const mapFile = (0, paths_1.normalizePath)((0, path_1.resolve)(declDir, (0, path_1.relative)(rootDir, file)).replace(/\.([cm]?[tj]s)x?$/, ".d.$1"));
declarationMapCache.set(mapFile, file);
}
}
exports.addInferredDeclarationMapPaths = addInferredDeclarationMapPaths;

View File

@@ -0,0 +1,235 @@
import { Comment } from "../comments/comment";
import type { ProjectReflection } from "./project";
import type { NeverIfInternal } from "../../utils";
import { ReflectionKind } from "./kind";
import type { Serializer, Deserializer, JSONOutput } from "../../serialization";
import type { ReflectionVariant } from "./variant";
import type { DeclarationReflection } from "./declaration";
/**
* Reset the reflection id.
*
* Used by the test cases to ensure the reflection ids won't change between runs.
*/
export declare function resetReflectionID(): void;
export declare enum ReflectionFlag {
None = 0,
Private = 1,
Protected = 2,
Public = 4,
Static = 8,
ExportAssignment = 16,
External = 32,
Optional = 64,
DefaultValue = 128,
Rest = 256,
Abstract = 512,
Const = 1024,
Let = 2048,
Readonly = 4096
}
/**
* This must extend Array in order to work with Handlebar's each helper.
*/
export declare class ReflectionFlags extends Array<string> {
private flags;
hasFlag(flag: ReflectionFlag): boolean;
/**
* Is this a private member?
*/
get isPrivate(): boolean;
/**
* Is this a protected member?
*/
get isProtected(): boolean;
/**
* Is this a public member?
*/
get isPublic(): boolean;
/**
* Is this a static member?
*/
get isStatic(): boolean;
/**
* Is this a declaration from an external document?
*/
get isExternal(): boolean;
/**
* Whether this reflection is an optional component or not.
*
* Applies to function parameters and object members.
*/
get isOptional(): boolean;
/**
* Whether it's a rest parameter, like `foo(...params);`.
*/
get isRest(): boolean;
get hasExportAssignment(): boolean;
get isAbstract(): boolean;
get isConst(): boolean;
get isReadonly(): boolean;
setFlag(flag: ReflectionFlag, set: boolean): void;
private setSingleFlag;
private static serializedFlags;
toObject(): JSONOutput.ReflectionFlags;
fromObject(obj: JSONOutput.ReflectionFlags): void;
}
export declare enum TraverseProperty {
Children = 0,
Parameters = 1,
TypeLiteral = 2,
TypeParameter = 3,
Signatures = 4,
IndexSignature = 5,
GetSignature = 6,
SetSignature = 7
}
export interface TraverseCallback {
/**
* May return false to bail out of any further iteration. To preserve backwards compatibility, if
* a function returns undefined, iteration must continue.
*/
(reflection: Reflection, property: TraverseProperty): boolean | NeverIfInternal<void>;
}
export type ReflectionVisitor = {
[K in keyof ReflectionVariant]?: (refl: ReflectionVariant[K]) => void;
};
/**
* Base class for all reflection classes.
*
* While generating a documentation, TypeDoc generates an instance of {@link ProjectReflection}
* as the root for all reflections within the project. All other reflections are represented
* by the {@link DeclarationReflection} class.
*
* This base class exposes the basic properties one may use to traverse the reflection tree.
* You can use the {@link ContainerReflection.children} and {@link parent} properties to walk the tree. The {@link ContainerReflection.groups} property
* contains a list of all children grouped and sorted for rendering.
* @category Reflections
*/
export declare abstract class Reflection {
/**
* Discriminator representing the type of reflection represented by this object.
*/
abstract readonly variant: keyof ReflectionVariant;
/**
* Unique id of this reflection.
*/
id: number;
/**
* The symbol name of this reflection.
*/
name: string;
/**
* The kind of this reflection.
*/
kind: ReflectionKind;
flags: ReflectionFlags;
/**
* The reflection this reflection is a child of.
*/
parent?: Reflection;
project: ProjectReflection;
/**
* The parsed documentation comment attached to this reflection.
*/
comment?: Comment;
/**
* The url of this reflection in the generated documentation.
* TODO: Reflections shouldn't know urls exist. Move this to a serializer.
*/
url?: string;
/**
* The name of the anchor of this child.
* TODO: Reflections shouldn't know anchors exist. Move this to a serializer.
*/
anchor?: string;
/**
* Is the url pointing to an individual document?
*
* When FALSE, the url points to an anchor tag on a page of a different reflection.
* TODO: Reflections shouldn't know how they are rendered. Move this to the correct serializer.
*/
hasOwnDocument?: boolean;
/**
* Url safe alias for this reflection.
*/
private _alias?;
private _aliases?;
constructor(name: string, kind: ReflectionKind, parent?: Reflection);
/**
* Test whether this reflection is of the given kind.
*/
kindOf(kind: ReflectionKind | ReflectionKind[]): boolean;
/**
* Return the full name of this reflection. Intended for use in debugging. For log messages
* intended to be displayed to the user for them to fix, prefer {@link getFriendlyFullName} instead.
*
* The full name contains the name of this reflection and the names of all parent reflections.
*
* @param separator Separator used to join the names of the reflections.
* @returns The full name of this reflection.
*/
getFullName(separator?: string): string;
/**
* Return the full name of this reflection, with signature names dropped if possible without
* introducing ambiguity in the name.
*/
getFriendlyFullName(): string;
/**
* Set a flag on this reflection.
*/
setFlag(flag: ReflectionFlag, value?: boolean): void;
/**
* Return an url safe alias for this reflection.
*/
getAlias(): string;
/**
* Has this reflection a visible comment?
*
* @returns TRUE when this reflection has a visible comment.
*/
hasComment(): boolean;
hasGetterOrSetter(): boolean;
/**
* Return a child by its name.
*
* @param arg The name hierarchy of the child to look for.
* @returns The found child or undefined.
*/
getChildByName(arg: string | string[]): Reflection | undefined;
/**
* Return whether this reflection is the root / project reflection.
*/
isProject(): this is ProjectReflection;
isDeclaration(): this is DeclarationReflection;
/**
* Check if this reflection or any of its parents have been marked with the `@deprecated` tag.
*/
isDeprecated(): boolean;
/**
* Traverse most potential child reflections of this reflection.
*
* Note: This may not necessarily traverse child reflections contained within the `type` property
* of the reflection, and should not be relied on for this. Support for checking object types will likely be removed in v0.26.
*
* The given callback will be invoked for all children, signatures and type parameters
* attached to this reflection.
*
* @param callback The callback function that should be applied for each child reflection.
*/
abstract traverse(callback: TraverseCallback): void;
visit(visitor: ReflectionVisitor): void;
/**
* Return a string representation of this reflection.
*/
toString(): string;
/**
* Return a string representation of this reflection and all of its children.
*
* Note: This is intended as a debug tool only, output may change between patch versions.
*
* @param indent Used internally to indent child reflections.
*/
toStringHierarchy(indent?: string): string;
toObject(serializer: Serializer): JSONOutput.Reflection;
fromObject(de: Deserializer, obj: JSONOutput.Reflection): void;
}

View File

@@ -0,0 +1,479 @@
"use strict";
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
var _, done = false;
for (var i = decorators.length - 1; i >= 0; i--) {
var context = {};
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
if (kind === "accessor") {
if (result === void 0) continue;
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
if (_ = accept(result.get)) descriptor.get = _;
if (_ = accept(result.set)) descriptor.set = _;
if (_ = accept(result.init)) initializers.unshift(_);
}
else if (_ = accept(result)) {
if (kind === "field") initializers.unshift(_);
else descriptor[key] = _;
}
}
if (target) Object.defineProperty(target, contextIn.name, descriptor);
done = true;
};
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
var useValue = arguments.length > 2;
for (var i = 0; i < initializers.length; i++) {
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
}
return useValue ? value : void 0;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Reflection = exports.TraverseProperty = exports.ReflectionFlags = exports.ReflectionFlag = exports.resetReflectionID = void 0;
const comment_1 = require("../comments/comment");
const utils_1 = require("./utils");
const kind_1 = require("./kind");
const general_1 = require("../../utils/general");
/**
* Current reflection id.
*/
let REFLECTION_ID = 0;
/**
* Reset the reflection id.
*
* Used by the test cases to ensure the reflection ids won't change between runs.
*/
function resetReflectionID() {
REFLECTION_ID = 0;
}
exports.resetReflectionID = resetReflectionID;
var ReflectionFlag;
(function (ReflectionFlag) {
ReflectionFlag[ReflectionFlag["None"] = 0] = "None";
ReflectionFlag[ReflectionFlag["Private"] = 1] = "Private";
ReflectionFlag[ReflectionFlag["Protected"] = 2] = "Protected";
ReflectionFlag[ReflectionFlag["Public"] = 4] = "Public";
ReflectionFlag[ReflectionFlag["Static"] = 8] = "Static";
ReflectionFlag[ReflectionFlag["ExportAssignment"] = 16] = "ExportAssignment";
ReflectionFlag[ReflectionFlag["External"] = 32] = "External";
ReflectionFlag[ReflectionFlag["Optional"] = 64] = "Optional";
ReflectionFlag[ReflectionFlag["DefaultValue"] = 128] = "DefaultValue";
ReflectionFlag[ReflectionFlag["Rest"] = 256] = "Rest";
ReflectionFlag[ReflectionFlag["Abstract"] = 512] = "Abstract";
ReflectionFlag[ReflectionFlag["Const"] = 1024] = "Const";
ReflectionFlag[ReflectionFlag["Let"] = 2048] = "Let";
ReflectionFlag[ReflectionFlag["Readonly"] = 4096] = "Readonly";
})(ReflectionFlag || (exports.ReflectionFlag = ReflectionFlag = {}));
const relevantFlags = [
ReflectionFlag.Private,
ReflectionFlag.Protected,
ReflectionFlag.Static,
ReflectionFlag.ExportAssignment,
ReflectionFlag.Optional,
ReflectionFlag.DefaultValue,
ReflectionFlag.Rest,
ReflectionFlag.Abstract,
ReflectionFlag.Const,
ReflectionFlag.Readonly,
];
/**
* This must extend Array in order to work with Handlebar's each helper.
*/
class ReflectionFlags extends Array {
constructor() {
super(...arguments);
this.flags = ReflectionFlag.None;
}
hasFlag(flag) {
return (flag & this.flags) !== 0;
}
/**
* Is this a private member?
*/
get isPrivate() {
return this.hasFlag(ReflectionFlag.Private);
}
/**
* Is this a protected member?
*/
get isProtected() {
return this.hasFlag(ReflectionFlag.Protected);
}
/**
* Is this a public member?
*/
get isPublic() {
return this.hasFlag(ReflectionFlag.Public);
}
/**
* Is this a static member?
*/
get isStatic() {
return this.hasFlag(ReflectionFlag.Static);
}
/**
* Is this a declaration from an external document?
*/
get isExternal() {
return this.hasFlag(ReflectionFlag.External);
}
/**
* Whether this reflection is an optional component or not.
*
* Applies to function parameters and object members.
*/
get isOptional() {
return this.hasFlag(ReflectionFlag.Optional);
}
/**
* Whether it's a rest parameter, like `foo(...params);`.
*/
get isRest() {
return this.hasFlag(ReflectionFlag.Rest);
}
get hasExportAssignment() {
return this.hasFlag(ReflectionFlag.ExportAssignment);
}
get isAbstract() {
return this.hasFlag(ReflectionFlag.Abstract);
}
get isConst() {
return this.hasFlag(ReflectionFlag.Const);
}
get isReadonly() {
return this.hasFlag(ReflectionFlag.Readonly);
}
setFlag(flag, set) {
switch (flag) {
case ReflectionFlag.Private:
this.setSingleFlag(ReflectionFlag.Private, set);
if (set) {
this.setFlag(ReflectionFlag.Protected, false);
this.setFlag(ReflectionFlag.Public, false);
}
break;
case ReflectionFlag.Protected:
this.setSingleFlag(ReflectionFlag.Protected, set);
if (set) {
this.setFlag(ReflectionFlag.Private, false);
this.setFlag(ReflectionFlag.Public, false);
}
break;
case ReflectionFlag.Public:
this.setSingleFlag(ReflectionFlag.Public, set);
if (set) {
this.setFlag(ReflectionFlag.Private, false);
this.setFlag(ReflectionFlag.Protected, false);
}
break;
default:
this.setSingleFlag(flag, set);
}
}
setSingleFlag(flag, set) {
const name = ReflectionFlag[flag].replace(/(.)([A-Z])/g, (_m, a, b) => a + " " + b.toLowerCase());
if (!set && this.hasFlag(flag)) {
if (relevantFlags.includes(flag)) {
this.splice(this.indexOf(name), 1);
}
this.flags ^= flag;
}
else if (set && !this.hasFlag(flag)) {
if (relevantFlags.includes(flag)) {
this.push(name);
}
this.flags |= flag;
}
}
toObject() {
return Object.fromEntries(ReflectionFlags.serializedFlags
.filter((flag) => this[flag])
.map((flag) => [flag, true]));
}
fromObject(obj) {
for (const key of Object.keys(obj)) {
const flagName = key.substring(2); // isPublic => Public
if (flagName in ReflectionFlag) {
this.setFlag(ReflectionFlag[flagName], true);
}
}
}
}
exports.ReflectionFlags = ReflectionFlags;
ReflectionFlags.serializedFlags = [
"isPrivate",
"isProtected",
"isPublic",
"isStatic",
"isExternal",
"isOptional",
"isRest",
"hasExportAssignment",
"isAbstract",
"isConst",
"isReadonly",
];
var TraverseProperty;
(function (TraverseProperty) {
TraverseProperty[TraverseProperty["Children"] = 0] = "Children";
TraverseProperty[TraverseProperty["Parameters"] = 1] = "Parameters";
TraverseProperty[TraverseProperty["TypeLiteral"] = 2] = "TypeLiteral";
TraverseProperty[TraverseProperty["TypeParameter"] = 3] = "TypeParameter";
TraverseProperty[TraverseProperty["Signatures"] = 4] = "Signatures";
TraverseProperty[TraverseProperty["IndexSignature"] = 5] = "IndexSignature";
TraverseProperty[TraverseProperty["GetSignature"] = 6] = "GetSignature";
TraverseProperty[TraverseProperty["SetSignature"] = 7] = "SetSignature";
})(TraverseProperty || (exports.TraverseProperty = TraverseProperty = {}));
/**
* Base class for all reflection classes.
*
* While generating a documentation, TypeDoc generates an instance of {@link ProjectReflection}
* as the root for all reflections within the project. All other reflections are represented
* by the {@link DeclarationReflection} class.
*
* This base class exposes the basic properties one may use to traverse the reflection tree.
* You can use the {@link ContainerReflection.children} and {@link parent} properties to walk the tree. The {@link ContainerReflection.groups} property
* contains a list of all children grouped and sorted for rendering.
* @category Reflections
*/
let Reflection = (() => {
var _a;
let _parent_decorators;
let _parent_initializers = [];
let _parent_extraInitializers = [];
let _project_decorators;
let _project_initializers = [];
let _project_extraInitializers = [];
return _a = class Reflection {
constructor(name, kind, parent) {
this.flags = new ReflectionFlags();
/**
* The reflection this reflection is a child of.
*/
this.parent = __runInitializers(this, _parent_initializers, void 0);
this.project = (__runInitializers(this, _parent_extraInitializers), __runInitializers(this, _project_initializers, void 0));
/**
* The parsed documentation comment attached to this reflection.
*/
this.comment = __runInitializers(this, _project_extraInitializers);
this.id = REFLECTION_ID++;
this.parent = parent;
this.project = parent?.project || this;
this.name = name;
this.kind = kind;
// If our parent is external, we are too.
if (parent?.flags.isExternal) {
this.setFlag(ReflectionFlag.External);
}
}
/**
* Test whether this reflection is of the given kind.
*/
kindOf(kind) {
const kindArray = Array.isArray(kind) ? kind : [kind];
return kindArray.some((kind) => (this.kind & kind) !== 0);
}
/**
* Return the full name of this reflection. Intended for use in debugging. For log messages
* intended to be displayed to the user for them to fix, prefer {@link getFriendlyFullName} instead.
*
* The full name contains the name of this reflection and the names of all parent reflections.
*
* @param separator Separator used to join the names of the reflections.
* @returns The full name of this reflection.
*/
getFullName(separator = ".") {
if (this.parent && !this.parent.isProject()) {
return this.parent.getFullName(separator) + separator + this.name;
}
else {
return this.name;
}
}
/**
* Return the full name of this reflection, with signature names dropped if possible without
* introducing ambiguity in the name.
*/
getFriendlyFullName() {
if (this.parent && !this.parent.isProject()) {
if (this.kindOf(kind_1.ReflectionKind.ConstructorSignature |
kind_1.ReflectionKind.CallSignature |
kind_1.ReflectionKind.GetSignature |
kind_1.ReflectionKind.SetSignature)) {
return this.parent.getFriendlyFullName();
}
return this.parent.getFriendlyFullName() + "." + this.name;
}
else {
return this.name;
}
}
/**
* Set a flag on this reflection.
*/
setFlag(flag, value = true) {
this.flags.setFlag(flag, value);
}
/**
* Return an url safe alias for this reflection.
*/
getAlias() {
if (!this._alias) {
let alias = this.name.replace(/\W/g, "_");
if (alias === "") {
alias = "reflection-" + this.id;
}
// NTFS/ExFAT use uppercase, so we will too. It probably won't matter
// in this case since names will generally be valid identifiers, but to be safe...
const upperAlias = alias.toUpperCase();
let target = this;
while (target.parent && !target.hasOwnDocument) {
target = target.parent;
}
target._aliases ||= new Map();
let suffix = "";
if (!target._aliases.has(upperAlias)) {
target._aliases.set(upperAlias, 1);
}
else {
const count = target._aliases.get(upperAlias);
suffix = "-" + count.toString();
target._aliases.set(upperAlias, count + 1);
}
alias += suffix;
this._alias = alias;
}
return this._alias;
}
/**
* Has this reflection a visible comment?
*
* @returns TRUE when this reflection has a visible comment.
*/
hasComment() {
return this.comment ? this.comment.hasVisibleComponent() : false;
}
hasGetterOrSetter() {
return false;
}
/**
* Return a child by its name.
*
* @param arg The name hierarchy of the child to look for.
* @returns The found child or undefined.
*/
getChildByName(arg) {
const names = Array.isArray(arg)
? arg
: (0, utils_1.splitUnquotedString)(arg, ".");
const name = names[0];
let result;
this.traverse((child) => {
if (child.name === name) {
if (names.length <= 1) {
result = child;
}
else {
result = child.getChildByName(names.slice(1));
}
return false;
}
return true;
});
return result;
}
/**
* Return whether this reflection is the root / project reflection.
*/
isProject() {
return false;
}
isDeclaration() {
return false;
}
/**
* Check if this reflection or any of its parents have been marked with the `@deprecated` tag.
*/
isDeprecated() {
let signaturesDeprecated = false;
this.visit({
declaration(decl) {
if (decl.signatures?.length &&
decl.signatures.every((sig) => sig.comment?.getTag("@deprecated"))) {
signaturesDeprecated = true;
}
},
});
if (signaturesDeprecated || this.comment?.getTag("@deprecated")) {
return true;
}
return this.parent?.isDeprecated() ?? false;
}
visit(visitor) {
visitor[this.variant]?.(this);
}
/**
* Return a string representation of this reflection.
*/
toString() {
return kind_1.ReflectionKind[this.kind] + " " + this.name;
}
/**
* Return a string representation of this reflection and all of its children.
*
* Note: This is intended as a debug tool only, output may change between patch versions.
*
* @param indent Used internally to indent child reflections.
*/
toStringHierarchy(indent = "") {
const lines = [indent + this.toString()];
indent += " ";
this.traverse((child) => {
lines.push(child.toStringHierarchy(indent));
return true;
});
return lines.join("\n");
}
toObject(serializer) {
return {
id: this.id,
name: this.name,
variant: this.variant,
kind: this.kind,
flags: this.flags.toObject(),
comment: this.comment && !this.comment.isEmpty()
? serializer.toObject(this.comment)
: undefined,
};
}
fromObject(de, obj) {
// DO NOT copy id from obj. When deserializing reflections
// they should be given new ids since they belong to a different project.
this.name = obj.name;
// Skip copying variant, we know it's already the correct value because the deserializer
// will construct the correct class type.
this.kind = obj.kind;
this.flags.fromObject(obj.flags);
// Parent is set during construction, so we don't need to do it here.
this.comment = de.revive(obj.comment, () => new comment_1.Comment());
// url, anchor, hasOwnDocument, _alias, _aliases are set during rendering and only relevant during render.
// It doesn't make sense to serialize them to json, or restore them.
}
},
(() => {
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
_parent_decorators = [general_1.NonEnumerable // So that it doesn't show up in console.log
];
_project_decorators = [general_1.NonEnumerable];
__esDecorate(null, null, _parent_decorators, { kind: "field", name: "parent", static: false, private: false, access: { has: obj => "parent" in obj, get: obj => obj.parent, set: (obj, value) => { obj.parent = value; } }, metadata: _metadata }, _parent_initializers, _parent_extraInitializers);
__esDecorate(null, null, _project_decorators, { kind: "field", name: "project", static: false, private: false, access: { has: obj => "project" in obj, get: obj => obj.project, set: (obj, value) => { obj.project = value; } }, metadata: _metadata }, _project_initializers, _project_extraInitializers);
if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
})(),
_a;
})();
exports.Reflection = Reflection;

View File

@@ -0,0 +1,33 @@
import { Reflection, TraverseCallback } from "./abstract";
import { ReflectionCategory } from "../ReflectionCategory";
import { ReflectionGroup } from "../ReflectionGroup";
import type { ReflectionKind } from "./kind";
import type { Serializer, JSONOutput, Deserializer } from "../../serialization";
import type { DeclarationReflection } from "./declaration";
/**
* @category Reflections
*/
export declare abstract class ContainerReflection extends Reflection {
/**
* The children of this reflection.
*/
children?: DeclarationReflection[];
/**
* All children grouped by their kind.
*/
groups?: ReflectionGroup[];
/**
* All children grouped by their category.
*/
categories?: ReflectionCategory[];
/**
* Return a list of all children of a certain kind.
*
* @param kind The desired kind of children.
* @returns An array containing all children with the desired kind.
*/
getChildrenByKind(kind: ReflectionKind): DeclarationReflection[];
traverse(callback: TraverseCallback): void;
toObject(serializer: Serializer): JSONOutput.ContainerReflection;
fromObject(de: Deserializer, obj: JSONOutput.ContainerReflection): void;
}

Some files were not shown because too many files have changed in this diff Show More