jsii-pacmak
Version:
A code generation framework for jsii backend languages
220 lines • 9.28 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.DotNetTypeResolver = void 0;
const spec = require("@jsii/spec");
const codemaker_1 = require("codemaker");
const filegenerator_1 = require("./filegenerator");
const nameutils_1 = require("./nameutils");
class DotNetTypeResolver {
constructor(assembly, findModule, findType, assembliesCurrentlyBeingCompiled) {
this.assembliesCurrentlyBeingCompiled = assembliesCurrentlyBeingCompiled;
// The dependency tree for the current jsii input model.
// This is later used to output the csproj
this.namespaceDependencies = new Map();
this.nameutils = new nameutils_1.DotNetNameUtils();
this.assembly = assembly;
this.findModule = findModule;
this.findType = findType;
}
/**
* Translates a type fqn to a native .NET full type
*/
toNativeFqn(fqn) {
const type = this.findType(fqn);
let typeName = '';
switch (type.kind) {
case spec.TypeKind.Interface:
typeName = this.nameutils.convertInterfaceName(type);
break;
case spec.TypeKind.Class:
typeName = this.nameutils.convertClassName(type);
break;
case spec.TypeKind.Enum:
typeName = this.nameutils.convertTypeName(type.name);
break;
default:
throw new Error(`Unknown type: ${type}`);
}
const [mod] = fqn.split('.');
const depMod = this.findModule(mod);
const dotnetNamespace = depMod.targets?.dotnet?.namespace;
if (!dotnetNamespace) {
throw new Error(`The assembly ${mod} does not have a dotnet.namespace setting`);
}
if (type.namespace) {
// If the type is declared in an additional namespace.
const namespaceFqn = `${this.assembly.name}.${type.namespace}`;
const associatedNamespace = this.assembly.types?.[namespaceFqn];
if (associatedNamespace) {
// Checking if there is a C# type associated with this namespace, in case we need to slugify it
const actualNamespace = this.toDotNetType(this.findType(namespaceFqn));
return `${actualNamespace}.${typeName}`;
}
const ns = this.resolveNamespace(depMod, mod, type.namespace);
return `${ns}.${typeName}`;
}
// When undefined, the type is located at the root of the assembly
return `${dotnetNamespace}.${typeName}`;
}
/**
* Resolves the namespaces dependencies by looking at the .jsii model
*/
resolveNamespacesDependencies() {
const assmDependencies = this.assembly.dependencies ?? {};
const assmConfigurations = this.assembly.dependencyClosure ?? {};
for (const [depName, version] of Object.entries(assmDependencies)) {
const depInfo = assmConfigurations[depName];
if (!this.namespaceDependencies.has(depName)) {
const dotnetInfo = depInfo.targets.dotnet;
const namespace = dotnetInfo.namespace;
const packageId = dotnetInfo.packageId;
const suffix = depInfo.targets.dotnet.versionSuffix;
this.namespaceDependencies.set(depName, new filegenerator_1.DotNetDependency(namespace, packageId, depName,
// suffix, when present, is guaranteed to start with a leading `-`
suffix ? `${version}${suffix}` : version, this.assembliesCurrentlyBeingCompiled.includes(depName)));
}
}
}
/**
* Loops through the implemented interfaces and returns the fully qualified .NET types of the interfaces
*
*/
resolveImplementedInterfaces(ifc) {
const interfaces = ifc.interfaces ?? [];
const baseTypeNames = [];
// For all base members
for (const base of interfaces) {
const interfaceFullType = this.toNativeFqn(base);
baseTypeNames.push(interfaceFullType);
}
return baseTypeNames;
}
/**
* Translates any jsii type to its corresponding .NET type
*/
toDotNetType(typeref) {
if (spec.isPrimitiveTypeReference(typeref)) {
return this.toDotNetPrimitive(typeref.primitive);
}
else if (spec.isCollectionTypeReference(typeref)) {
return this.toDotNetCollection(typeref);
}
else if (spec.isNamedTypeReference(typeref)) {
return this.toNativeFqn(typeref.fqn);
}
else if (typeref.union) {
return 'object';
}
throw new Error(`Invalid type reference: ${JSON.stringify(typeref)}`);
}
/**
* Translates any jsii type to the name of its corresponding .NET type (as a .NET string).
*/
toDotNetTypeName(typeref) {
if (spec.isPrimitiveTypeReference(typeref)) {
return this.toDotNetPrimitiveName(typeref.primitive);
}
else if (spec.isCollectionTypeReference(typeref)) {
return this.toDotNetCollectionName(typeref);
}
else if (spec.isNamedTypeReference(typeref)) {
return `typeof(${this.toNativeFqn(typeref.fqn)}).FullName`;
}
else if (typeref.union) {
return '"object"';
}
throw new Error(`Invalid type reference: ${JSON.stringify(typeref)}`);
}
resolveNamespace(assm, assmName, ns) {
let resolved = assm.targets?.dotnet?.namespace;
if (!resolved) {
throw new Error(`Assembly ${assmName} does not have targets.dotnet.namespace configured!`);
}
const segments = ns.split('.');
for (let i = 0; i < segments.length; i++) {
const submoduleName = `${assmName}.${segments.slice(0, i + 1).join('.')}`;
const submodule = assm.submodules?.[submoduleName];
if (submodule && submodule.targets?.dotnet?.namespace) {
resolved = submodule.targets.dotnet.namespace;
}
else {
resolved = `${resolved}.${(0, codemaker_1.toPascalCase)(segments[i])}`;
}
}
return resolved;
}
/**
* Translates a primitive in jsii to a native .NET primitive
*/
toDotNetPrimitive(primitive) {
switch (primitive) {
case spec.PrimitiveType.Boolean:
return 'bool';
case spec.PrimitiveType.Date:
return 'System.DateTime';
case spec.PrimitiveType.Json:
return 'Newtonsoft.Json.Linq.JObject';
case spec.PrimitiveType.Number:
return 'double';
case spec.PrimitiveType.String:
return 'string';
case spec.PrimitiveType.Any:
return 'object';
default:
throw new Error(`Unknown primitive type: ${primitive}`);
}
}
/**
* Translates a primitive in jsii to the name of a native .NET primitive
*/
toDotNetPrimitiveName(primitive) {
switch (primitive) {
case spec.PrimitiveType.Boolean:
return '"bool"';
case spec.PrimitiveType.Date:
return 'typeof(System.DateTime).FullName';
case spec.PrimitiveType.Json:
return 'typeof(Newtonsoft.Json.Linq.JObject).FullName';
case spec.PrimitiveType.Number:
return '"double"';
case spec.PrimitiveType.String:
return '"string"';
case spec.PrimitiveType.Any:
return '"object"';
default:
throw new Error(`Unknown primitive type: ${primitive}`);
}
}
/**
* Translates a collection in jsii to a native .NET collection
*/
toDotNetCollection(ref) {
const elementDotNetType = this.toDotNetType(ref.collection.elementtype);
switch (ref.collection.kind) {
case spec.CollectionKind.Array:
return `${elementDotNetType}[]`;
case spec.CollectionKind.Map:
return `System.Collections.Generic.IDictionary<string, ${elementDotNetType}>`;
default:
throw new Error(`Unsupported collection kind: ${ref.collection.kind}`);
}
}
/**
* Translates a collection in jsii to the name of a native .NET collection
*/
toDotNetCollectionName(ref) {
const [_, dollar, quote, content] = /^(?:(\$)?("))?([^"]+)"?$/.exec(this.toDotNetTypeName(ref.collection.elementtype));
const interpolates = dollar || !quote ? '$' : '';
const elementTypeName = quote ? content : `{${content}}`;
switch (ref.collection.kind) {
case spec.CollectionKind.Array:
return `${interpolates}"${elementTypeName}[]"`;
case spec.CollectionKind.Map:
return `${interpolates}"System.Collections.Generic.IDictionary<string, ${elementTypeName}>"`;
default:
throw new Error(`Unsupported collection kind: ${ref.collection.kind}`);
}
}
}
exports.DotNetTypeResolver = DotNetTypeResolver;
//# sourceMappingURL=dotnettyperesolver.js.map
;