From a7e8949cb7fd97dbd03f9c79f4d2b65cb6c37d1b Mon Sep 17 00:00:00 2001 From: Sam Ruby Date: Wed, 5 Sep 2018 09:44:42 -0400 Subject: [PATCH] tools: add [src] links to child-process.html handle exports. as an alternative to module.exports PR-URL: https://github.com/nodejs/node/pull/22706 Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell --- test/fixtures/apilinks/exports.js | 13 ++++++ test/fixtures/apilinks/exports.json | 6 +++ tools/doc/apilinks.js | 66 ++++++++++++++++++----------- 3 files changed, 60 insertions(+), 25 deletions(-) create mode 100644 test/fixtures/apilinks/exports.js create mode 100644 test/fixtures/apilinks/exports.json diff --git a/test/fixtures/apilinks/exports.js b/test/fixtures/apilinks/exports.js new file mode 100644 index 00000000000000..880fdf6c9dbe0d --- /dev/null +++ b/test/fixtures/apilinks/exports.js @@ -0,0 +1,13 @@ +'use strict'; + +// Support `exports` as an alternative to `module.exports`. + +function Buffer() {}; + +exports.Buffer = Buffer; +exports.fn1 = function fn1() {}; + +var fn2 = exports.fn2 = function() {}; + +function fn3() {}; +exports.fn3 = fn3; diff --git a/test/fixtures/apilinks/exports.json b/test/fixtures/apilinks/exports.json new file mode 100644 index 00000000000000..f17367a0fc8557 --- /dev/null +++ b/test/fixtures/apilinks/exports.json @@ -0,0 +1,6 @@ +{ + "exports.Buffer": "exports.js#L5", + "exports.fn1": "exports.js#L8", + "exports.fn2": "exports.js#L10", + "exports.fn3": "exports.js#L12" +} diff --git a/tools/doc/apilinks.js b/tools/doc/apilinks.js index b0a221cf014179..0a33125a17b103 100644 --- a/tools/doc/apilinks.js +++ b/tools/doc/apilinks.js @@ -61,6 +61,7 @@ process.argv.slice(2).forEach((file) => { // Scan for exports. const exported = { constructors: [], identifiers: [] }; + const indirect = {}; program.forEach((statement) => { if (statement.type === 'ExpressionStatement') { const expr = statement.expression; @@ -69,35 +70,52 @@ process.argv.slice(2).forEach((file) => { let lhs = expr.left; if (expr.left.object.type === 'MemberExpression') lhs = lhs.object; if (lhs.type !== 'MemberExpression') return; - if (lhs.object.name !== 'module') return; - if (lhs.property.name !== 'exports') return; - - let rhs = expr.right; - while (rhs.type === 'AssignmentExpression') rhs = rhs.right; - - if (rhs.type === 'NewExpression') { - exported.constructors.push(rhs.callee.name); - } else if (rhs.type === 'ObjectExpression') { - rhs.properties.forEach((property) => { - if (property.value.type === 'Identifier') { - exported.identifiers.push(property.value.name); - if (/^[A-Z]/.test(property.value.name[0])) { - exported.constructors.push(property.value.name); - } + if (lhs.object.name === 'exports') { + const name = lhs.property.name; + if (expr.right.type === 'FunctionExpression') { + definition[`${basename}.${name}`] = + `${link}#L${statement.loc.start.line}`; + } else if (expr.right.type === 'Identifier') { + if (expr.right.name === name) { + indirect[name] = `${basename}.${name}`; } - }); - } else if (rhs.type === 'Identifier') { - exported.identifiers.push(rhs.name); + } else { + exported.identifiers.push(name); + } + } else if (lhs.object.name === 'module') { + if (lhs.property.name !== 'exports') return; + + let rhs = expr.right; + while (rhs.type === 'AssignmentExpression') rhs = rhs.right; + + if (rhs.type === 'NewExpression') { + exported.constructors.push(rhs.callee.name); + } else if (rhs.type === 'ObjectExpression') { + rhs.properties.forEach((property) => { + if (property.value.type === 'Identifier') { + exported.identifiers.push(property.value.name); + if (/^[A-Z]/.test(property.value.name[0])) { + exported.constructors.push(property.value.name); + } + } + }); + } else if (rhs.type === 'Identifier') { + exported.identifiers.push(rhs.name); + } } } else if (statement.type === 'VariableDeclaration') { for (const decl of statement.declarations) { let init = decl.init; while (init && init.type === 'AssignmentExpression') init = init.left; if (!init || init.type !== 'MemberExpression') continue; - if (init.object.name !== 'module') continue; - if (init.property.name !== 'exports') continue; - exported.constructors.push(decl.id.name); - definition[decl.id.name] = `${link}#L${statement.loc.start.line}`; + if (init.object.name === 'exports') { + definition[`${basename}.${init.property.name}`] = + `${link}#L${statement.loc.start.line}`; + } else if (init.object.name === 'module') { + if (init.property.name !== 'exports') continue; + exported.constructors.push(decl.id.name); + definition[decl.id.name] = `${link}#L${statement.loc.start.line}`; + } } } }); @@ -107,10 +125,8 @@ process.argv.slice(2).forEach((file) => { // ClassName.foo = ...; // ClassName.prototype.foo = ...; // function Identifier(...) {...}; - // class Foo {...} + // class Foo {...}; // - const indirect = {}; - program.forEach((statement) => { if (statement.type === 'ExpressionStatement') { const expr = statement.expression;