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 { return {
pass: received === built, 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', () => { it('produces an ordered file for a standard list of modules', () => {
expect( const modules = [
dependenciesDot({ createModule('a', ['b']),
modules: [ createModule('b', ['c']),
createModule('a', ['b']), createModule('c', []),
createModule('b', ['c']), ];
createModule('c', []), expect(dependenciesDot({modules})).toBeAMultilineString(
], 'digraph {',
}), '\t"a" -> "b";',
).toBeAMultilineString('digraph {', '\t"a" -> "b";', '\t"b" -> "c";', '}'); '\t"b" -> "c";',
...metadata(modules),
'}',
);
}); });
it('writes one entry per dependency', () => { it('writes one entry per dependency', () => {
const modules = [
createModule('a', ['b', 'c']),
createModule('b', ['d']),
createModule('c', []),
createModule('d', []),
];
expect( expect(
dependenciesDot({ dependenciesDot({
modules: [ modules,
createModule('a', ['b', 'c']),
createModule('b', ['d']),
createModule('c', []),
createModule('d', []),
],
}), }),
).toBeAMultilineString( ).toBeAMultilineString(
'digraph {', 'digraph {',
'\t"a" -> "b";', '\t"a" -> "b";',
'\t"a" -> "c";', '\t"a" -> "c";',
'\t"b" -> "d";', '\t"b" -> "d";',
...metadata(modules),
'}', '}',
); );
}); });
it('handles non-printable characters', () => { it('handles non-printable characters', () => {
const modules = [createModule('"\n', ['\r\t']), createModule('\r\t', [])];
expect( expect(
dependenciesDot({ 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', () => { it('handles circular dependencies', () => {
const modules = [createModule('a', ['b']), createModule('b', ['a'])];
expect( expect(
dependenciesDot({ 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>) { function createModule(path: string, deps: Array<string>) {
return { 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})), 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. // Opening digraph.
list.push('digraph {'); list.push('digraph {');
const meta: Map<string, string> = new Map();
// Adding each module -> dependency. // Adding each module -> dependency.
for (const module of modules) { for (const module of modules) {
const file = JSON.stringify(module.file.path); const file = JSON.stringify(module.file.path);
meta.set(
module.file.path,
`fb_size=${Buffer.byteLength(module.file.code, 'utf8')}`,
);
module.dependencies.forEach(dependency => { module.dependencies.forEach(dependency => {
list.push(`\t${file} -> ${JSON.stringify(dependency.path)};`); list.push(`\t${file} -> ${JSON.stringify(dependency.path)};`);
}); });
} }
for (const [moduleName, metadata] of meta.entries()) {
list.push(`\t${JSON.stringify(moduleName)}[${metadata}];`);
}
// Closing digraph. // Closing digraph.
list.push('}'); list.push('}');