@cosmology/ast
Version:
Cosmos TypeScript AST generation
237 lines (215 loc) • 7.53 kB
text/typescript
import * as t from '@babel/types';
import { makeCommentBlock } from './utils';
// TODO move to @cosmology/utils package
export const commentBlock = (value: string): t.CommentBlock => {
return {
type: 'CommentBlock',
value,
start: null,
end: null,
loc: null
};
};
export const commentLine = (value: string): t.CommentLine => {
return {
type: 'CommentLine',
value,
start: null,
end: null,
loc: null
};
};
export function tsMethodSignature(
key: t.Expression,
typeParameters: t.TSTypeParameterDeclaration | null | undefined = null,
parameters: Array<t.Identifier | t.RestElement>,
typeAnnotation: t.TSTypeAnnotation | null = null,
trailingComments?: t.Comment[],
leadingComments?: t.Comment[]
): t.TSMethodSignature {
const obj = t.tsMethodSignature(
key, typeParameters, parameters, typeAnnotation
);
obj.kind = 'method';
if (trailingComments && trailingComments.length) {
obj.trailingComments = trailingComments;
}
if (leadingComments && leadingComments.length) {
obj.leadingComments = leadingComments;
}
return obj;
}
export const classMethod = (
kind: "get" | "set" | "method" | "constructor" | undefined,
key: t.Identifier | t.StringLiteral | t.NumericLiteral | t.Expression,
params: Array<t.Identifier | t.Pattern | t.RestElement | t.TSParameterProperty>,
body: t.BlockStatement,
returnType?: t.TSTypeAnnotation,
leadingComments: t.CommentLine[] | t.CommentBlock[] = [],
computed: boolean = false,
_static: boolean = false,
generator: boolean = false,
async: boolean = false,
) => {
const obj = t.classMethod(kind, key, params, body, computed, _static, generator, async)
if (returnType) {
obj.returnType = returnType;
}
if (leadingComments) {
obj.leadingComments = leadingComments;
}
return obj;
};
export const tsEnumMember = (
id: t.Identifier | t.StringLiteral,
initializer?: t.Expression,
leadingComments?: any[]
) => {
const obj = t.tsEnumMember(id, initializer);
obj.leadingComments = leadingComments;
return obj;
};
export const tsPropertySignature = (
key: t.Expression,
typeAnnotation: t.TSTypeAnnotation,
optional: boolean
) => {
const obj = t.tsPropertySignature(key, typeAnnotation);
obj.optional = optional;
return obj
};
export const functionDeclaration = (
id: t.Identifier,
params: (t.Identifier | t.Pattern | t.RestElement)[],
body: t.BlockStatement,
generator?: boolean,
async?: boolean,
returnType?: t.TSTypeAnnotation
): t.FunctionDeclaration => {
const func = t.functionDeclaration(id, params, body, generator, async);
func.returnType = returnType;
return func;
};
export const callExpression = (
callee: t.Expression | t.V8IntrinsicIdentifier,
_arguments: (t.Expression | t.SpreadElement | t.ArgumentPlaceholder)[],
typeParameters: t.TSTypeParameterInstantiation
) => {
const callExpr = t.callExpression(callee, _arguments);
callExpr.typeParameters = typeParameters;
return callExpr;
};
export const identifier = (name: string, typeAnnotation: t.TSTypeAnnotation, optional: boolean = false) => {
const type = t.identifier(name);
type.typeAnnotation = typeAnnotation;
type.optional = optional;
return type;
}
export const classDeclaration = (
id: t.Identifier,
superClass: t.Expression | null | undefined = null,
body: t.ClassBody,
decorators: Array<t.Decorator> | null = null,
vImplements?: t.TSExpressionWithTypeArguments[],
superTypeParameters?: t.TypeParameterInstantiation | t.TSTypeParameterInstantiation
): t.ClassDeclaration => {
const obj = t.classDeclaration(id, superClass, body, decorators);
if (superTypeParameters) {
obj.superTypeParameters = superTypeParameters;
}
if (vImplements) {
obj.implements = vImplements;
}
return obj;
}
export function classProperty(
key: t.Identifier | t.StringLiteral | t.NumericLiteral | t.Expression,
value: t.Expression | null = null,
typeAnnotation: t.TypeAnnotation | t.TSTypeAnnotation | t.Noop | null = null,
decorators: Array<t.Decorator> | null = null,
computed: boolean = false,
_static: boolean = false,
_readonly: boolean = false,
accessibility?: 'private' | 'protected' | 'public',
leadingComments: t.CommentLine[] = []
): t.ClassProperty {
const obj = t.classProperty(key, value, typeAnnotation, decorators, computed, _static);
if (accessibility) obj.accessibility = accessibility;
if (_readonly) obj.readonly = _readonly;
if (leadingComments.length) obj.leadingComments = leadingComments;
return obj;
};
export const arrowFunctionExpression = (
params: (t.Identifier | t.Pattern | t.RestElement)[],
body: t.BlockStatement,
returnType?: t.TSTypeAnnotation,
isAsync: boolean = false,
typeParameters?: t.TypeParameterDeclaration | t.TSTypeParameterDeclaration | t.Noop
) => {
const func = t.arrowFunctionExpression(params, body, isAsync);
func.returnType = returnType;
func.typeParameters = typeParameters;
return func;
};
export const tsTypeParameterDeclaration = (params: Array<t.TSTypeParameter>): t.TSTypeParameterDeclaration => {
const obj = t.tsTypeParameterDeclaration(params);
delete obj.extra;
return obj;
};
export const objectPattern = (
properties: (t.RestElement | t.ObjectProperty)[],
typeAnnotation: t.TSTypeAnnotation
) => {
const obj = t.objectPattern(properties);
obj.typeAnnotation = typeAnnotation;
return obj;
}
export const objectMethod =
(
kind: "method" | "get" | "set",
key: t.Expression,
params: (t.Identifier | t.Pattern | t.RestElement)[],
body: t.BlockStatement,
computed?: boolean,
generator?: boolean,
async?: boolean,
returnType?: t.TSTypeAnnotation | t.TypeAnnotation | t.Noop,
typeParameters?: t.TypeParameterDeclaration | t.TSTypeParameterDeclaration | t.Noop
): t.ObjectMethod => {
const obj = t.objectMethod(kind, key, params, body, computed, generator, async);
obj.returnType = returnType;
obj.typeParameters = typeParameters;
return obj;
};
export const objectProperty = (
key: t.Expression | t.Identifier | t.StringLiteral | t.NumericLiteral | t.BigIntLiteral | t.DecimalLiteral | t.PrivateName,
value: t.Expression | t.PatternLike,
computed?: boolean,
shorthand?: boolean,
decorators?: Array<t.Decorator> | null,
leadingComments: t.CommentLine[] = []
): t.ObjectProperty => {
const obj = t.objectProperty(key, value, computed, shorthand, decorators);
if (leadingComments.length) obj.leadingComments = leadingComments;
return obj;
};
export const makeCommentLineWithBlocks = (comment: string): t.CommentLine[] => {
if (!comment) return [];
// NOTE using blocks instead of lines here...
// @ts-ignore
return [makeCommentBlock(comment)];
}
export const newExpression = (
callee: t.Expression | t.V8IntrinsicIdentifier,
_arguments: (
| t.Expression
| t.SpreadElement
| t.JSXNamespacedName
| t.ArgumentPlaceholder
)[],
typeParameters?: t.TSTypeParameterInstantiation
): t.NewExpression => {
const expr = t.newExpression(callee, _arguments);
expr.typeParameters = typeParameters;
return expr;
};