jsii-pacmak
Version:
A code generation framework for jsii backend languages
211 lines • 6.89 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GoTypeRef = void 0;
const log = require("../../../logging");
/*
* Maps names of JS primitives to corresponding Go types as strings
*/
class PrimitiveMapper {
constructor(name) {
this.name = name;
this.MAP = {
number: 'float64',
boolean: 'bool',
any: 'interface{}',
date: 'time.Time',
string: 'string',
json: `map[string]interface{}`,
};
}
get goPrimitive() {
const val = this.MAP[this.name];
if (!val) {
log.debug(`Unmapped primitive type: ${this.name}`);
}
return val ?? this.name;
}
}
/*
* Accepts a JSII TypeReference and Go Package and can resolve the GoType within the module tree.
*/
class GoTypeRef {
constructor(root, reference, options = {
opaqueUnionTypes: true,
}) {
this.root = root;
this.reference = reference;
this.options = options;
}
get type() {
if (this.reference.fqn) {
return this.root.findType(this.reference.fqn);
}
return undefined;
}
get specialDependencies() {
return {
fmt: false,
init: false,
internal: false,
runtime: false,
time: containsDate(this.reference, this.options.opaqueUnionTypes),
};
function containsDate(ref, opaqueUnionType) {
if (ref.primitive === 'date') {
return true;
}
if (ref.arrayOfType) {
return containsDate(ref.arrayOfType, opaqueUnionType);
}
if (ref.mapOfType) {
return containsDate(ref.mapOfType, opaqueUnionType);
}
if (!opaqueUnionType && ref.unionOfTypes) {
return ref.unionOfTypes.some((item) => containsDate(item, opaqueUnionType));
}
return false;
}
}
get primitiveType() {
if (this.reference.primitive) {
return new PrimitiveMapper(this.reference.primitive).goPrimitive;
}
return undefined;
}
get name() {
return this.type?.name;
}
get datatype() {
const reflectType = this.type?.type;
return reflectType?.isInterfaceType() && reflectType.datatype;
}
get namespace() {
return this.type?.namespace;
}
get void() {
return this.reference.void;
}
get typeMap() {
if (!this._typeMap) {
this._typeMap = this.buildTypeMap(this);
}
return this._typeMap;
}
/**
* The go `import`s required in order to be able to use this type in code.
*/
get dependencies() {
const ret = new Array();
switch (this.typeMap.type) {
case 'interface':
if (this.type?.pkg) {
ret.push(this.type.pkg);
}
break;
case 'array':
case 'map':
ret.push(...this.typeMap.value.dependencies);
break;
case 'union':
if (!this.options.opaqueUnionTypes) {
for (const t of this.typeMap.value) {
ret.push(...t.dependencies);
}
}
break;
case 'void':
case 'primitive':
break;
}
return ret;
}
get unionOfTypes() {
const typeMap = this.typeMap;
if (typeMap.type !== 'union') {
return undefined;
}
return typeMap.value;
}
get withTransparentUnions() {
if (!this.options.opaqueUnionTypes) {
return this;
}
return new GoTypeRef(this.root, this.reference, {
...this.options,
opaqueUnionTypes: false,
});
}
/*
* Return the name of a type for reference from the `Package` passed in
*/
scopedName(scope) {
return this.scopedTypeName(this.typeMap, scope);
}
scopedReference(scope) {
return this.scopedTypeName(this.typeMap, scope, true);
}
buildTypeMap(ref) {
if (ref.primitiveType) {
return { type: 'primitive', value: ref.primitiveType };
}
else if (ref.reference.arrayOfType) {
return {
type: 'array',
value: new GoTypeRef(this.root, ref.reference.arrayOfType, this.options),
};
}
else if (ref.reference.mapOfType) {
return {
type: 'map',
value: new GoTypeRef(this.root, ref.reference.mapOfType, this.options),
};
}
else if (ref.reference.unionOfTypes) {
return {
type: 'union',
value: ref.reference.unionOfTypes.map((typeRef) => new GoTypeRef(this.root, typeRef, this.options)),
};
}
else if (ref.reference.void) {
return { type: 'void' };
}
return { type: 'interface', value: ref };
}
scopedTypeName(typeMap, scope, asRef = false) {
if (typeMap.type === 'primitive') {
const { value } = typeMap;
const prefix = asRef && value !== 'interface{}' ? '*' : '';
return `${prefix}${value}`;
}
else if (typeMap.type === 'array' || typeMap.type === 'map') {
const prefix = asRef ? '*' : '';
const wrapper = typeMap.type === 'array' ? '[]' : 'map[string]';
const innerName = this.scopedTypeName(typeMap.value.typeMap, scope, asRef) ??
'interface{}';
return `${prefix}${wrapper}${innerName}`;
}
else if (typeMap.type === 'interface') {
const prefix = asRef && typeMap.value.datatype ? '*' : '';
const baseName = typeMap.value.name;
// type is defined in the same scope as the current one, no namespace required
if (scope.packageName === typeMap.value.namespace && baseName) {
// if the current scope is the same as the types scope, return without a namespace
return `${prefix}${baseName}`;
}
// type is defined in another module and requires a namespace and import
if (baseName) {
return `${prefix}${typeMap.value.namespace}.${baseName}`;
}
}
else if (typeMap.type === 'union') {
return 'interface{}';
}
else if (typeMap.type === 'void') {
return '';
}
// type isn't handled
throw new Error(`Type ${typeMap.value?.name} does not resolve to a known Go type.`);
}
}
exports.GoTypeRef = GoTypeRef;
//# sourceMappingURL=go-type-reference.js.map