@ts-ast-parser/core
Version:
Reflects a simplified version of the TypeScript AST for generating documentation
198 lines • 6.7 kB
JavaScript
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