in src/jsii/fingerprinting.ts [44:147]
private doFingerprint(fqn: string, recursionBreaker: Set<string>) {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const self = this;
const existing = this.cache.get(fqn);
if (existing) {
return existing;
}
const hash = crypto.createHash('sha256');
hash.update(fqn);
const type = this.findType(fqn);
if (type) {
hash.update(type.kind);
switch (type.kind) {
case spec.TypeKind.Enum:
for (const member of sortedByName(type.members)) {
hash.update(member.name);
}
break;
case spec.TypeKind.Class:
case spec.TypeKind.Interface:
if (type.kind === spec.TypeKind.Class) {
visitType(type.base);
visitCallable(type.initializer);
}
for (const prop of sortedByName(type.properties ?? [])) {
hash.update(prop.name);
visitBools(prop.immutable, prop.static, prop.optional, prop.protected);
visitTypeReference(prop.type);
}
for (const method of sortedByName(type.methods ?? [])) {
hash.update(method.name);
visitCallable(method);
visitBools(method.returns?.optional);
visitTypeReference(method.returns?.type);
}
for (const implint of type.interfaces ?? []) {
visitType(implint);
}
break;
}
}
const ret = hash.digest('hex');
this.cache.set(fqn, ret);
return ret;
function visitType(fqnStr?: string) {
if (!fqnStr) {
return;
}
if (recursionBreaker.has(fqnStr)) {
hash.update('$RECURSION$');
return;
}
recursionBreaker.add(fqnStr);
hash.update(self.doFingerprint(fqnStr, recursionBreaker));
recursionBreaker.delete(fqnStr);
}
function visitCallable(callable?: spec.Callable) {
if (!callable) {
return;
}
visitBools(callable.protected);
for (const param of callable.parameters ?? []) {
visitBools(param.optional, param.variadic);
visitTypeReference(param.type);
}
}
function visitTypeReference(typeRef?: spec.TypeReference) {
if (!typeRef) {
return;
}
if (spec.isPrimitiveTypeReference(typeRef)) {
hash.update(typeRef.primitive);
}
if (spec.isNamedTypeReference(typeRef)) {
visitType(typeRef.fqn);
}
if (spec.isCollectionTypeReference(typeRef)) {
hash.update(typeRef.collection.kind);
visitTypeReference(typeRef.collection.elementtype);
}
if (spec.isUnionTypeReference(typeRef)) {
for (const t of typeRef.union.types) {
visitTypeReference(t);
}
}
}
function visitBools(...vs: Array<boolean | undefined>) {
hash.update(vs.map((v) => (v ? '1' : '0')).join(''));
}
}