Skip to content

Commit 97c0d5f

Browse files
committed
Merge pull request #211 from benmosher/issue-202-hoisting
hoisting
2 parents 47d6dea + 10fb144 commit 97c0d5f

File tree

4 files changed

+76
-25
lines changed

4 files changed

+76
-25
lines changed

src/rules/namespace.js

+30-24
Original file line numberDiff line numberDiff line change
@@ -14,37 +14,43 @@ module.exports = function (context) {
1414

1515
return {
1616

17-
'ImportDeclaration': function (declaration) {
18-
if (declaration.specifiers.length === 0) return
17+
// pick up all imports at body entry time, to properly respect hoisting
18+
'Program': function ({ body }) {
19+
function processBodyStatement(declaration) {
20+
if (declaration.type !== 'ImportDeclaration') return
1921

20-
const imports = Exports.get(declaration.source.value, context)
21-
if (imports == null) return null
22+
if (declaration.specifiers.length === 0) return
2223

23-
if (imports.errors.length) {
24-
imports.reportErrors(context, declaration)
25-
return
26-
}
24+
const imports = Exports.get(declaration.source.value, context)
25+
if (imports == null) return null
26+
27+
if (imports.errors.length) {
28+
imports.reportErrors(context, declaration)
29+
return
30+
}
2731

28-
for (let specifier of declaration.specifiers) {
29-
switch (specifier.type) {
30-
case 'ImportNamespaceSpecifier':
31-
if (!imports.hasNamed) {
32-
context.report(specifier,
33-
`No exported names found in module '${declaration.source.value}'.`)
32+
for (let specifier of declaration.specifiers) {
33+
switch (specifier.type) {
34+
case 'ImportNamespaceSpecifier':
35+
if (!imports.hasNamed) {
36+
context.report(specifier,
37+
`No exported names found in module '${declaration.source.value}'.`)
38+
}
39+
namespaces.set(specifier.local.name, imports.named)
40+
break
41+
case 'ImportDefaultSpecifier':
42+
case 'ImportSpecifier': {
43+
const meta = imports.named.get(
44+
// default to 'default' for default http://i.imgur.com/nj6qAWy.jpg
45+
specifier.imported ? specifier.imported.name : 'default')
46+
if (!meta || !meta.namespace) break
47+
namespaces.set(specifier.local.name, meta.namespace)
48+
break
3449
}
35-
namespaces.set(specifier.local.name, imports.named)
36-
break
37-
case 'ImportDefaultSpecifier':
38-
case 'ImportSpecifier': {
39-
const meta = imports.named.get(
40-
// default to 'default' for default http://i.imgur.com/nj6qAWy.jpg
41-
specifier.imported ? specifier.imported.name : 'default')
42-
if (!meta || !meta.namespace) break
43-
namespaces.set(specifier.local.name, meta.namespace)
44-
break
4550
}
4651
}
4752
}
53+
body.forEach(processBodyStatement)
4854
},
4955

5056
// same as above, but does not add names to local map

src/rules/no-deprecated.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ module.exports = function (context) {
66
, namespaces = new Map()
77

88
function checkSpecifiers(node) {
9+
if (node.type !== 'ImportDeclaration') return
910
if (node.source == null) return // local export, ignore
1011

1112
const imports = Exports.get(node.source.value, context)
@@ -64,7 +65,7 @@ module.exports = function (context) {
6465
}
6566

6667
return {
67-
'ImportDeclaration': checkSpecifiers,
68+
'Program': ({ body }) => body.forEach(checkSpecifiers),
6869

6970
'Identifier': function (node) {
7071
if (node.parent.type === 'MemberExpression' && node.parent.property === node) {

tests/src/rules/namespace.js

+22
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,13 @@ const valid = [
6868
parser: 'babel-eslint',
6969
}),
7070

71+
// respect hoisting
72+
test({
73+
code:
74+
'function x() { console.log((names.b).c); } ' +
75+
'import * as names from "./named-exports"; ',
76+
}),
77+
7178
]
7279

7380
const invalid = [
@@ -138,6 +145,21 @@ const invalid = [
138145
code: "import b from './deep/default'; console.log(b.e)",
139146
errors: [ "'e' not found in imported namespace 'b'." ],
140147
}),
148+
149+
// respect hoisting
150+
test({
151+
code:
152+
'console.log(names.c);' +
153+
"import * as names from './named-exports'; ",
154+
errors: [error('c', 'names')],
155+
}),
156+
test({
157+
code:
158+
'function x() { console.log(names.c) } ' +
159+
"import * as names from './named-exports'; ",
160+
errors: [error('c', 'names')],
161+
}),
162+
141163
]
142164

143165
///////////////////////

tests/src/rules/no-deprecated.js

+22
Original file line numberDiff line numberDiff line change
@@ -134,3 +134,25 @@ ruleTester.run('no-deprecated', rule, {
134134
}),
135135
],
136136
})
137+
138+
ruleTester.run('no-deprecated: hoisting', rule, {
139+
valid: [
140+
141+
test({
142+
code: "function x(deepDep) { console.log(deepDep.MY_TERRIBLE_ACTION) } import { deepDep } from './deep-deprecated'",
143+
}),
144+
145+
],
146+
147+
invalid: [
148+
149+
test({
150+
code: "console.log(MY_TERRIBLE_ACTION); import { MY_TERRIBLE_ACTION } from './deprecated'",
151+
errors: [
152+
{ type: 'Identifier', message: 'Deprecated: please stop sending/handling this action type.' },
153+
{ type: 'ImportSpecifier', message: 'Deprecated: please stop sending/handling this action type.' },
154+
],
155+
}),
156+
157+
],
158+
})

0 commit comments

Comments
 (0)