Skip to content

Commit 610b43b

Browse files
committed
feature: @putout/plugin-declare-before-reference: cross-references
1 parent 0e4ec0d commit 610b43b

4 files changed

Lines changed: 42 additions & 1 deletion

File tree

packages/plugin-declare-before-reference/lib/declare-before-reference.js

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const {types, operator} = require('putout');
44
const {
55
remove,
66
compare,
7+
compareAny,
78
insertBefore,
89
getPathAfterRequires,
910
} = operator;
@@ -19,6 +20,7 @@ const {entries} = Object;
1920
const isTopScope = (a) => isFunction(a) || isProgram(a);
2021
const getTopUID = (a) => a.find(isTopScope).scope.uid;
2122
const getBlockUID = (a) => a.find(isBlockStatement)?.scope.uid;
23+
const getKey = (a) => a.key;
2224

2325
module.exports.report = ({name}) => {
2426
return `Declare '${name}' before referencing to avoid 'ReferenceError'`;
@@ -74,18 +76,27 @@ module.exports.traverse = ({push}) => ({
7476
break;
7577

7678
for (const referencePath of referencePaths) {
79+
const referenceParentPath = referencePath.parentPath;
7780
const referenceUid = getTopUID(referencePath);
7881
const blockUid = getBlockUID(referencePath);
7982

8083
if (uid !== referenceUid && uid !== blockUid)
8184
continue;
8285

83-
if (referencePath.parentPath.isExportDefaultDeclaration())
86+
if (referenceParentPath.isExportDefaultDeclaration())
8487
break;
8588

8689
if (referencePath.isExportDeclaration())
8790
break;
8891

92+
const initPath = path.get('init');
93+
94+
if (compareAny(getName(initPath), getKeys(referenceParentPath)))
95+
break;
96+
97+
if (compareAny(getName(referenceParentPath), getKeys(path)))
98+
break;
99+
89100
const [own, pathLoc] = getLoc(path);
90101
const [referenceOwn, referenceLoc] = getLoc(referencePath);
91102

@@ -124,3 +135,24 @@ function getLoc(path) {
124135

125136
return [own, loc];
126137
}
138+
139+
function getName(path) {
140+
do {
141+
if (!path.isMemberExpression())
142+
return path;
143+
} while (path = path.get('object'));
144+
}
145+
146+
function getKeys(path) {
147+
const {id} = path.node;
148+
149+
if (!id)
150+
return [];
151+
152+
const {properties} = id;
153+
154+
if (!properties)
155+
return [];
156+
157+
return properties.map(getKey);
158+
}

packages/plugin-declare-before-reference/test/declare-before-reference.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,8 @@ test('plugin-declare-before-reference: transform: convert-traverse-to-scan', (t)
131131
});
132132
t.end();
133133
});
134+
135+
test('plugin-declare-before-reference: no report: cross-reference', (t) => {
136+
t.noReport('cross-reference');
137+
t.end();
138+
});
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
const {path, references} = binding;
2+
const binding = path.scope.bindings[name];
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
const binding = path.scope.bindings[name];
2+
const {path, references} = binding;

0 commit comments

Comments
 (0)