UNPKG

@cosmology/ast

Version:
305 lines (304 loc) 12.6 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.isMethod = exports.createFieldTypeComparison = exports.createArrayTypeComparison = exports.createProtoTypeComparison = exports.createFieldExistingTest = exports.createScalarTypeComparison = exports.createInstanceOfTypeComparisonGroup = exports.createInstanceOfTypeComparison = void 0; const t = __importStar(require("@babel/types")); const utils_1 = require("../../../utils"); const types_1 = require("../types"); const types_2 = require("../../types"); const utils_2 = require("@cosmology/utils"); const INPUT_PARAM = "o"; const createInstanceOfTypeComparison = (args) => { const { fieldName, type } = args; return t.binaryExpression("instanceof", fieldName, t.identifier(type)); }; exports.createInstanceOfTypeComparison = createInstanceOfTypeComparison; const createInstanceOfTypeComparisonGroup = (args) => { const { context, fieldName, field, types } = args; switch (types.length) { case 0: throw new Error("types shouldn't be empty."); case 1: return (0, exports.createInstanceOfTypeComparison)({ context, fieldName, field, type: types[0], }); default: const current = types.shift(); return t.logicalExpression("||", (0, exports.createInstanceOfTypeComparison)({ context, fieldName, field, type: current, }), (0, exports.createInstanceOfTypeComparisonGroup)({ context, fieldName, field, types, })); } }; exports.createInstanceOfTypeComparisonGroup = createInstanceOfTypeComparisonGroup; const createScalarTypeComparison = (args) => { const { fieldName, type } = args; return t.binaryExpression("===", t.unaryExpression("typeof", fieldName), t.stringLiteral(type)); }; exports.createScalarTypeComparison = createScalarTypeComparison; const createFieldExistingTest = (args) => { const { fieldName } = args; args.context.addUtil("isSet"); return t.callExpression(t.identifier("isSet"), [fieldName]); }; exports.createFieldExistingTest = createFieldExistingTest; const createProtoTypeComparison = (args) => { const { context, fieldName, field, methodName } = args; switch (field.type) { case "google.protobuf.Duration": case "Duration": const durationFormat = args.context.pluginValue("prototypes.typingsFormat.duration"); if (durationFormat === "string") { return (0, exports.createScalarTypeComparison)({ context, fieldName, field, type: "string", }); } case "google.protobuf.Timestamp": case "Timestamp": const timestampFormat = args.context.pluginValue("prototypes.typingsFormat.timestamp"); if (timestampFormat === "date") { (0, exports.createInstanceOfTypeComparison)({ context, fieldName, field, type: "Date", }); } case "Any": case "google.protobuf.Any": const lookupInterface = field.options?.["(cosmos_proto.accepts_interface)"]; const acceptedTypes = (0, utils_1.getAcceptedInterfacesTypes)(context, lookupInterface); const acceptedTypeNames = acceptedTypes.map((acceptedType) => acceptedType.readAs); const typeName = context.getTypeName(field); acceptedTypeNames.push(typeName); return acceptedTypeNames.reduce((comparison, acceptedTypeName) => { const current = t.callExpression(t.memberExpression(t.identifier(acceptedTypeName), t.identifier(methodName)), [fieldName]); return comparison ? t.logicalExpression("||", comparison, current) : current; }, undefined); } const typeName = context.getTypeName(field); return t.callExpression(t.memberExpression(t.identifier(typeName), t.identifier(methodName)), [fieldName]); }; exports.createProtoTypeComparison = createProtoTypeComparison; const createArrayTypeComparison = (args) => { const { fieldName, typeComparison } = args; const isArrayExp = t.callExpression(t.memberExpression(t.identifier("Array"), t.identifier("isArray")), [t.memberExpression(t.identifier(INPUT_PARAM), t.identifier(fieldName))]); return typeComparison ? t.logicalExpression("&&", isArrayExp, t.logicalExpression("||", t.unaryExpression("!", t.memberExpression(t.memberExpression(t.identifier(INPUT_PARAM), t.identifier(fieldName)), t.identifier("length"))), typeComparison)) : isArrayExp; }; exports.createArrayTypeComparison = createArrayTypeComparison; function getScalarExpression(args) { //TODO:: Date, timestamp, etc const { context, field, fieldName } = args; switch (field.type) { case "string": return (0, exports.createScalarTypeComparison)({ context, field, fieldName, type: "string", }); case "bool": return (0, exports.createScalarTypeComparison)({ context, field, fieldName, type: "boolean", }); case "float": case "double": case "int32": case "sint32": case "uint32": case "fixed32": case "sfixed32": return (0, exports.createScalarTypeComparison)({ context, field, fieldName, type: "number", }); case "bytes": return t.logicalExpression("||", (0, exports.createInstanceOfTypeComparison)({ context, field, fieldName, type: "Uint8Array", }), (0, exports.createScalarTypeComparison)({ context, field, fieldName, type: "string", })); case "int64": case "sint64": case "uint64": case "fixed64": case "sfixed64": return (0, exports.createScalarTypeComparison)({ context, field, fieldName, type: "bigint", }); } return undefined; } const createFieldTypeComparison = (args) => { const { context, field, fieldName, methodName } = args; if (field.keyType) { return (0, exports.createFieldExistingTest)({ context, fieldName: t.memberExpression(t.identifier(INPUT_PARAM), t.identifier(fieldName)), field, }); } switch (field.parsedType.type) { case "Enum": if (field.rule === "repeated") { return (0, exports.createArrayTypeComparison)({ context, field, fieldName, }); } else { return (0, exports.createFieldExistingTest)({ context, fieldName: t.memberExpression(t.identifier(INPUT_PARAM), t.identifier(fieldName)), field, }); } case "Type": if (field.rule === "repeated") { return (0, exports.createArrayTypeComparison)({ context, field, fieldName, typeComparison: (0, exports.createProtoTypeComparison)({ context, methodName, field, fieldName: t.memberExpression(t.memberExpression(t.identifier(INPUT_PARAM), t.identifier(fieldName)), t.numericLiteral(0), true), }), }); } else { return (0, exports.createProtoTypeComparison)({ context, methodName, fieldName: t.memberExpression(t.identifier(INPUT_PARAM), t.identifier(fieldName)), field, }); } } if (field.rule === "repeated") { return (0, exports.createArrayTypeComparison)({ context, field, fieldName, typeComparison: getScalarExpression({ context, field, fieldName: t.memberExpression(t.memberExpression(t.identifier(INPUT_PARAM), t.identifier(fieldName)), t.numericLiteral(0), true), }), }); } const expr = getScalarExpression({ context, field, fieldName: t.memberExpression(t.identifier(INPUT_PARAM), t.identifier(fieldName)), }); if (expr) { return expr; } throw new Error(`need to implement is (${field.type} rules[${field.rule}] name[${fieldName}])`); }; exports.createFieldTypeComparison = createFieldTypeComparison; const isMethod = (args) => { const { context, name, proto, getFieldName } = args; const methodName = args.methodName ?? "is"; const typeName = getTypeName(name, methodName); const typeUrl = (0, utils_2.getTypeUrl)(context.ref.proto, proto); if (!typeUrl) return; const returnType = t.tsTypeAnnotation(t.tsTypePredicate(t.identifier(INPUT_PARAM), t.tsTypeAnnotation(t.tsTypeReference(t.identifier(typeName))))); const fieldTypesComparison = Object.keys(proto.fields ?? {}).reduce((comparison, fieldName) => { const field = proto.fields[fieldName]; const oneOfs = (0, types_1.getOneOfs)(proto); const isOneOf = oneOfs.includes(fieldName); const isOptional = (0, types_1.getFieldOptionalityForDefaults)(context, field, isOneOf); if (isOptional) { return comparison; } const fieldNameWithCase = getFieldName ? getFieldName(fieldName, field, name, context) : fieldName; const current = (0, exports.createFieldTypeComparison)({ context, methodName, field, fieldName: fieldNameWithCase, }); return comparison ? t.logicalExpression("&&", comparison, current) : current; }, undefined); const typeUrlExpr = t.binaryExpression("===", t.memberExpression(t.identifier(INPUT_PARAM), t.identifier("$typeUrl")), t.memberExpression(t.identifier(name), t.identifier("typeUrl"))); const method = (0, utils_1.objectMethod)("method", t.identifier(methodName), [(0, utils_1.identifier)(INPUT_PARAM, t.tsTypeAnnotation(t.tsAnyKeyword()), false)], t.blockStatement([ t.returnStatement(t.logicalExpression("&&", t.identifier(INPUT_PARAM), fieldTypesComparison ? t.logicalExpression("||", typeUrlExpr, fieldTypesComparison) : typeUrlExpr)), ]), false, false, false, returnType); return method; }; exports.isMethod = isMethod; function getTypeName(typeName, methodName) { switch (methodName) { case "isSDK": return types_2.SymbolNames.SDKType(typeName); case "isAmino": return types_2.SymbolNames.Amino(typeName); case "is": default: return typeName; } }