UNPKG

jsii-pacmak

Version:

A code generation framework for jsii backend languages

220 lines 9.28 kB
"use strict"; 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