Dependencies file: add size as attributes

Summary:
Adds module size as `fb_`-prefixed node attributes to the digraph output of dependencies.

The list of edges is now followed by a list of node declarations, that use the `fb_size` attribute to expose the module size in bytes.

E.g:

```
digraph {
	"a" -> "b";
	"b" -> "c";
	"a"[fb_size=123];
	"b"[fb_size=456];
	"c"[fb_size=789];
}

```

Reviewed By: fkgozali

Differential Revision: D6064861

fbshipit-source-id: 73127e08c5e38075b5112053de12f9abac1102ee
This commit is contained in:
David Aurelio 2017-10-17 03:40:50 -07:00 committed by Facebook Github Bot
parent 4903fc6a04
commit 86ffdae347
2 changed files with 60 additions and 21 deletions

View File

@ -28,7 +28,7 @@ expect.extend({
return {
pass: received === built,
message: `Expected ${received} to equal ${built}`,
message: () => `Expected ${received} to equal ${built}`,
};
},
});
@ -42,56 +42,85 @@ describe('dependencies-dot', () => {
});
it('produces an ordered file for a standard list of modules', () => {
expect(
dependenciesDot({
modules: [
const modules = [
createModule('a', ['b']),
createModule('b', ['c']),
createModule('c', []),
],
}),
).toBeAMultilineString('digraph {', '\t"a" -> "b";', '\t"b" -> "c";', '}');
];
expect(dependenciesDot({modules})).toBeAMultilineString(
'digraph {',
'\t"a" -> "b";',
'\t"b" -> "c";',
...metadata(modules),
'}',
);
});
it('writes one entry per dependency', () => {
expect(
dependenciesDot({
modules: [
const modules = [
createModule('a', ['b', 'c']),
createModule('b', ['d']),
createModule('c', []),
createModule('d', []),
],
];
expect(
dependenciesDot({
modules,
}),
).toBeAMultilineString(
'digraph {',
'\t"a" -> "b";',
'\t"a" -> "c";',
'\t"b" -> "d";',
...metadata(modules),
'}',
);
});
it('handles non-printable characters', () => {
const modules = [createModule('"\n', ['\r\t']), createModule('\r\t', [])];
expect(
dependenciesDot({
modules: [createModule('"\n', ['\r\t']), createModule('\r\t', [])],
modules,
}),
).toBeAMultilineString('digraph {', '\t"\\"\\n" -> "\\r\\t";', '}');
).toBeAMultilineString(
'digraph {',
'\t"\\"\\n" -> "\\r\\t";',
...metadata(modules),
'}',
);
});
it('handles circular dependencies', () => {
const modules = [createModule('a', ['b']), createModule('b', ['a'])];
expect(
dependenciesDot({
modules: [createModule('a', ['b']), createModule('b', ['a'])],
modules,
}),
).toBeAMultilineString('digraph {', '\t"a" -> "b";', '\t"b" -> "a";', '}');
).toBeAMultilineString(
'digraph {',
'\t"a" -> "b";',
'\t"b" -> "a";',
...metadata(modules),
'}',
);
});
});
function createModule(path: string, deps: Array<string>) {
return {
file: {code: '', map: null, path, type: 'module'},
file: {
code: `var path = ${JSON.stringify(path)};`,
map: null,
path,
type: 'module',
},
dependencies: deps.map(d => ({id: d, path: d})),
};
}
function metadata(modules) {
return modules.map(
m => `\t${JSON.stringify(m.file.path)}[fb_size=${m.file.code.length}];`,
);
}

View File

@ -20,15 +20,25 @@ function dependenciesDot({modules}: {+modules: Iterable<Module>}) {
// Opening digraph.
list.push('digraph {');
const meta: Map<string, string> = new Map();
// Adding each module -> dependency.
for (const module of modules) {
const file = JSON.stringify(module.file.path);
meta.set(
module.file.path,
`fb_size=${Buffer.byteLength(module.file.code, 'utf8')}`,
);
module.dependencies.forEach(dependency => {
list.push(`\t${file} -> ${JSON.stringify(dependency.path)};`);
});
}
for (const [moduleName, metadata] of meta.entries()) {
list.push(`\t${JSON.stringify(moduleName)}[${metadata}];`);
}
// Closing digraph.
list.push('}');