UNPKG

@ts-ast-parser/core

Version:

Reflects a simplified version of the TypeScript AST for generating documentation

198 lines 6.7 kB
import { getVisibilityModifier, isAbstract, isOptional, isReadOnly, isStatic } from '../utils/member.js'; import { createType, createTypeFromDeclaration } from '../factories/create-type.js'; import { resolveExpression } from '../utils/resolve-expression.js'; import { tryAddProperty } from '../utils/try-add-property.js'; import { getReturnStatement } from '../utils/function.js'; import { MemberKind } from '../models/member-kind.js'; import { getDecorators } from '../utils/decorator.js'; import { DecoratorNode } from './decorator-node.js'; import { CommentNode } from './comment-node.js'; import ts from 'typescript'; /** * Represents the reflected node of a property declaration */ export class PropertyNode { constructor(node, nodeContext, context) { Object.defineProperty(this, "_node", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "_nodeContext", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "_context", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "_jsDoc", { enumerable: true, configurable: true, writable: true, value: void 0 }); this._node = node; this._nodeContext = nodeContext; this._context = context; const [getter, setter] = this._getAccessors(); if (getter) { this._jsDoc = new CommentNode(getter); } else if (setter) { this._jsDoc = new CommentNode(setter); } else { this._jsDoc = new CommentNode(this._node); } } getName() { const [getter, setter] = this._getAccessors(); if (getter) { return getter.name.getText() ?? ''; } if (setter) { return setter.name.getText() ?? ''; } if (ts.isIdentifier(this._node.name)) { return this._node.name.escapedText ?? ''; } return this._node.name.getText() ?? ''; } getKind() { return MemberKind.Property; } getTSNode() { return this._node; } getContext() { return this._context; } getLine() { const [getter, setter] = this._getAccessors(); if (getter) { return this._context.getLinePosition(getter); } if (setter) { return this._context.getLinePosition(setter); } return this._context.getLocation(this._node).line; } getType() { const jsDocType = ts.getJSDocType(this._node); if (jsDocType) { return createType(jsDocType, this._context); } if (this._nodeContext?.type) { return createType(this._nodeContext.type, this._context); } if (this._node.type) { return createType(this._node.type, this._context); } return createTypeFromDeclaration(this._node, this._context); } getDefault() { const jsDocDefaultValue = this.getJSDoc().getTag('default')?.text; const [getter, setter] = this._getAccessors(); if (jsDocDefaultValue) { return jsDocDefaultValue; } if (getter) { return resolveExpression(getReturnStatement(getter.body)?.expression, this._context); } if (setter) { return undefined; } return resolveExpression(this._node.initializer, this._context); } getModifier() { if (!ts.isClassElement(this._node)) { return null; } return getVisibilityModifier(this._node); } getJSDoc() { return this._jsDoc; } getDecorators() { const [getter, setter] = this._getAccessors(); if (getter) { return getDecorators(getter).map(d => new DecoratorNode(d, this._context)); } if (setter) { return getDecorators(setter).map(d => new DecoratorNode(d, this._context)); } return getDecorators(this._node).map(d => new DecoratorNode(d, this._context)); } isOptional() { if (this._nodeContext) { return isOptional(this._nodeContext.symbol); } const symbol = this._context.getSymbol(this._node); return isOptional(symbol); } isStatic() { const [getter, setter] = this._getAccessors(); if (getter) { return isStatic(getter); } if (setter) { return isStatic(setter); } return isStatic(this._node); } isReadOnly() { const readOnlyTag = !!this.getJSDoc().getTag('readonly'); const [getter, setter] = this._getAccessors(); return readOnlyTag || (!!getter && !setter) || isReadOnly(this._node); } isWriteOnly() { const [getter, setter] = this._getAccessors(); return !getter && !!setter; } isAbstract() { return isAbstract(this._node); } isInherited() { return !this._nodeContext?.overrides && !!this._nodeContext?.inherited; } overrides() { return !!this._nodeContext?.overrides; } /** * Serializes the reflected node * * @returns The reflected node as a serializable object */ serialize() { const tmpl = { name: this.getName(), kind: this.getKind(), type: this.getType().serialize(), }; tryAddProperty(tmpl, 'line', this.getLine()); tryAddProperty(tmpl, 'optional', this.isOptional()); tryAddProperty(tmpl, 'jsDoc', this.getJSDoc().serialize()); tryAddProperty(tmpl, 'decorators', this.getDecorators().map(d => d.serialize())); tryAddProperty(tmpl, 'default', this.getDefault()); tryAddProperty(tmpl, 'static', this.isStatic()); tryAddProperty(tmpl, 'readOnly', this.isReadOnly()); tryAddProperty(tmpl, 'abstract', this.isAbstract()); tryAddProperty(tmpl, 'override', this.overrides()); tryAddProperty(tmpl, 'inherited', this.isInherited()); tryAddProperty(tmpl, 'writeOnly', this.isWriteOnly()); return tmpl; } _getAccessors() { const decls = this._nodeContext?.symbol?.getDeclarations() ?? []; const getter = decls.find(ts.isGetAccessor); const setter = decls.find(ts.isSetAccessor); return [getter, setter]; } } //# sourceMappingURL=property-node.js.map