Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
function isAssignable(actualTypeFqn: string, requiredType: spec.NamedTypeReference, lookup: TypeLookup): boolean {
// The empty object is assignable to everything
if (actualTypeFqn === EMPTY_OBJECT_FQN) { return true; }
if (requiredType.fqn === actualTypeFqn) {
return true;
}
const actualType = lookup(actualTypeFqn);
if (spec.isClassType(actualType)) {
if (actualType.base && isAssignable(actualType.base, requiredType, lookup)) {
return true;
}
}
if (spec.isClassOrInterfaceType(actualType) && actualType.interfaces) {
return actualType.interfaces.find(iface => isAssignable(iface, requiredType, lookup)) != null;
}
return false;
}
function _inehritanceDoesNotChangeContracts(validator: Validator, assembly: spec.Assembly, diagnostic: DiagnosticEmitter) {
for (const type of _allTypes(assembly)) {
if (spec.isClassType(type)) {
for (const method of type.methods ?? []) {
_validateMethodOverride(method, type);
}
for (const property of type.properties ?? []) {
_validatePropertyOverride(property, type);
}
}
if (spec.isClassOrInterfaceType(type) && (type.interfaces?.length ?? 0) > 0) {
for (const method of type.methods ?? []) {
// Overrides "win" over implementations
if (method.overrides) { continue; }
_validateMethodImplementation(method, type);
}
for (const property of type.properties ?? []) {
_validatePropertyImplementation(property, type);
}
}
}
function _validateMethodOverride(method: spec.Method, type: spec.ClassType): boolean {
if (!type.base) { return false; }
const baseType = _dereference(type.base, assembly, validator) as spec.ClassType;
if (!baseType) { return false; }
const overridden = (baseType.methods ?? []).find(m => m.name === method.name);
Object.values(assembly.types).forEach(type => {
emitDocs(type.docs, `${assembly.name}.${type.name}`);
if (spec.isEnumType(type)) {
type.members.forEach(m => emitDocs(m.docs, `${assembly.name}.${type.name}.${m.name}`));
}
if (spec.isClassOrInterfaceType(type)) {
(type.methods ?? []).forEach(m => emitDocs(m.docs, `${assembly.name}.${type.name}#${m.name}`));
(type.properties ?? []).forEach(m => emitDocs(m.docs, `${assembly.name}.${type.name}#${m.name}`));
}
});
}
function _allProperties(assm: spec.Assembly): spec.Property[] {
const properties = new Array();
for (const type of _allTypes(assm)) {
if (!spec.isClassOrInterfaceType(type)) { continue; }
if (!type.properties) { continue; }
type.properties.forEach(property => properties.push(property));
}
return properties;
}
function _allMethods(assm: spec.Assembly): spec.Method[] {
const methods = new Array();
for (const type of _allTypes(assm)) {
if (!spec.isClassOrInterfaceType(type)) { continue; }
if (!type.methods) { continue; }
type.methods.forEach(method => methods.push(method));
}
return methods;
}
function propertiesOf(t: spec.Type, lookup: TypeLookup): {[name: string]: spec.Property} {
if (!spec.isClassOrInterfaceType(t)) { return {}; }
let ret: { [name: string]: spec.Property } = {};
if (t.interfaces) {
for (const iface of t.interfaces) {
ret = { ...ret, ...propertiesOf(lookup(iface), lookup) };
}
}
if (spec.isClassType(t) && t.base) {
ret = { ...ret, ...propertiesOf(lookup(t.base), lookup) };
}
for (const prop of t.properties ?? []) {
ret[prop.name] = prop;
}
function _allTypeReferences(assm: spec.Assembly): spec.NamedTypeReference[] {
const typeReferences = new Array();
for (const type of _allTypes(assm)) {
if (!spec.isClassOrInterfaceType(type)) { continue; }
if (spec.isClassType(type) && type.base) {
typeReferences.push({ fqn: type.base });
}
if (type.interfaces) {
type.interfaces.forEach(iface => typeReferences.push({ fqn: iface }));
}
}
for (const prop of _allProperties(assm)) {
_collectTypeReferences(prop.type);
}
for (const meth of _allMethods(assm)) {
if (meth.returns) {
_collectTypeReferences(meth.returns.type);
}
for (const param of meth.parameters ?? []) {
_collectTypeReferences(param.type);