@cosmology/ast
Version:
Cosmos TypeScript AST generation
408 lines (407 loc) • 18.1 kB
JavaScript
import * as t from '@babel/types';
import { getInterfaceDecoderName, getKeyTypeEntryName } from '..';
import { TypeLong } from '../../../utils';
export const decode = {
string(args) {
const num = args.field.id;
const prop = args.field.name;
return switchOnTag(num, prop, baseTypes.string(args));
},
bool(args) {
const num = args.field.id;
const prop = args.field.name;
return switchOnTag(num, prop, baseTypes.bool(args));
},
double(args) {
const num = args.field.id;
const prop = args.field.name;
return switchOnTag(num, prop, baseTypes.double(args));
},
float(args) {
const num = args.field.id;
const prop = args.field.name;
return switchOnTag(num, prop, baseTypes.float(args));
},
int32(args) {
const num = args.field.id;
const prop = args.field.name;
return switchOnTag(num, prop, baseTypes.int32(args));
},
sint32(args) {
const num = args.field.id;
const prop = args.field.name;
return switchOnTag(num, prop, baseTypes.sint32(args));
},
uint32(args) {
const num = args.field.id;
const prop = args.field.name;
return switchOnTag(num, prop, baseTypes.uint32(args));
},
fixed32(args) {
const num = args.field.id;
const prop = args.field.name;
return switchOnTag(num, prop, baseTypes.fixed32(args));
},
sfixed32(args) {
const num = args.field.id;
const prop = args.field.name;
return switchOnTag(num, prop, baseTypes.sfixed32(args));
},
int64(args) {
const num = args.field.id;
const prop = args.field.name;
return switchOnTag(num, prop, baseTypes.int64(args));
},
sint64(args) {
const num = args.field.id;
const prop = args.field.name;
return switchOnTag(num, prop, baseTypes.sint64(args));
},
uint64(args) {
const num = args.field.id;
const prop = args.field.name;
return switchOnTag(num, prop, baseTypes.uint64(args));
},
fixed64(args) {
const num = args.field.id;
const prop = args.field.name;
return switchOnTag(num, prop, baseTypes.fixed64(args));
},
sfixed64(args) {
const num = args.field.id;
const prop = args.field.name;
return switchOnTag(num, prop, baseTypes.sfixed64(args));
},
duration(args) {
const num = args.field.id;
const prop = args.field.name;
const durationFormat = args.context.pluginValue('prototypes.typingsFormat.duration');
switch (durationFormat) {
case 'string':
return switchOnTag(num, prop, baseTypes.durationString(args));
case 'duration':
default:
return switchOnTag(num, prop, baseTypes.type(args));
}
},
timestamp(args) {
const num = args.field.id;
const prop = args.field.name;
const timestampFormat = args.context.pluginValue('prototypes.typingsFormat.timestamp');
switch (timestampFormat) {
case 'timestamp':
return switchOnTag(num, prop, baseTypes.timestamp(args));
case 'date':
default:
return switchOnTag(num, prop, baseTypes.timestampDate(args));
}
},
type(args) {
const num = args.field.id;
const prop = args.field.name;
return switchOnTag(num, prop, baseTypes.type(args));
},
enum(args) {
const num = args.field.id;
const prop = args.field.name;
return switchOnTag(num, prop, baseTypes.enum(args));
},
bytes(args) {
const num = args.field.id;
const prop = args.field.name;
return switchOnTag(num, prop, baseTypes.bytes(args));
},
keyHash(args) {
const num = args.field.id;
const prop = args.field.name;
return switchOnTagTakesArray(num, prop, baseTypes.keyHash(args));
},
tagDelimArray(args, expr) {
const num = args.field.id;
const prop = args.field.name;
return switchTagDelimArray(num, prop, expr);
},
array(args, expr) {
const num = args.field.id;
const prop = args.field.name;
return switchArray(num, prop, expr);
},
typeArray(args) {
const num = args.field.id;
const prop = args.field.name;
const name = args.context.getTypeName(args.field);
if (!args.context.options.aminoEncoding.useLegacyInlineEncoding &&
args.context.options.interfaces.enabled &&
args.field.type === 'google.protobuf.Any' &&
args.field.options['(cosmos_proto.accepts_interface)']) {
const isGlobalRegistry = args.context.options.interfaces?.enabled && args.context.options.interfaces?.useGlobalDecoderRegistry;
if (isGlobalRegistry) {
return switchAnyTypeArrayUnwrap(num, prop, name);
}
const interfaceName = args.field.options['(cosmos_proto.accepts_interface)'];
const interfaceFnName = getInterfaceDecoderName(interfaceName);
return args.context.options.interfaces.enabled && args.context.options.interfaces.useUseInterfacesParams ? switchAnyTypeArrayUseInterfaces(num, prop, name, interfaceFnName) : switchAnyTypeArray(num, prop, name);
}
return switchProtoTypeArray(args, num, prop, name);
}
};
export const baseTypes = {
// reader.string();
string(args) {
const useCosmosSDKDec = args.context.pluginValue('prototypes.typingsFormat.customTypes.useCosmosSDKDec');
const isCosmosSDKDec = (args.field.options?.['(gogoproto.customtype)'] ==
'github.com/cosmos/cosmos-sdk/types.Dec') ||
(args.field.options?.['(gogoproto.customtype)'] ==
'cosmossdk.io/math.LegacyDec');
let valueExpression = t.callExpression(t.memberExpression(t.identifier('reader'), t.identifier('string')), []);
if (useCosmosSDKDec && isCosmosSDKDec) {
args.context.addUtil("Decimal");
valueExpression = t.callExpression(t.memberExpression(t.callExpression(t.memberExpression(t.identifier('Decimal'), t.identifier('fromAtomics')), [
valueExpression,
t.numericLiteral(18)
]), t.identifier('toString')), []);
}
return valueExpression;
},
// reader.bool();
bool(args) {
return t.callExpression(t.memberExpression(t.identifier('reader'), t.identifier('bool')), []);
},
// reader.double();
double(args) {
return t.callExpression(t.memberExpression(t.identifier('reader'), t.identifier('double')), []);
},
// reader.float();
float(args) {
return t.callExpression(t.memberExpression(t.identifier('reader'), t.identifier('float')), []);
},
// reader.int32();
int32(args) {
return t.callExpression(t.memberExpression(t.identifier('reader'), t.identifier('int32')), []);
},
// reader.sint32();
sint32(args) {
return t.callExpression(t.memberExpression(t.identifier('reader'), t.identifier('sint32')), []);
},
// reader.uint32();
uint32(args) {
return t.callExpression(t.memberExpression(t.identifier('reader'), t.identifier('uint32')), []);
},
// reader.fixed32();
fixed32(args) {
return t.callExpression(t.memberExpression(t.identifier('reader'), t.identifier('fixed32')), []);
},
// reader.sfixed32();
sfixed32(args) {
return t.callExpression(t.memberExpression(t.identifier('reader'), t.identifier('sfixed32')), []);
},
long(type, args) {
TypeLong.addUtil(args.context);
switch (TypeLong.getType(args.context)) {
case 'BigInt':
return t.callExpression(t.memberExpression(t.identifier('reader'), t.identifier(type)), []);
case 'Long':
default:
return t.tsAsExpression(t.callExpression(t.memberExpression(t.identifier('reader'), t.identifier(type)), []), t.tsTypeReference(TypeLong.getPropIdentifier(args.context)));
}
},
// (reader.int64() as Long);
int64(args) {
return baseTypes.long('int64', args);
},
// (reader.sint64() as Long);
sint64(args) {
return baseTypes.long('sint64', args);
},
// (reader.uint64() as Long);
uint64(args) {
return baseTypes.long('uint64', args);
},
// (reader.fixed64() as Long);
fixed64(args) {
return baseTypes.long('fixed64', args);
},
// (reader.sfixed64() as Long);
sfixed64(args) {
return baseTypes.long('sfixed64', args);
},
// SignDocDirectAux.decode(reader, reader.uint32());
protoType(args) {
const name = args.context.getTypeName(args.field);
return t.callExpression(t.memberExpression(t.identifier(name), t.identifier('decode')), [
t.identifier('reader'),
t.callExpression(t.memberExpression(t.identifier('reader'), t.identifier('uint32')), []),
...(args.context.options.interfaces.enabled && args.context.options.interfaces.useUseInterfacesParams ? [
t.identifier('useInterfaces'),
] : []),
]);
},
anyType(args) {
const isGlobalRegistry = args.context.options.interfaces?.enabled && args.context.options.interfaces?.useGlobalDecoderRegistry;
if (isGlobalRegistry) {
return t.callExpression(t.memberExpression(t.identifier("GlobalDecoderRegistry"), t.identifier("unwrapAny")), [
t.identifier('reader')
]);
}
const interfaceName = args.field.options['(cosmos_proto.accepts_interface)'];
const interfaceFnName = getInterfaceDecoderName(interfaceName);
const asAny = t.tsAsExpression(t.callExpression(t.identifier(interfaceFnName), [
t.identifier('reader')
]), t.tsTypeReference(t.identifier('Any')));
return args.context.options.interfaces.enabled && args.context.options.interfaces.useUseInterfacesParams ? t.conditionalExpression(t.identifier('useInterfaces'), asAny, baseTypes.protoType(args)) : asAny;
},
type(args) {
if (!args.context.options.aminoEncoding.useLegacyInlineEncoding &&
args.context.options.interfaces.enabled &&
args.field.type === 'google.protobuf.Any' &&
args.field.options['(cosmos_proto.accepts_interface)']) {
return baseTypes.anyType(args);
}
return baseTypes.protoType(args);
},
// (reader.int32() as any);
enum(args) {
return t.tsAsExpression(t.callExpression(t.memberExpression(t.identifier('reader'), t.identifier('int32')), []), t.tsAnyKeyword());
},
// reader.bytes()
bytes(args) {
return t.callExpression(t.memberExpression(t.identifier('reader'), t.identifier('bytes')), []);
},
// message.period = fromDuration(Duration.decode(reader, reader.uint32()));
durationString(args) {
args.context.addUtil('fromDuration');
return t.callExpression(t.identifier('fromDuration'), [
t.callExpression(t.memberExpression(t.identifier('Duration'), t.identifier('decode')), [
t.identifier('reader'),
t.callExpression(t.memberExpression(t.identifier('reader'), t.identifier('uint32')), [])
])
]);
},
// message.periodReset = Timestamp.decode(reader, reader.uint32());
timestamp(args) {
return t.callExpression(t.memberExpression(t.identifier('Timestamp'), t.identifier('decode')), [
t.identifier('reader'),
t.callExpression(t.memberExpression(t.identifier('reader'), t.identifier('uint32')), [])
]);
},
timestampDate(args) {
args.context.addUtil('fromTimestamp');
return t.callExpression(t.identifier('fromTimestamp'), [
t.callExpression(t.memberExpression(t.identifier('Timestamp'), t.identifier('decode')), [
t.identifier('reader'),
t.callExpression(t.memberExpression(t.identifier('reader'), t.identifier('uint32')), [])
])
]);
},
// const entry1 = LogEntry_LabelsEntry.decode(reader, reader.uint32());
// if (entry1.value !== undefined) {
// message.labels[entry13.key] = entry13.value;
// }
keyHash(args) {
const prop = args.field.name;
const name = args.typeName;
const id = args.field.id;
const entryVariable = `entry${id}`;
return [
t.variableDeclaration('const', [
t.variableDeclarator(t.identifier(entryVariable), t.callExpression(t.memberExpression(t.identifier(getKeyTypeEntryName(name, prop)), t.identifier('decode')), [
t.identifier('reader'),
t.callExpression(t.memberExpression(t.identifier('reader'), t.identifier('uint32')), [])
]))
]),
t.ifStatement(t.binaryExpression('!==', t.memberExpression(t.identifier(entryVariable), t.identifier('value')), t.identifier('undefined')), t.blockStatement([
t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.memberExpression(t.identifier('message'), t.identifier(prop)), t.memberExpression(t.identifier(entryVariable), t.identifier('key')), true), t.memberExpression(t.identifier(entryVariable), t.identifier('value'))))
]))
];
}
};
export const switchOnTag = (num, prop, expr) => {
return t.switchCase(t.numericLiteral(num), [
t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.identifier('message'), t.identifier(prop)), expr)),
t.breakStatement()
]);
};
export const switchOnTagTakesArray = (num, prop, expr) => {
return t.switchCase(t.numericLiteral(num), [
...expr,
t.breakStatement()
]);
};
// message.tokenInMaxs.push(Coin.decode(reader, reader.uint32()));
export const switchProtoTypeArray = (args, num, prop, name) => {
return t.switchCase(t.numericLiteral(num), [
t.expressionStatement(t.callExpression(t.memberExpression(t.memberExpression(t.identifier('message'), t.identifier(prop)), t.identifier('push')), [
t.callExpression(t.memberExpression(t.identifier(name), t.identifier('decode')), [
t.identifier('reader'),
t.callExpression(t.memberExpression(t.identifier('reader'), t.identifier('uint32')), []),
...(args.context.options.interfaces.enabled && args.context.options.interfaces.useUseInterfacesParams ? [
t.identifier('useInterfaces'),
] : []),
])
])),
t.breakStatement()
]);
};
export const switchAnyTypeArrayUnwrap = (num, prop, name) => {
return t.switchCase(t.numericLiteral(num), [
t.expressionStatement(t.callExpression(t.memberExpression(t.memberExpression(t.identifier('message'), t.identifier(prop)), t.identifier('push')), [
t.callExpression(t.memberExpression(t.identifier("GlobalDecoderRegistry"), t.identifier("unwrapAny")), [
t.identifier('reader')
])
])),
t.breakStatement()
]);
};
export const switchAnyTypeArray = (num, prop, name) => {
return t.switchCase(t.numericLiteral(num), [
t.expressionStatement(t.callExpression(t.memberExpression(t.memberExpression(t.identifier("message"), t.identifier(prop)), t.identifier("push")), [
t.tsAsExpression(t.callExpression(t.memberExpression(t.identifier(name), t.identifier("decode")), [
t.identifier("reader"),
t.callExpression(t.memberExpression(t.identifier("reader"), t.identifier("uint32")), [])
]), t.tsTypeReference(t.identifier("Any"))),
])),
t.breakStatement(),
]);
};
export const switchAnyTypeArrayUseInterfaces = (num, prop, typeName, interfaceName) => {
return switchArray(num, prop, t.conditionalExpression(t.identifier('useInterfaces'), t.tsAsExpression(t.callExpression(t.identifier(interfaceName), [
t.identifier('reader')
]), t.tsTypeReference(t.identifier('Any'))), t.callExpression(t.memberExpression(t.identifier(typeName), t.identifier('decode')), [
t.identifier('reader'),
t.callExpression(t.memberExpression(t.identifier('reader'), t.identifier('uint32')), []),
t.identifier('useInterfaces'),
])));
};
// if ((tag & 7) === 2) {
// const end2 = reader.uint32() + reader.pos;
// while (reader.pos < end2) {
// message.codeIds.push((reader.uint64() as Long));
// }
// } else {
// message.codeIds.push((reader.uint64() as Long));
// }
export const switchTagDelimArray = (num, prop, expr) => {
const blockStmt = t.blockStatement([
t.expressionStatement(t.callExpression(t.memberExpression(t.memberExpression(t.identifier('message'), t.identifier(prop)), t.identifier('push')), [
expr
]))
]);
return t.switchCase(t.numericLiteral(num), [
t.ifStatement(t.binaryExpression('===', t.binaryExpression('&', t.identifier('tag'), t.numericLiteral(7)), t.numericLiteral(2)), t.blockStatement([
t.variableDeclaration('const', [
t.variableDeclarator(t.identifier('end2'), t.binaryExpression('+', t.callExpression(t.memberExpression(t.identifier('reader'), t.identifier('uint32')), []), t.memberExpression(t.identifier('reader'), t.identifier('pos'))))
]),
// while loop
t.whileStatement(t.binaryExpression('<', t.memberExpression(t.identifier('reader'), t.identifier('pos')), t.identifier('end2')), blockStmt)
]), blockStmt),
t.breakStatement()
]);
};
export const switchArray = (num, prop, expr) => {
return t.switchCase(t.numericLiteral(num), [
t.expressionStatement(t.callExpression(t.memberExpression(t.memberExpression(t.identifier('message'), t.identifier(prop)), t.identifier('push')), [
expr
])),
t.breakStatement()
]);
};