mirror of
https://github.com/github/codeql-action.git
synced 2025-12-28 10:10:17 +08:00
Co-authored-by: Andrew Eisenberg <aeisenberg@github.com> Co-authored-by: Henry Mercer <henrymercer@github.com>
160 lines
7.0 KiB
JavaScript
160 lines
7.0 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.FieldInfoGenerator = void 0;
|
|
const rt = require("@protobuf-ts/runtime");
|
|
const ts = require("typescript");
|
|
const plugin_framework_1 = require("@protobuf-ts/plugin-framework");
|
|
/**
|
|
* Generates TypeScript code for runtime field information,
|
|
* from runtime field information.
|
|
*/
|
|
class FieldInfoGenerator {
|
|
constructor(registry, imports, options) {
|
|
this.registry = registry;
|
|
this.imports = imports;
|
|
this.options = options;
|
|
}
|
|
createFieldInfoLiterals(source, fieldInfos) {
|
|
fieldInfos = fieldInfos.map(fi => FieldInfoGenerator.denormalizeFieldInfo(fi));
|
|
return ts.createArrayLiteral(fieldInfos.map(fi => this.createFieldInfoLiteral(source, fi)), true);
|
|
}
|
|
createFieldInfoLiteral(source, fieldInfo) {
|
|
fieldInfo = FieldInfoGenerator.denormalizeFieldInfo(fieldInfo);
|
|
let properties = [];
|
|
// no: The field number of the .proto field.
|
|
// name: The original name of the .proto field.
|
|
// kind: discriminator
|
|
// localName: The name of the field in the runtime.
|
|
// jsonName: The name of the field in JSON.
|
|
// oneof: The name of the `oneof` group, if this field belongs to one.
|
|
for (let key of ["no", "name", "kind", "localName", "jsonName", "oneof"]) {
|
|
if (fieldInfo[key] !== undefined) {
|
|
properties.push(ts.createPropertyAssignment(key, plugin_framework_1.typescriptLiteralFromValue(fieldInfo[key])));
|
|
}
|
|
}
|
|
// repeat: Is the field repeated?
|
|
if (fieldInfo.repeat !== undefined) {
|
|
properties.push(ts.createPropertyAssignment("repeat", this.createRepeatType(fieldInfo.repeat)));
|
|
}
|
|
// opt: Is the field optional?
|
|
if (fieldInfo.opt !== undefined) {
|
|
properties.push(ts.createPropertyAssignment("opt", plugin_framework_1.typescriptLiteralFromValue(fieldInfo.opt)));
|
|
}
|
|
switch (fieldInfo.kind) {
|
|
case "scalar":
|
|
// T: Scalar field type.
|
|
properties.push(ts.createPropertyAssignment("T", this.createScalarType(fieldInfo.T)));
|
|
// L?: JavaScript long type
|
|
if (fieldInfo.L !== undefined) {
|
|
properties.push(ts.createPropertyAssignment("L", this.createLongType(fieldInfo.L)));
|
|
}
|
|
break;
|
|
case "enum":
|
|
// T: Return enum field type info.
|
|
properties.push(ts.createPropertyAssignment(ts.createIdentifier('T'), this.createEnumT(source, fieldInfo.T())));
|
|
break;
|
|
case "message":
|
|
// T: Return message field type handler.
|
|
properties.push(ts.createPropertyAssignment(ts.createIdentifier('T'), this.createMessageT(source, fieldInfo.T())));
|
|
break;
|
|
case "map":
|
|
// K: Map field key type.
|
|
properties.push(ts.createPropertyAssignment("K", this.createScalarType(fieldInfo.K)));
|
|
// V: Map field value type.
|
|
properties.push(ts.createPropertyAssignment("V", this.createMapV(source, fieldInfo.V)));
|
|
break;
|
|
}
|
|
// options:
|
|
if (fieldInfo.options) {
|
|
properties.push(ts.createPropertyAssignment(ts.createIdentifier('options'), plugin_framework_1.typescriptLiteralFromValue(fieldInfo.options)));
|
|
}
|
|
return ts.createObjectLiteral(properties, false);
|
|
}
|
|
/**
|
|
* Creates the interface field / oneof name based on original proto field name and naming options.
|
|
*/
|
|
static createTypescriptLocalName(name, options) {
|
|
return options.useProtoFieldName ? name : rt.lowerCamelCase(name);
|
|
}
|
|
/**
|
|
* Turn normalized field info returned by normalizeFieldInfo() back into
|
|
* the minimized form.
|
|
*/
|
|
static denormalizeFieldInfo(info) {
|
|
let partial = Object.assign({}, info);
|
|
if (info.jsonName === rt.lowerCamelCase(info.name)) {
|
|
delete partial.jsonName;
|
|
}
|
|
if (info.localName === rt.lowerCamelCase(info.name)) {
|
|
delete partial.localName;
|
|
}
|
|
if (info.repeat === rt.RepeatType.NO) {
|
|
delete partial.repeat;
|
|
}
|
|
if (info.opt === false) {
|
|
delete partial.opt;
|
|
}
|
|
else if (info.opt === true && info.kind == "message") {
|
|
delete partial.opt;
|
|
}
|
|
return partial;
|
|
}
|
|
createMessageT(source, type) {
|
|
let descriptor = this.registry.resolveTypeName(type.typeName);
|
|
let generatedMessage = this.imports.type(source, descriptor);
|
|
return ts.createArrowFunction(undefined, undefined, [], undefined, ts.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.createIdentifier(generatedMessage));
|
|
}
|
|
createEnumT(source, ei) {
|
|
let [pbTypeName, , sharedPrefix] = ei, descriptor = this.registry.resolveTypeName(pbTypeName), generatedEnum = this.imports.type(source, descriptor), enumInfoLiteral = [
|
|
ts.createStringLiteral(pbTypeName),
|
|
ts.createIdentifier(generatedEnum),
|
|
];
|
|
if (sharedPrefix) {
|
|
enumInfoLiteral.push(ts.createStringLiteral(sharedPrefix));
|
|
}
|
|
return ts.createArrowFunction(undefined, undefined, [], undefined, ts.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.createArrayLiteral(enumInfoLiteral, false));
|
|
}
|
|
createRepeatType(type) {
|
|
const expr = ts.createNumericLiteral(type.toString());
|
|
ts.addSyntheticTrailingComment(expr, ts.SyntaxKind.MultiLineCommentTrivia, `RepeatType.${rt.RepeatType[type]}`);
|
|
return expr;
|
|
}
|
|
createScalarType(type) {
|
|
const expr = ts.createNumericLiteral(type.toString());
|
|
ts.addSyntheticTrailingComment(expr, ts.SyntaxKind.MultiLineCommentTrivia, `ScalarType.${rt.ScalarType[type]}`);
|
|
return expr;
|
|
}
|
|
createLongType(type) {
|
|
const expr = ts.createNumericLiteral(type.toString());
|
|
ts.addSyntheticTrailingComment(expr, ts.SyntaxKind.MultiLineCommentTrivia, `LongType.${rt.LongType[type]}`);
|
|
return expr;
|
|
}
|
|
// V: Map field value type.
|
|
createMapV(source, mapV) {
|
|
let T;
|
|
let L = undefined;
|
|
switch (mapV.kind) {
|
|
case "message":
|
|
T = this.createMessageT(source, mapV.T());
|
|
break;
|
|
case "enum":
|
|
T = this.createEnumT(source, mapV.T());
|
|
break;
|
|
case "scalar":
|
|
T = this.createScalarType(mapV.T);
|
|
if (mapV.L !== undefined)
|
|
L = this.createLongType(mapV.L);
|
|
break;
|
|
}
|
|
const properties = [
|
|
ts.createPropertyAssignment(ts.createIdentifier('kind'), ts.createStringLiteral(mapV.kind)),
|
|
ts.createPropertyAssignment(ts.createIdentifier('T'), T)
|
|
];
|
|
if (L) {
|
|
properties.push(ts.createPropertyAssignment(ts.createIdentifier('L'), L));
|
|
}
|
|
return ts.createObjectLiteral(properties);
|
|
}
|
|
}
|
|
exports.FieldInfoGenerator = FieldInfoGenerator;
|