Skip to content

Commit 1929a98

Browse files
committed
feature: @putout/plugin-declare-before-reference: add not top level
1 parent e30bfad commit 1929a98

File tree

4 files changed

+50
-14
lines changed

4 files changed

+50
-14
lines changed

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

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,39 +8,51 @@ const {
88
getPathAfterRequires,
99
} = operator;
1010

11-
const {isFunction, isProgram} = types;
11+
const {
12+
isFunction,
13+
isStatement,
14+
isBlockStatement,
15+
isProgram,
16+
} = types;
1217

1318
const {entries} = Object;
14-
const isTopScope = (a) => isFunction(a) || isProgram(a);
19+
const isTopScope = (a) => isFunction(a) || isProgram(a) || isBlockStatement(a);
1520

1621
module.exports.report = ({name}) => {
1722
return `Declare '${name}' before referencing to avoid 'ReferenceError'`;
1823
};
1924

20-
module.exports.fix = ({path}) => {
21-
const programPath = path.scope.getProgramParent().path;
25+
module.exports.fix = ({path, referencePath}) => {
2226
const {node} = path.parentPath;
27+
const programPath = path.scope.getProgramParent().path;
2328

2429
delete node.loc;
2530

2631
remove(path.parentPath);
2732

28-
const body = programPath.get('body');
29-
const [first] = body;
30-
31-
if (compare(first, 'const __a = require(__b)')) {
32-
const latest = getPathAfterRequires(body.slice(1));
33-
insertBefore(latest, node);
33+
if (path.scope.uid !== programPath.scope.uid) {
34+
const topPath = referencePath.find(isStatement);
35+
36+
insertBefore(topPath, node);
37+
} else {
38+
const body = programPath.get('body');
39+
const [first] = body;
3440

35-
return;
41+
if (compare(first, 'const __a = require(__b)')) {
42+
const latest = getPathAfterRequires(body.slice(1));
43+
insertBefore(latest, node);
44+
45+
return;
46+
}
47+
48+
programPath.node.body.unshift(node);
3649
}
3750

3851
path.__putout_declare_before_reference = true;
39-
programPath.node.body.unshift(node);
4052
};
4153

4254
module.exports.traverse = ({push}) => ({
43-
Program(path) {
55+
'Program|BlockStatement'(path) {
4456
const {bindings} = path.scope;
4557

4658
for (const [name, value] of entries(bindings)) {
@@ -53,13 +65,16 @@ module.exports.traverse = ({push}) => ({
5365
if (path.isFunctionDeclaration())
5466
continue;
5567

68+
if (path.isClassDeclaration())
69+
continue;
70+
5671
if (path.__putout_declare_before_reference)
5772
break;
5873

5974
for (const referencePath of referencePaths) {
6075
const referenceUid = referencePath.find(isTopScope).scope.uid;
6176

62-
if (uid !== referenceUid)
77+
if (uid !== referenceUid && (uid && referencePath.find(isFunction)))
6378
continue;
6479

6580
if (referencePath.parentPath.isExportDefaultDeclaration())
@@ -78,6 +93,7 @@ module.exports.traverse = ({push}) => ({
7893
push({
7994
name,
8095
path,
96+
referencePath,
8197
});
8298

8399
if (!own)
@@ -87,6 +103,7 @@ module.exports.traverse = ({push}) => ({
87103
push({
88104
name,
89105
path,
106+
referencePath,
90107
});
91108
}
92109
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ test('plugin-declare-before-reference: no transform: require', (t) => {
9797
t.end();
9898
});
9999

100+
test('plugin-declare-before-reference: transform: destructuring', (t) => {
101+
t.transform('destructuring');
102+
t.end();
103+
});
104+
100105
test('plugin-declare-before-reference: no report: apply-types', (t) => {
101106
t.noReportAfterTransform('apply-types', {
102107
'apply-types': printer.rules['apply-types'],
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module.exports.fix = ({path, lefts, right, merged}) => {
2+
if (merged) {
3+
const rightPath = path.get('right');
4+
const {right, left} = rightPath.node;
5+
const {object, property} = left;
6+
}
7+
};
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module.exports.fix = ({path, lefts, right, merged}) => {
2+
if (merged) {
3+
const rightPath = path.get('right');
4+
const {object, property} = left;
5+
const {right, left} = rightPath.node;
6+
}
7+
}

0 commit comments

Comments
 (0)