@cosmology/ast
Version:
Cosmos TypeScript AST generation
135 lines (134 loc) • 5.25 kB
JavaScript
import * as t from "@babel/types";
const BILLION = t.numericLiteral(1_000_000_000);
BILLION.extra = { raw: "1_000_000_000", rawValue: 1000000000 };
export { BILLION };
export const cleanComment = (str) => {
return str.replace(/\*\//g, "*\\/");
};
const ensureOneSpace = (str) => {
if (/^[\s\n\t]+/.test(str))
return str;
return ` ${str}`;
};
export const makeCommentBlock = (comment) => {
if (!/[\n]+/.test(comment)) {
return {
type: "CommentBlock",
value: `* ${cleanComment(comment)} `,
start: null,
end: null,
loc: null,
};
}
let lines = comment.split("\n");
lines = ["*", ...lines, " "];
const comments = lines.map((line, i) => {
if (i == 0)
return line;
if (i == 1)
return ` *${ensureOneSpace(cleanComment(line))}`;
if (i == lines.length - 1)
return cleanComment(line);
return ` *${ensureOneSpace(cleanComment(line))}`;
});
return {
type: "CommentBlock",
value: comments.join("\n"),
start: null,
end: null,
loc: null,
};
};
export const renderNameSafely = (name) => {
return name
.split("_")
.map((str) => {
const parts = str.split(".");
str = parts[parts.length - 1];
return str;
})
.join("_");
};
export const getProtoFieldTypeName = (context, field) => {
let name = context.getTypeName(field);
return renderNameSafely(name);
};
export const recursiveNamespace = (names, moduleBlockBody) => {
if (!names || !names.length)
return moduleBlockBody;
const name = names.pop();
const body = [
t.exportNamedDeclaration(t.tsModuleDeclaration(t.identifier(name), t.tsModuleBlock(recursiveNamespace(names, moduleBlockBody)))),
];
return body;
};
export const bindMethod = (name) => {
return t.expressionStatement(t.assignmentExpression("=", t.memberExpression(t.thisExpression(), t.identifier(name)), t.callExpression(t.memberExpression(t.memberExpression(t.thisExpression(), t.identifier(name)), t.identifier("bind")), [t.thisExpression()])));
};
export const shorthandProperty = (prop) => {
return t.objectProperty(t.identifier(prop), t.identifier(prop), false, true);
};
export const importStmt = (names, path) => {
return t.importDeclaration(names.map((name) => t.importSpecifier(t.identifier(name), t.identifier(name))), t.stringLiteral(path));
};
export const memberExpressionOrIdentifier = (names) => {
if (names.length === 1) {
return t.identifier(names[0]);
}
if (names.length === 2) {
const [b, a] = names;
return t.memberExpression(t.identifier(a), t.identifier(b));
}
const [name, ...rest] = names;
return t.memberExpression(memberExpressionOrIdentifier(rest), t.identifier(name));
};
export const memberExpressionOrIdentifierAminoCasing = (names, aminoCasingFn) => {
if (names.length === 1) {
return t.identifier(aminoCasingFn(names[0]));
}
if (names.length === 2) {
const [b, a] = names;
return t.memberExpression(t.identifier(aminoCasingFn(a)), t.identifier(aminoCasingFn(b)));
}
const [name, ...rest] = names;
return t.memberExpression(memberExpressionOrIdentifierAminoCasing(rest, aminoCasingFn), t.identifier(aminoCasingFn(name)));
};
export const memberExpressionOrIdentifierAminoCaseField = (fields, aminoCaseFunc, useNullHandling = false) => {
if (fields.length === 1) {
return t.identifier(aminoCaseFunc(fields[0]));
}
if (fields.length === 2) {
const [b, a] = fields;
return useNullHandling
? t.memberExpression(t.identifier(aminoCaseFunc(a)), t.identifier(aminoCaseFunc(b)), false, true)
: t.memberExpression(t.identifier(aminoCaseFunc(a)), t.identifier(aminoCaseFunc(b)));
}
const [field, ...rest] = fields;
return useNullHandling
? t.memberExpression(memberExpressionOrIdentifierAminoCaseField(rest, aminoCaseFunc, useNullHandling), t.identifier(aminoCaseFunc(field)), false, true)
: t.memberExpression(memberExpressionOrIdentifierAminoCaseField(rest, aminoCaseFunc, useNullHandling), t.identifier(aminoCaseFunc(field)));
};
export const promiseTypeAnnotation = (name) => {
return t.tsTypeAnnotation(t.tsTypeReference(t.identifier("Promise"), t.tsTypeParameterInstantiation([
t.tsTypeReference(t.identifier(name)),
])));
};
export const getAcceptedInterfacesTypes = (context, lookupInterface) => {
return lookupInterface
? context.store._symbols.filter((s) => s.implementsType === lookupInterface &&
s.ref === context.ref.filename)
: [];
};
export const getSdkFieldName = (fieldName, field) => {
return field.options?.["(telescope:orig)"] ?? fieldName;
};
export const getAminoFieldName = (fieldName, field, interfaceName, context) => {
const orig = field.options?.["(telescope:orig)"] ?? fieldName;
if (interfaceName === "Any" &&
context.ref.proto.package === "google.protobuf" &&
(orig === "type_url" || orig === "typeUrl")) {
// type_url => type for amino
return "type";
}
return orig;
};