utils/node_modules/@microsoft/api-extractor-model/lib/items/ApiItem.js
2024-02-07 01:33:07 -05:00

274 lines
10 KiB
JavaScript

"use strict";
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See LICENSE in the project root for license information.
Object.defineProperty(exports, "__esModule", { value: true });
exports.ApiItem = exports.apiItem_onParentChanged = exports.ApiItemKind = void 0;
const ApiParameterListMixin_1 = require("../mixins/ApiParameterListMixin");
const node_core_library_1 = require("@rushstack/node-core-library");
const ApiItemContainerMixin_1 = require("../mixins/ApiItemContainerMixin");
/**
* The type returned by the {@link ApiItem.kind} property, which can be used to easily distinguish subclasses of
* {@link ApiItem}.
*
* @public
*/
var ApiItemKind;
(function (ApiItemKind) {
ApiItemKind["CallSignature"] = "CallSignature";
ApiItemKind["Class"] = "Class";
ApiItemKind["Constructor"] = "Constructor";
ApiItemKind["ConstructSignature"] = "ConstructSignature";
ApiItemKind["EntryPoint"] = "EntryPoint";
ApiItemKind["Enum"] = "Enum";
ApiItemKind["EnumMember"] = "EnumMember";
ApiItemKind["Function"] = "Function";
ApiItemKind["IndexSignature"] = "IndexSignature";
ApiItemKind["Interface"] = "Interface";
ApiItemKind["Method"] = "Method";
ApiItemKind["MethodSignature"] = "MethodSignature";
ApiItemKind["Model"] = "Model";
ApiItemKind["Namespace"] = "Namespace";
ApiItemKind["Package"] = "Package";
ApiItemKind["Property"] = "Property";
ApiItemKind["PropertySignature"] = "PropertySignature";
ApiItemKind["TypeAlias"] = "TypeAlias";
ApiItemKind["Variable"] = "Variable";
ApiItemKind["None"] = "None";
})(ApiItemKind = exports.ApiItemKind || (exports.ApiItemKind = {}));
// PRIVATE - Allows ApiItemContainerMixin to assign the parent.
//
exports.apiItem_onParentChanged = Symbol('ApiItem._onAddToContainer');
/**
* The abstract base class for all members of an `ApiModel` object.
*
* @remarks
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
* API declarations.
* @public
*/
class ApiItem {
constructor(options) {
// ("options" is not used here, but part of the inheritance pattern)
}
static deserialize(jsonObject, context) {
// The Deserializer class is coupled with a ton of other classes, so we delay loading it
// to avoid ES5 circular imports.
const deserializerModule = require('../model/Deserializer');
return deserializerModule.Deserializer.deserialize(context, jsonObject);
}
/** @virtual */
static onDeserializeInto(options, context, jsonObject) {
// (implemented by subclasses)
}
/** @virtual */
serializeInto(jsonObject) {
jsonObject.kind = this.kind;
jsonObject.canonicalReference = this.canonicalReference.toString();
}
/**
* Identifies the subclass of the `ApiItem` base class.
* @virtual
*/
get kind() {
throw new Error('ApiItem.kind was not implemented by the child class');
}
/**
* Warning: This API is used internally by API extractor but is not yet ready for general usage.
*
* @remarks
*
* Returns a `DeclarationReference` object using the experimental new declaration reference notation.
*
* @beta
*/
get canonicalReference() {
if (!this._canonicalReference) {
try {
this._canonicalReference = this.buildCanonicalReference();
}
catch (e) {
const name = this.getScopedNameWithinPackage() || this.displayName;
throw new node_core_library_1.InternalError(`Error building canonical reference for ${name}:\n` + e.message);
}
}
return this._canonicalReference;
}
/**
* Returns a string key that can be used to efficiently retrieve an `ApiItem` from an `ApiItemContainerMixin`.
* The key is unique within the container. Its format is undocumented and may change at any time.
*
* @remarks
* Use the `getContainerKey()` static member to construct the key. Each subclass has a different implementation
* of this function, according to the aspects that are important for identifying it.
*
* @virtual
*/
get containerKey() {
throw new node_core_library_1.InternalError('ApiItem.containerKey was not implemented by the child class');
}
/**
* Returns a name for this object that can be used in diagnostic messages, for example.
*
* @remarks
* For an object that inherits ApiNameMixin, this will return the declared name (e.g. the name of a TypeScript
* function). Otherwise, it will return a string such as "(call signature)" or "(model)".
*
* @virtual
*/
get displayName() {
switch (this.kind) {
case ApiItemKind.CallSignature:
return '(call)';
case ApiItemKind.Constructor:
return '(constructor)';
case ApiItemKind.ConstructSignature:
return '(new)';
case ApiItemKind.IndexSignature:
return '(indexer)';
case ApiItemKind.Model:
return '(model)';
}
return '(???)'; // All other types should inherit ApiNameMixin which will override this property
}
/**
* If this item was added to a ApiItemContainerMixin item, then this returns the container item.
* If this is an Parameter that was added to a method or function, then this returns the function item.
* Otherwise, it returns undefined.
* @virtual
*/
get parent() {
return this._parent;
}
/**
* This property supports a visitor pattern for walking the tree.
* For items with ApiItemContainerMixin, it returns the contained items, sorted alphabetically.
* Otherwise it returns an empty array.
* @virtual
*/
get members() {
return [];
}
/**
* If this item has a name (i.e. extends `ApiNameMixin`), then return all items that have the same parent
* and the same name. Otherwise, return all items that have the same parent and the same `ApiItemKind`.
*
* @remarks
* Examples: For a function, this would return all overloads for the function. For a constructor, this would
* return all overloads for the constructor. For a merged declaration (e.g. a `namespace` and `enum` with the
* same name), this would return both declarations. If this item does not have a parent, or if it is the only
* item of its name/kind, then the result is an array containing only this item.
*/
getMergedSiblings() {
const parent = this._parent;
if (parent && ApiItemContainerMixin_1.ApiItemContainerMixin.isBaseClassOf(parent)) {
return parent._getMergedSiblingsForMember(this);
}
return [];
}
/**
* Returns the chain of ancestors, starting from the root of the tree, and ending with the this item.
*/
getHierarchy() {
const hierarchy = [];
for (let current = this; current !== undefined; current = current.parent) {
hierarchy.push(current);
}
hierarchy.reverse();
return hierarchy;
}
/**
* This returns a scoped name such as `"Namespace1.Namespace2.MyClass.myMember()"`. It does not include the
* package name or entry point.
*
* @remarks
* If called on an ApiEntrypoint, ApiPackage, or ApiModel item, the result is an empty string.
*/
getScopedNameWithinPackage() {
const reversedParts = [];
for (let current = this; current !== undefined; current = current.parent) {
if (current.kind === ApiItemKind.Model ||
current.kind === ApiItemKind.Package ||
current.kind === ApiItemKind.EntryPoint) {
break;
}
if (reversedParts.length !== 0) {
reversedParts.push('.');
}
else {
switch (current.kind) {
case ApiItemKind.CallSignature:
case ApiItemKind.ConstructSignature:
case ApiItemKind.Constructor:
case ApiItemKind.IndexSignature:
// These functional forms don't have a proper name, so we don't append the "()" suffix
break;
default:
if (ApiParameterListMixin_1.ApiParameterListMixin.isBaseClassOf(current)) {
reversedParts.push('()');
}
}
}
reversedParts.push(current.displayName);
}
return reversedParts.reverse().join('');
}
/**
* If this item is an ApiPackage or has an ApiPackage as one of its parents, then that object is returned.
* Otherwise undefined is returned.
*/
getAssociatedPackage() {
for (let current = this; current !== undefined; current = current.parent) {
if (current.kind === ApiItemKind.Package) {
return current;
}
}
return undefined;
}
/**
* If this item is an ApiModel or has an ApiModel as one of its parents, then that object is returned.
* Otherwise undefined is returned.
*/
getAssociatedModel() {
for (let current = this; current !== undefined; current = current.parent) {
if (current.kind === ApiItemKind.Model) {
return current;
}
}
return undefined;
}
/**
* A text string whose value determines the sort order that is automatically applied by the
* {@link (ApiItemContainerMixin:interface)} class.
*
* @remarks
* The value of this string is undocumented and may change at any time.
* If {@link (ApiItemContainerMixin:interface).preserveMemberOrder} is enabled for the `ApiItem`'s parent,
* then no sorting is performed, and this key is not used.
*
* @virtual
*/
getSortKey() {
return this.containerKey;
}
/**
* PRIVATE
*
* @privateRemarks
* Allows ApiItemContainerMixin to assign the parent when the item is added to a container.
*
* @internal
*/
[exports.apiItem_onParentChanged](parent) {
this._parent = parent;
this._canonicalReference = undefined;
}
/**
* Builds the cached object used by the `canonicalReference` property.
* @virtual
*/
buildCanonicalReference() {
throw new node_core_library_1.InternalError('ApiItem.canonicalReference was not implemented by the child class');
}
}
exports.ApiItem = ApiItem;
//# sourceMappingURL=ApiItem.js.map