| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent b2a955a commit c32d557
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,13 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + // Parallel assignment to the exported variable and module.exports. | ||
| 4 | + | ||
| 5 | + function ok() { | ||
| 6 | + } | ||
| 7 | + | ||
| 8 | + const asserts = module.exports = ok; | ||
| 9 | + | ||
| 10 | + asserts.ok = ok; | ||
| 11 | + | ||
| 12 | + asserts.strictEqual = function() { | ||
| 13 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,5 @@ | |||
| 1 | + { | ||
| 2 | + "asserts": "reverse.js#L8", | ||
| 3 | + "asserts.ok": "reverse.js#L5", | ||
| 4 | + "asserts.strictEqual": "reverse.js#L12" | ||
| 5 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -55,35 +55,50 @@ process.argv.slice(2).forEach((file) => { | |||
| 55 | 55 | const ast = acorn.parse(source, { ecmaVersion: 10, locations: true }); | |
| 56 | 56 | const program = ast.body; | |
| 57 | 57 | ||
| 58 | + // Build link | ||
| 59 | + const link = `https://github.com/${repo}/blob/${tag}/` + | ||
| 60 | + path.relative('.', file).replace(/\\/g, '/'); | ||
| 61 | + | ||
| 58 | 62 | // Scan for exports. | |
| 59 | 63 | const exported = { constructors: [], identifiers: [] }; | |
| 60 | 64 | program.forEach((statement) => { | |
| 61 | - if (statement.type !== 'ExpressionStatement') return; | ||
| 62 | - const expr = statement.expression; | ||
| 63 | - if (expr.type !== 'AssignmentExpression') return; | ||
| 64 | - | ||
| 65 | - let lhs = expr.left; | ||
| 66 | - if (expr.left.object.type === 'MemberExpression') lhs = lhs.object; | ||
| 67 | - if (lhs.type !== 'MemberExpression') return; | ||
| 68 | - if (lhs.object.name !== 'module') return; | ||
| 69 | - if (lhs.property.name !== 'exports') return; | ||
| 70 | - | ||
| 71 | - let rhs = expr.right; | ||
| 72 | - while (rhs.type === 'AssignmentExpression') rhs = rhs.right; | ||
| 73 | - | ||
| 74 | - if (rhs.type === 'NewExpression') { | ||
| 75 | - exported.constructors.push(rhs.callee.name); | ||
| 76 | - } else if (rhs.type === 'ObjectExpression') { | ||
| 77 | - rhs.properties.forEach((property) => { | ||
| 78 | - if (property.value.type === 'Identifier') { | ||
| 79 | - exported.identifiers.push(property.value.name); | ||
| 80 | - if (/^[A-Z]/.test(property.value.name[0])) { | ||
| 81 | - exported.constructors.push(property.value.name); | ||
| 65 | + if (statement.type === 'ExpressionStatement') { | ||
| 66 | + const expr = statement.expression; | ||
| 67 | + if (expr.type !== 'AssignmentExpression') return; | ||
| 68 | + | ||
| 69 | + let lhs = expr.left; | ||
| 70 | + if (expr.left.object.type === 'MemberExpression') lhs = lhs.object; | ||
| 71 | + if (lhs.type !== 'MemberExpression') return; | ||
| 72 | + if (lhs.object.name !== 'module') return; | ||
| 73 | + if (lhs.property.name !== 'exports') return; | ||
| 74 | + | ||
| 75 | + let rhs = expr.right; | ||
| 76 | + while (rhs.type === 'AssignmentExpression') rhs = rhs.right; | ||
| 77 | + | ||
| 78 | + if (rhs.type === 'NewExpression') { | ||
| 79 | + exported.constructors.push(rhs.callee.name); | ||
| 80 | + } else if (rhs.type === 'ObjectExpression') { | ||
| 81 | + rhs.properties.forEach((property) => { | ||
| 82 | + if (property.value.type === 'Identifier') { | ||
| 83 | + exported.identifiers.push(property.value.name); | ||
| 84 | + if (/^[A-Z]/.test(property.value.name[0])) { | ||
| 85 | + exported.constructors.push(property.value.name); | ||
| 86 | + } | ||
| 82 | 87 | } | |
| 83 | - } | ||
| 84 | - }); | ||
| 85 | - } else if (rhs.type === 'Identifier') { | ||
| 86 | - exported.identifiers.push(rhs.name); | ||
| 88 | + }); | ||
| 89 | + } else if (rhs.type === 'Identifier') { | ||
| 90 | + exported.identifiers.push(rhs.name); | ||
| 91 | + } | ||
| 92 | + } else if (statement.type === 'VariableDeclaration') { | ||
| 93 | + for (const decl of statement.declarations) { | ||
| 94 | + let init = decl.init; | ||
| 95 | + while (init && init.type === 'AssignmentExpression') init = init.left; | ||
| 96 | + if (!init || init.type !== 'MemberExpression') continue; | ||
| 97 | + if (init.object.name !== 'module') continue; | ||
| 98 | + if (init.property.name !== 'exports') continue; | ||
| 99 | + exported.constructors.push(decl.id.name); | ||
| 100 | + definition[decl.id.name] = `${link}#L${statement.loc.start.line}`; | ||
| 101 | + } | ||
| 87 | 102 | } | |
| 88 | 103 | }); | |
| 89 | 104 | ||
@@ -93,8 +108,7 @@ process.argv.slice(2).forEach((file) => { | |||
| 93 | 108 | // ClassName.prototype.foo = ...; | |
| 94 | 109 | // function Identifier(...) {...}; | |
| 95 | 110 | // | |
| 96 | - const link = `https://github.com/${repo}/blob/${tag}/` + | ||
| 97 | - path.relative('.', file).replace(/\\/g, '/'); | ||
| 111 | + const indirect = {}; | ||
| 98 | 112 | ||
| 99 | 113 | program.forEach((statement) => { | |
| 100 | 114 | if (statement.type === 'ExpressionStatement') { | |
@@ -128,6 +142,11 @@ process.argv.slice(2).forEach((file) => { | |||
| 128 | 142 | } | |
| 129 | 143 | ||
| 130 | 144 | definition[name] = `${link}#L${statement.loc.start.line}`; | |
| 145 | + | ||
| 146 | + if (expr.left.property.name === expr.right.name) { | ||
| 147 | + indirect[expr.right.name] = name; | ||
| 148 | + } | ||
| 149 | + | ||
| 131 | 150 | } else if (statement.type === 'FunctionDeclaration') { | |
| 132 | 151 | const name = statement.id.name; | |
| 133 | 152 | if (!exported.identifiers.includes(name)) return; | |
@@ -136,6 +155,18 @@ process.argv.slice(2).forEach((file) => { | |||
| 136 | 155 | `${link}#L${statement.loc.start.line}`; | |
| 137 | 156 | } | |
| 138 | 157 | }); | |
| 158 | + | ||
| 159 | + // Search for indirect references of the form ClassName.foo = foo; | ||
| 160 | + if (Object.keys(indirect).length > 0) { | ||
| 161 | + program.forEach((statement) => { | ||
| 162 | + if (statement.type === 'FunctionDeclaration') { | ||
| 163 | + const name = statement.id.name; | ||
| 164 | + if (indirect[name]) { | ||
| 165 | + definition[indirect[name]] = `${link}#L${statement.loc.start.line}`; | ||
| 166 | + } | ||
| 167 | + } | ||
| 168 | + }); | ||
| 169 | + } | ||
| 139 | 170 | }); | |
| 140 | 171 | ||
| 141 | 172 | console.log(JSON.stringify(definition, null, 2)); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments