Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
public toNativeFqn(fqn: string): string {
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 as spec.ClassType);
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 module does not have a dotnet.namespace setting');
}
if (type.namespace) {
// If the type is declared in an additional namespace.
public toNativeFqn(fqn: string): string {
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 as spec.ClassType);
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 module 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) {
function _isAbstract(symbol: ts.Symbol, declaringType: spec.ClassType | spec.InterfaceType): boolean {
// everything is abstract in interfaces
if (declaringType.kind === spec.TypeKind.Interface) {
return true;
}
return !!symbol.valueDeclaration
&& (ts.getCombinedModifierFlags(symbol.valueDeclaration) & ts.ModifierFlags.Abstract) !== 0;
}
private emitInterfaceProxy(ifc: spec.InterfaceType | spec.ClassType): void {
// No need to slugify for a proxy
const name = `${this.nameutils.convertTypeName(ifc.name)}Proxy`;
const namespace = ifc.namespace ? `${this.assembly.targets!.dotnet!.namespace}.${ifc.namespace}` : this.assembly.targets!.dotnet!.namespace;
const isNested = this.isNested(ifc);
this.openFileIfNeeded(name, namespace, isNested);
this.dotnetDocGenerator.emitDocs(ifc);
this.dotnetRuntimeGenerator.emitAttributesForInterfaceProxy(ifc);
const interfaceFqn = this.typeresolver.toNativeFqn(ifc.fqn);
const suffix = ifc.kind === spec.TypeKind.Interface ? `: DeputyBase, ${interfaceFqn}`
: `: ${interfaceFqn}`;
this.code.openBlock(`internal sealed class ${name} ${suffix}`);
// Create the private constructor
this.code.openBlock(`private ${name}(ByRefValue reference): base(reference)`);
this.code.closeBlock();
// We have already output a member (constructor), setting the first member flag to true
this.flagFirstMemberWritten(true);
const datatype = false;
const proxy = true;
this.emitInterfaceMembersForProxyOrDatatype(ifc, datatype, proxy);
this.code.closeBlock();
this.closeFileIfNeeded(name, namespace, isNested);
private isOptionalPrimitive(optionalValue: spec.OptionalValue | undefined): boolean {
if (!optionalValue || !optionalValue.optional) {
return false;
}
// If the optional type is an enum then we need to flag it as ?
const typeref = optionalValue.type as spec.NamedTypeReference;
let isOptionalEnum = false;
if (typeref && typeref.fqn) {
const type = this.findType(typeref.fqn);
isOptionalEnum = type.kind === spec.TypeKind.Enum;
}
return (spec.isPrimitiveTypeReference(optionalValue.type)
// In .NET, string or object is a reference type, and can be nullable
&& optionalValue.type.primitive !== spec.PrimitiveType.String
&& optionalValue.type.primitive !== spec.PrimitiveType.Any
&& optionalValue.type.primitive !== spec.PrimitiveType.Json) // Json is not a primitive in .NET
|| isOptionalEnum;
}
private emitMethod(cls: spec.ClassType | spec.InterfaceType, method: spec.Method, emitForProxyOrDatatype = false): void {
this.emitNewLineIfNecessary();
const returnType = method.returns ? this.typeresolver.toDotNetType(method.returns.type) : 'void';
let staticKeyWord = '';
let overrideKeyWord = '';
let virtualKeyWord = '';
let definedOnAncestor = false;
// In the case of the source being a class, we check if it is already defined on an ancestor
if (cls.kind === spec.TypeKind.Class) {
definedOnAncestor = this.isMemberDefinedOnAncestor(cls, method);
}
// The method is an override if it's defined on the ancestor, or if the parent is a class and we are generating a proxy or datatype class
let overrides = definedOnAncestor || (cls.kind === spec.TypeKind.Class && emitForProxyOrDatatype);
// We also inspect the jsii model to see if it overrides a class member.
if (method.overrides) {
const overrideType = this.findType(method.overrides);
if (overrideType.kind === spec.TypeKind.Class) {
// Overrides a class, needs overrides keyword
overrides = true;
}
}
if (method.static) {
staticKeyWord = 'static ';
} else if (overrides) {
// Add the override key word if the method is emitted for a proxy or data type or is defined on an ancestor
private _findCtor(fqn: string, args: any[]): { ctor: any, parameters?: spec.Parameter[] } {
if (fqn === wire.EMPTY_OBJECT_FQN) {
return { ctor: Object };
}
const typeinfo = this._typeInfoForFqn(fqn);
switch (typeinfo.kind) {
case spec.TypeKind.Class:
const classType = typeinfo as spec.ClassType;
this._validateMethodArguments(classType.initializer, args);
return { ctor: this._findSymbol(fqn), parameters: classType.initializer && classType.initializer.parameters };
case spec.TypeKind.Interface:
throw new Error(`Cannot create an object with an FQN of an interface: ${fqn}`);
default:
throw new Error(`Unexpected FQN kind: ${fqn}`);
}
}
const flags = ts.getCombinedModifierFlags(decl);
if (flags & ts.ModifierFlags.Const) {
this._diagnostic(decl,
ts.DiagnosticCategory.Error,
"Exported enum cannot be declared 'const'");
}
const docs = this._visitDocumentation(symbol, ctx);
const typeContext = ctx.replaceStability(docs?.stability);
const members = type.isUnion() ? type.types : [type];
const jsiiType: spec.EnumType = {
assembly: this.projectInfo.name,
fqn: `${[this.projectInfo.name, ...ctx.namespace].join('.')}.${symbol.name}`,
kind: spec.TypeKind.Enum,
members: members.map(m => ({
name: m.symbol.name,
docs: this._visitDocumentation(m.symbol, typeContext),
})),
name: symbol.name,
namespace: ctx.namespace.length > 0 ? ctx.namespace.join('.') : undefined,
docs
};
return Promise.resolve(jsiiType);
}