in sqlite/src/blobStore.ts [391:462]
private computeHash(): string {
const hash = crypto.createHash('md5');
hash.update(this.blob.contents);
const options: CompressorOptions = { mode: 'hash' };
const compressor = assertDefined(Compressor.getVertexCompressor(VertexLabels.range));
const rangeHashes: Map<Id, string> = new Map();
for (let key of Object.keys(this.blob.ranges)) {
const range = this.blob.ranges[key];
const rangeHash = crypto.createHash('md5').update(JSON.stringify(compressor.compress(range, options), undefined, 0)).digest('base64');
rangeHashes.set(Number(key), rangeHash);
}
for (let item of Array.from(rangeHashes.values()).sort(Strings.compare)) {
hash.update(item);
}
// moniker
if (this.blob.monikers !== undefined) {
const monikers = LiteralMap.values(this.blob.monikers).sort(Monikers.compare);
const compressor = assertDefined(Compressor.getVertexCompressor(VertexLabels.moniker));
for (let moniker of monikers) {
const compressed = compressor.compress(moniker, options);
hash.update(JSON.stringify(compressed, undefined, 0));
}
}
// Assume that folding ranges are already sorted
if (this.blob.foldingRanges) {
const compressor = foldingRangeCompressor;
for (let range of this.blob.foldingRanges) {
const compressed = compressor.compress(range, options);
hash.update(JSON.stringify(compressed, undefined, 0));
}
}
// Unsure if we need to sort the children by range or not?
if (this.blob.documentSymbols && this.blob.documentSymbols.length > 0) {
const first = this.blob.documentSymbols[0];
const compressor = lsp.DocumentSymbol.is(first) ? undefined : assertDefined(Compressor.getVertexCompressor(VertexLabels.range));
if (compressor === undefined) {
throw new Error(`Document symbol compression not supported`);
}
const inline = (result: any[], value: RangeBasedDocumentSymbol) => {
const item: any[] = [];
const rangeHash = assertDefined(rangeHashes.get(value.id));
item.push(rangeHash);
if (value.children && value.children.length > 0) {
const children: any[] = [];
for (let child of value.children) {
inline(children, child);
}
item.push(children);
}
result.push(item);
};
let compressed: any[] = [];
for (let symbol of (this.blob.documentSymbols as RangeBasedDocumentSymbol[])) {
inline(compressed, symbol);
}
hash.update(JSON.stringify(compressed, undefined, 0));
}
// Diagnostics
if (this.blob.diagnostics && this.blob.diagnostics.length > 0) {
this.blob.diagnostics = this.blob.diagnostics.sort(Diagnostics.compare);
const compressor = diagnosticCompressor;
for (let diagnostic of this.blob.diagnostics) {
let compressed = compressor.compress(diagnostic, options);
hash.update(JSON.stringify(compressed, undefined, 0));
}
}
return hash.digest('base64');
}