Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
public static toNativeReference(type: spec.Type) {
const [, ...name] = type.fqn.split('.');
const resolvedName = name.join('.');
const result: { typescript: string, javascript?: string } = {
typescript: `import { ${resolvedName} } from '${type.assembly}';`
};
if (!spec.isInterfaceType(type)) {
result.javascript = `const { ${resolvedName} } = require('${type.assembly}');`;
} else {
result.javascript = `// ${resolvedName} is an interface`;
}
return result;
}
private _tryTypeInfoForProperty(property: string, classFqn: string, interfaces: string[] = []): spec.Property | undefined {
for (const fqn of [classFqn, ...interfaces]) {
if (fqn === wire.EMPTY_OBJECT_FQN) { continue; }
const typeInfo = this._typeInfoForFqn(fqn);
let properties;
let bases;
if (spec.isClassType(typeInfo)) {
const classTypeInfo = typeInfo as spec.ClassType;
properties = classTypeInfo.properties;
bases = classTypeInfo.base ? [classTypeInfo.base] : [];
} else if (spec.isInterfaceType(typeInfo)) {
const interfaceTypeInfo = typeInfo as spec.InterfaceType;
properties = interfaceTypeInfo.properties;
bases = interfaceTypeInfo.interfaces ?? [];
} else {
throw new Error(`Type of kind ${typeInfo.kind} does not have properties`);
}
for (const p of properties ?? []) {
if (p.name === property) {
return p;
}
}
// recurse to parent type (if exists)
for (const baseFqn of bases) {
const ret = this._tryTypeInfoForProperty(property, baseFqn);
this._deferUntilTypesAvailable(fqn, jsiiType.interfaces ?? [], type.symbol.valueDeclaration, (...bases: spec.Type[]) => {
if ((jsiiType.methods ?? []).length === 0) {
jsiiType.datatype = true;
}
for (const base of bases) {
if (spec.isInterfaceType(base) && !base.datatype) {
jsiiType.datatype = undefined;
}
}
const interfaceName = isInterfaceName(jsiiType.name);
// If it's not a datatype the name must start with an "I".
if (!jsiiType.datatype && !interfaceName) {
this._diagnostic(type.symbol.declarations[0],
ts.DiagnosticCategory.Error,
`Interface contains behavior: name should be "I${jsiiType.name}"`);
}
// If the name starts with an "I" it is not intended as a datatype, so switch that off.
if (jsiiType.datatype && interfaceName) {
jsiiType.datatype = undefined;
if (jsiiType.datatype) {
for (const prop of jsiiType.properties ?? []) {
if (!prop.immutable) {
const p = type.getProperty(prop.name)!;
this._diagnostic(p.valueDeclaration,
ts.DiagnosticCategory.Error,
`The property '${prop.name}' in data type '${jsiiType.name}' must be 'readonly' since data is passed by-value`);
// force property to be "readonly" since jsii languages will pass this by-value
prop.immutable = true;
}
}
} else {
// This is *NOT* a data type, so it may not extend something that is one.
for (const base of bases) {
if (!spec.isInterfaceType(base)) {
// Invalid type we already warned about earlier, just ignoring it here...
continue;
}
if (base.datatype) {
this._diagnostic(type.symbol.valueDeclaration,
ts.DiagnosticCategory.Error,
`Attempted to extend struct ${base.fqn} from regular interface ${jsiiType.fqn}`);
}
}
}
});
this._deferUntilTypesAvailable(symbol.name, [lastParamTypeRef], lastParamSymbol!.declarations[0], (lastParamType) => {
if (!spec.isInterfaceType(lastParamType) || !lastParamType.datatype) { return; }
// Liftable datatype, make sure no parameter names match any of the properties in the datatype
const propNames = this.allProperties(lastParamType);
const paramNames = new Set(parameters.slice(0, parameters.length - 1).map(x => x.name));
const sharedNames = intersection(propNames, paramNames);
if (sharedNames.size > 0) {
this._diagnostic(
declaration,
ts.DiagnosticCategory.Error,
`Name occurs in both function arguments and in datatype properties, rename one: ${Array.from(sharedNames).join(', ')}`);
}
});
}
function recurse(this: Assembler, int: spec.InterfaceType) {
for (const property of int.properties ?? []) {
ret.add(property.name);
}
for (const baseRef of int.interfaces ?? []) {
const base = this._dereference(baseRef, null);
if (!base) { throw new Error('Impossible to have unresolvable base in allProperties()'); }
if (!spec.isInterfaceType(base)) { throw new Error('Impossible to have non-interface base in allProperties()'); }
recurse.call(this, base);
}
}
}
this._deferUntilTypesAvailable(fqn, [typeRef], decl, (deref) => {
if (!spec.isInterfaceType(deref)) {
this._diagnostic(decl,
ts.DiagnosticCategory.Error,
`Inheritance clause of ${fqn} uses ${spec.describeTypeReference(typeRef)} as an interface`);
}
});