in desktop/plugins/public/leak_canary/processLeakString.tsx [157:254]
function processLeak(output: Leak[], leakInfo: string): Leak[] {
const lines = leakInfo.split('\n');
// Elements shows a Object's classname and package, wheras elementsSimple shows
// just its classname
const elements = new Map<string, Element>();
const elementsSimple = new Map<string, Element>();
let rootElementId = '';
let i = 0;
while (i < lines.length && !lines[i].endsWith(LEAK_BEGIN_INDICATOR)) {
i++;
}
i++;
if (i >= lines.length) {
return output;
}
let elementId = 0;
let elementIdStr = String(elementId);
// Last element is leaked object
let leakedObjName = '';
while (i < lines.length && lines[i].startsWith('*')) {
const line = lines[i];
const prevElementIdStr = String(elementId - 1);
if (elementId !== 0) {
// Add element to previous element's children
safeAddChildElementId(elementIdStr, prevElementIdStr, elements);
safeAddChildElementId(elementIdStr, prevElementIdStr, elementsSimple);
} else {
rootElementId = elementIdStr;
}
const element = getElementSimple(line, elementIdStr);
leakedObjName = element.name;
elements.set(elementIdStr, element);
elementsSimple.set(elementIdStr, element);
i++;
elementId++;
elementIdStr = String(elementId);
}
while (
i < lines.length &&
!lines[i].startsWith(RETAINED_SIZE_INDICATOR) &&
!lines[i].startsWith(BEGIN_DETAILS_SECTION_INDICATOR)
) {
i++;
}
let retainedSize = 'unknown size';
if (lines[i].startsWith(RETAINED_SIZE_INDICATOR)) {
const match = lines[i].match(/\* Retaining: (.*)./);
if (match) {
retainedSize = match[1];
}
}
while (
i < lines.length &&
!lines[i].startsWith(BEGIN_DETAILS_SECTION_INDICATOR)
) {
i++;
}
i++;
// Parse information on each object's fields, package
const {staticFields, instanceFields, packages} = generateFieldsList(lines, i);
// While elementsSimple remains as-is, elements has the package of each class
// inserted, in order to enable 'Show full class path'
for (const [elementId, pkg] of packages.entries()) {
const element = elements.get(elementId);
if (!element) {
continue;
}
// Gets everything before the field name, which is replaced by the package
const match = element.name.match(/([^\. ]*)(.*)/);
if (match && match.length === 3) {
element.name = pkg + match[2];
}
}
output.push({
title: leakedObjName,
root: rootElementId,
elements: toObjectMap(elements),
elementsSimple: toObjectMap(elementsSimple),
staticFields: toObjectMap(staticFields, true),
instanceFields: toObjectMap(instanceFields, true),
retainedSize: retainedSize,
});
return output;
}