@cosmology/ast
Version:
Cosmos TypeScript AST generation
327 lines (326 loc) • 13.6 kB
JavaScript
import * as t from '@babel/types';
import { identifier, callExpression, TypeLong } from '../../../utils';
import { getDefaultTSTypeFromProtoType } from '../../types';
// message.sender = expr
const setField = (prop, expr) => {
return t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.identifier('message'), t.identifier(prop)), expr));
};
// message.sender = object.sender ?? value;
const setNullishCoalescing = (prop, value) => {
return setField(prop, t.logicalExpression('??', t.memberExpression(t.identifier('object'), t.identifier(prop)), value));
};
const setNotUndefinedAndNotNull = (prop, value, defaultValue, args) => {
const strictNullCheckForPrototypeMethods = args.context.pluginValue('prototypes.strictNullCheckForPrototypeMethods');
if (strictNullCheckForPrototypeMethods) {
return t.ifStatement(t.logicalExpression('&&', t.binaryExpression('!==', t.memberExpression(t.identifier('object'), t.identifier(prop)), t.identifier('undefined')), t.binaryExpression('!==', t.memberExpression(t.identifier('object'), t.identifier(prop)), t.nullLiteral())), t.blockStatement([
t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.identifier('message'), t.identifier(prop)), value))
]));
}
else {
return t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.identifier('message'), t.identifier(prop)), t.conditionalExpression(t.logicalExpression('&&', t.binaryExpression('!==', t.memberExpression(t.identifier('object'), t.identifier(prop)), t.identifier('undefined')), t.binaryExpression('!==', t.memberExpression(t.identifier('object'), t.identifier(prop)), t.nullLiteral())), value, defaultValue)));
}
};
export const fromPartial = {
// message.sender = object.sender ?? "";
string(args) {
const prop = args.field.name;
return setNullishCoalescing(prop, getDefaultTSTypeFromProtoType(args.context, args.field, args.isOneOf));
},
// message.disableMacros = object.disableMacros ?? false;
bool(args) {
const prop = args.field.name;
return setNullishCoalescing(prop, getDefaultTSTypeFromProtoType(args.context, args.field, args.isOneOf));
},
// message.doubleValue = object.doubleValue ?? 0;
number(args) {
const prop = args.field.name;
return setNullishCoalescing(prop, getDefaultTSTypeFromProtoType(args.context, args.field, args.isOneOf));
},
int32(args) {
return fromPartial.number(args);
},
uint32(args) {
return fromPartial.number(args);
},
sint32(args) {
return fromPartial.number(args);
},
fixed32(args) {
return fromPartial.number(args);
},
sfixed32(args) {
return fromPartial.number(args);
},
double(args) {
return fromPartial.number(args);
},
float(args) {
return fromPartial.number(args);
},
// OLD: message.myInt64Value = object.myInt64Value !== undefined && object.myInt64Value !== null ? Long.fromValue(object.myInt64Value) : Long.ZERO;
// NEW: if( object.myInt64Value !== undefined && object.myInt64Value !== null ) { message.myInt64Value = Long.fromValue(object.myInt64Value) }
long(args) {
const prop = args.field.name;
TypeLong.addUtil(args.context);
return setNotUndefinedAndNotNull(prop, TypeLong.getFromValueWithArgs(args.context, t.memberExpression(t.identifier('object'), t.identifier(prop))), getDefaultTSTypeFromProtoType(args.context, args.field, args.isOneOf), args);
},
int64(args) {
return fromPartial.long(args);
},
uint64(args) {
return fromPartial.long(args);
},
sint64(args) {
return fromPartial.long(args);
},
fixed64(args) {
return fromPartial.long(args);
},
sfixed64(args) {
return fromPartial.long(args);
},
// message.signDoc = object.signDoc !== undefined && object.signDoc !== null ? SignDocDirectAux.fromPartial(object.signDoc) : SignDocDirectAux.fromPartial({});
type(args) {
const prop = args.field.name;
let name = args.context.getTypeName(args.field);
if (!args.context.options.aminoEncoding.useLegacyInlineEncoding &&
args.context.options.interfaces.enabled &&
args.context.options.interfaces?.useGlobalDecoderRegistry &&
args.field.type === 'google.protobuf.Any' &&
args.field.options['(cosmos_proto.accepts_interface)']) {
name = 'GlobalDecoderRegistry';
}
return setNotUndefinedAndNotNull(prop, t.callExpression(t.memberExpression(t.identifier(name), t.identifier('fromPartial')), [
t.memberExpression(t.identifier('object'), t.identifier(prop))
]), t.identifier('undefined'), args);
},
// message.mode = object.mode ?? 0;
enum(args) {
const prop = args.field.name;
return setNullishCoalescing(prop, getDefaultTSTypeFromProtoType(args.context, args.field, args.isOneOf));
},
// message.queryData = object.queryData ?? new Uint8Array()
bytes(args) {
const prop = args.field.name;
return setNullishCoalescing(prop, getDefaultTSTypeFromProtoType(args.context, args.field, args.isOneOf));
},
// message.period = object.period ?? undefined;
duration(args) {
const durationFormat = args.context.pluginValue('prototypes.typingsFormat.duration');
switch (durationFormat) {
case 'string':
return fromPartial.durationString(args);
case 'duration':
default:
return fromPartial.type(args);
}
},
durationString(args) {
const prop = args.field.name;
return setNullishCoalescing(prop, t.identifier('undefined'));
},
timestamp(args) {
const timestampFormat = args.context.pluginValue('prototypes.typingsFormat.timestamp');
switch (timestampFormat) {
case 'timestamp':
return fromPartial.type(args);
case 'date':
default:
return fromPartial.timestampDate(args);
}
},
// message.periodReset = object.periodReset ?? undefined;
timestampDate(args) {
const prop = args.field.name;
return setNullishCoalescing(prop, t.identifier('undefined'));
},
// message.referenceMap = Object.entries(object.referenceMap ?? {}).reduce<{
// [key: Long]: Reference;
// }>((acc, [key, value]) => {
// if (value !== undefined) {
// acc[Number(key)] = Reference.fromPartial(value);
// }
// return acc;
// }, {});
// message.labels = Object.entries(object.typeMap ?? {}).reduce<{
// [key: string]: string;
// }>((acc, [key, value]) => {
// if (value !== undefined) {
// acc[key] = String(value);
// }
// return acc;
// }, {});
keyHash(args) {
const prop = args.field.name;
const keyType = args.field.keyType;
const valueType = args.field.parsedType.name;
let fromPartialWithArgs = null;
// valueTypeType: string for identifier
let valueTypeType = valueType;
switch (valueType) {
case 'string':
fromPartialWithArgs = t.callExpression(t.identifier('String'), [
t.identifier('value')
]);
break;
case 'int32':
case 'uint32':
valueTypeType = 'number';
fromPartialWithArgs = t.callExpression(t.identifier('Number'), [
t.identifier('value')
]);
break;
case 'int64':
case 'uint64':
case 'sint64':
case 'fixed64':
case 'sfixed64':
TypeLong.addUtil(args.context);
valueTypeType = TypeLong.getPropType(args.context);
fromPartialWithArgs = TypeLong.getFromValueWithArgs(args.context, t.identifier('value'));
break;
default:
fromPartialWithArgs = t.callExpression(t.memberExpression(t.identifier(valueType), t.identifier('fromPartial')), [
t.identifier('value')
]);
}
let wrapKey = null;
let keyTypeType = null;
switch (keyType) {
case 'string':
wrapKey = (a) => a;
keyTypeType = t.tsStringKeyword();
break;
case 'int64':
case 'uint64':
case 'sint64':
case 'fixed64':
case 'sfixed64':
wrapKey = (a) => t.callExpression(t.identifier('Number'), [
a
]);
TypeLong.addUtil(args.context);
keyTypeType = t.tsTypeReference(TypeLong.getPropIdentifier(args.context));
break;
case 'int32':
case 'uint32':
wrapKey = (a) => t.callExpression(t.identifier('Number'), [
a
]);
keyTypeType = t.tsNumberKeyword();
break;
default:
throw new Error('keyHash requires new type. Ask maintainers.');
}
return t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.identifier('message'), t.identifier(prop)), callExpression(t.memberExpression(t.callExpression(t.memberExpression(t.identifier('Object'), t.identifier('entries')), [
t.logicalExpression('??', t.memberExpression(t.identifier('object'), t.identifier(prop)), t.objectExpression([]))
]), t.identifier('reduce')), [
t.arrowFunctionExpression([
t.identifier('acc'),
t.arrayPattern([
t.identifier('key'),
t.identifier('value')
])
], t.blockStatement([
t.ifStatement(t.binaryExpression('!==', t.identifier('value'), t.identifier('undefined')), t.blockStatement([
t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.identifier('acc'), wrapKey(t.identifier('key')), true), fromPartialWithArgs))
])),
t.returnStatement(t.identifier('acc'))
])),
t.objectExpression([]),
], t.tsTypeParameterInstantiation([
t.tsTypeLiteral([
t.tsIndexSignature([
identifier('key', t.tsTypeAnnotation(keyTypeType))
], t.tsTypeAnnotation(t.tsTypeReference(t.identifier(valueTypeType))))
])
]))));
},
// message.codeIds = object.codeIds?.map(e => Long.fromValue(e)) || [];
array(args, expr) {
const prop = args.field.name;
return t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.identifier('message'), t.identifier(prop)), t.logicalExpression('||', t.optionalCallExpression(t.optionalMemberExpression(t.memberExpression(t.identifier('object'), t.identifier(prop)), t.identifier('map'), false, true), [
t.arrowFunctionExpression([
t.identifier('e')
], expr)
], false), t.arrayExpression([]))));
}
};
export const arrayTypes = {
// message.overloadId = object.overloadId?.map(e => e) || [];
identity() {
return t.identifier('e');
},
string() {
return arrayTypes.identity();
},
bool() {
return arrayTypes.identity();
},
bytes() {
return arrayTypes.identity();
},
double() {
return arrayTypes.identity();
},
float() {
return arrayTypes.identity();
},
int32() {
return arrayTypes.identity();
},
uint32() {
return arrayTypes.identity();
},
sint32() {
return arrayTypes.identity();
},
fixed32() {
return arrayTypes.identity();
},
sfixed32() {
return arrayTypes.identity();
},
enum() {
return arrayTypes.identity();
},
// message.codeIds = object.codeIds?.map(e => Long.fromValue(e)) || [];
long(args) {
TypeLong.addUtil(args.context);
return TypeLong.getFromValueWithArgs(args.context, t.identifier('e'));
},
int64(args) {
return arrayTypes.long(args);
},
uint64(args) {
return arrayTypes.long(args);
},
sint64(args) {
return arrayTypes.long(args);
},
fixed64(args) {
return arrayTypes.long(args);
},
sfixed64(args) {
return arrayTypes.long(args);
},
// message.tokenInMaxs = object.tokenInMaxs?.map(e => Coin.fromPartial(e)) || [];
type(args) {
let name = args.context.getTypeName(args.field);
let callee = t.memberExpression(t.identifier(name), t.identifier('fromPartial'));
if (!args.context.options.aminoEncoding.useLegacyInlineEncoding &&
args.context.options.interfaces.enabled &&
args.context.options.interfaces?.useGlobalDecoderRegistry &&
args.field.type === 'google.protobuf.Any' &&
args.field.options['(cosmos_proto.accepts_interface)']) {
name = 'GlobalDecoderRegistry';
callee = t.memberExpression(t.identifier(name), t.identifier('fromPartial'));
return t.tsAsExpression(t.callExpression(callee, [
t.identifier('e')
]), t.tsAnyKeyword());
}
return t.callExpression(callee, [
t.identifier('e')
]);
}
};