Skip to content

Commit

Permalink
WIP ES7 namespace export support
Browse files Browse the repository at this point in the history
  • Loading branch information
benmosher committed Feb 6, 2016
1 parent 40e98b7 commit b3ca8de
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 123 deletions.
2 changes: 1 addition & 1 deletion src/rules/namespace.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ module.exports = function (context) {
if (imports.errors.length) {
context.report({
node: declaration.source,
message: `Parse errors in imported module '${declaration.source.value}'.`,
message: `Parse errors in imported module '${declaration.source.value}'.` + JSON.stringify(imports.errors),
})
return
}
Expand Down
1 change: 1 addition & 0 deletions tests/files/deep-es7/a.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * as b from './b'
1 change: 1 addition & 0 deletions tests/files/deep-es7/b.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * as c from './c'
1 change: 1 addition & 0 deletions tests/files/deep-es7/c.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * as d from './d'
1 change: 1 addition & 0 deletions tests/files/deep-es7/d.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const e = "e"
247 changes: 125 additions & 122 deletions tests/src/rules/namespace.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,137 +9,140 @@ function error(name, namespace) {
return { message: `'${name}' not found in imported namespace '${namespace}'.` }
}


ruleTester.run('namespace', rule, {
valid: [
test({ code: "import * as foo from './empty-folder';"}),
test({ code: 'import * as names from "./named-exports"; ' +
'console.log((names.b).c); ' }),

test({ code: 'import * as names from "./named-exports"; ' +
'console.log(names.a);' }),
test({ code: 'import * as names from "./re-export-names"; ' +
'console.log(names.foo);' }),
test({ code: "import * as elements from './jsx';"
, settings: { 'import/parse-options': { plugins: ['jsx'] }}}),
test({ code: "import * as foo from './common';"
, settings: { 'import/ignore': ['common'] } }),

// destructuring namespaces
test({ code: 'import * as names from "./named-exports";' +
'const { a } = names' }),
test({ code: 'import * as names from "./named-exports";' +
'const { d: c } = names' }),
test({ code: 'import * as names from "./named-exports";' +
'const { c } = foo\n' +
' , { length } = "names"\n' +
' , alt = names' }),
// deep destructuring only cares about top level
test({ code: 'import * as names from "./named-exports";' +
'const { ExportedClass: { length } } = names' }),

// detect scope redefinition
test({ code: 'import * as names from "./named-exports";' +
'function b(names) { const { c } = names }' }),
test({ code: 'import * as names from "./named-exports";' +
'function b() { let names = null; const { c } = names }' }),
test({ code: 'import * as names from "./named-exports";' +
'const x = function names() { const { c } = names }' }),


/////////
// es7 //
/////////
test({ code: 'export * as names from "./named-exports"'
, parser: 'babel-eslint' }),
test({ code: 'export defport, * as names from "./named-exports"'
, parser: 'babel-eslint' }),
// non-existent is handled by no-unresolved
test({ code: 'export * as names from "./does-not-exist"'
, parser: 'babel-eslint' }),

///////////////////////
// deep dereferences //
///////////////////////

test({ code: 'import * as a from "./deep/a"; console.log(a.b.c.d.e)' }),
test({ code: 'import * as a from "./deep/a"; console.log(a.b.c.d.e.f)' }),
test({ code: 'import * as a from "./deep/a"; var {b:{c:{d:{e}}}} = a' }),
],

invalid: [
test({code: "import * as foo from './common';",
errors: ["No exported names found in module './common'."]}),
test({code: "import * as names from './default-export';",
errors: ["No exported names found in module './default-export'."]}),

test({ code: "import * as names from './named-exports'; " +
' console.log(names.c);'
, errors: [error('c', 'names')] }),

test({ code: "import * as names from './named-exports';" +
" console.log(names['a']);"
, errors: 1 }),

// assignment warning (from no-reassign)
test({ code: 'import * as foo from \'./bar\'; foo.foo = \'y\';'
, errors: [{ message: 'Assignment to member of namespace \'foo\'.'}] }),
test({ code: 'import * as foo from \'./bar\'; foo.x = \'y\';'
, errors: 2 }),

// invalid destructuring
test({ code: 'import * as names from "./named-exports";' +
'const { c } = names'
, errors: [{ type: 'Property' }] }),
test({ code: 'import * as names from "./named-exports";' +
'function b() { const { c } = names }'
, errors: [{ type: 'Property' }] }),
test({ code: 'import * as names from "./named-exports";' +
'const { c: d } = names'
, errors: [{ type: 'Property' }] }),
test({ code: 'import * as names from "./named-exports";' +
'const { c: { d } } = names'
, errors: [{ type: 'Property' }] }),

/////////
// es7 //
/////////
test({ code: 'export * as names from "./default-export"'
, parser: 'babel-eslint'
, errors: 1 }),
test({ code: 'export defport, * as names from "./default-export"'
, parser: 'babel-eslint'
, errors: 1 }),


// parse errors
const valid = [
test({ code: "import * as foo from './empty-folder';"}),
test({ code: 'import * as names from "./named-exports"; ' +
'console.log((names.b).c); ' }),

test({ code: 'import * as names from "./named-exports"; ' +
'console.log(names.a);' }),
test({ code: 'import * as names from "./re-export-names"; ' +
'console.log(names.foo);' }),
test({ code: "import * as elements from './jsx';"
, settings: { 'import/parse-options': { plugins: ['jsx'] }}}),
test({ code: "import * as foo from './common';"
, settings: { 'import/ignore': ['common'] } }),

// destructuring namespaces
test({ code: 'import * as names from "./named-exports";' +
'const { a } = names' }),
test({ code: 'import * as names from "./named-exports";' +
'const { d: c } = names' }),
test({ code: 'import * as names from "./named-exports";' +
'const { c } = foo\n' +
' , { length } = "names"\n' +
' , alt = names' }),
// deep destructuring only cares about top level
test({ code: 'import * as names from "./named-exports";' +
'const { ExportedClass: { length } } = names' }),

// detect scope redefinition
test({ code: 'import * as names from "./named-exports";' +
'function b(names) { const { c } = names }' }),
test({ code: 'import * as names from "./named-exports";' +
'function b() { let names = null; const { c } = names }' }),
test({ code: 'import * as names from "./named-exports";' +
'const x = function names() { const { c } = names }' }),


/////////
// es7 //
/////////
test({ code: 'export * as names from "./named-exports"'
, parser: 'babel-eslint' }),
test({ code: 'export defport, * as names from "./named-exports"'
, parser: 'babel-eslint' }),
// non-existent is handled by no-unresolved
test({ code: 'export * as names from "./does-not-exist"'
, parser: 'babel-eslint' }),
]

const invalid = [
test({code: "import * as foo from './common';",
errors: ["No exported names found in module './common'."]}),
test({code: "import * as names from './default-export';",
errors: ["No exported names found in module './default-export'."]}),

test({ code: "import * as names from './named-exports'; " +
' console.log(names.c);'
, errors: [error('c', 'names')] }),

test({ code: "import * as names from './named-exports';" +
" console.log(names['a']);"
, errors: 1 }),

// assignment warning (from no-reassign)
test({ code: 'import * as foo from \'./bar\'; foo.foo = \'y\';'
, errors: [{ message: 'Assignment to member of namespace \'foo\'.'}] }),
test({ code: 'import * as foo from \'./bar\'; foo.x = \'y\';'
, errors: 2 }),

// invalid destructuring
test({ code: 'import * as names from "./named-exports";' +
'const { c } = names'
, errors: [{ type: 'Property' }] }),
test({ code: 'import * as names from "./named-exports";' +
'function b() { const { c } = names }'
, errors: [{ type: 'Property' }] }),
test({ code: 'import * as names from "./named-exports";' +
'const { c: d } = names'
, errors: [{ type: 'Property' }] }),
test({ code: 'import * as names from "./named-exports";' +
'const { c: { d } } = names'
, errors: [{ type: 'Property' }] }),

/////////
// es7 //
/////////
test({ code: 'export * as names from "./default-export"'
, parser: 'babel-eslint'
, errors: 1 }),
test({ code: 'export defport, * as names from "./default-export"'
, parser: 'babel-eslint'
, errors: 1 }),


// parse errors
test({
code: "import * as namespace from './malformed.js';",
errors: [{
message: "Parse errors in imported module './malformed.js'.",
type: 'Literal',
}],
}),

]

///////////////////////
// deep dereferences //
//////////////////////
;[['deep', 'espree'], ['deep-es7', 'babel-eslint']].forEach(function ([folder, parser]) { // close over params
valid.push(
test({ parser, code: `import * as a from "./${folder}/a"; console.log(a.b.c.d.e)` }),
test({ parser, code: `import * as a from "./${folder}/a"; console.log(a.b.c.d.e.f)` }),
test({ parser, code: `import * as a from "./${folder}/a"; var {b:{c:{d:{e}}}} = a` }))

invalid.push(
test({
code: "import * as namespace from './malformed.js';",
errors: [{
message: "Parse errors in imported module './malformed.js'.",
type: 'Literal',
}],
}),


///////////////////////
// deep dereferences //
///////////////////////
test({
code: 'import * as a from "./deep/a"; console.log(a.b.e)',
parser,
code: `import * as a from "./${folder}/a"; console.log(a.b.e)`,
errors: [ "'e' not found in deeply imported namespace 'a.b'." ],
}),
test({
code: 'import * as a from "./deep/a"; console.log(a.b.c.e)',
parser,
code: `import * as a from "./${folder}/a"; console.log(a.b.c.e)`,
errors: [ "'e' not found in deeply imported namespace 'a.b.c'." ],
}),
test({
code: 'import * as a from "./deep/a"; var {b:{ e }} = a',
parser,
code: `import * as a from "./${folder}/a"; var {b:{ e }} = a`,
errors: [ "'e' not found in deeply imported namespace 'a.b'." ],
}),
test({
code: 'import * as a from "./deep/a"; var {b:{c:{ e }}} = a',
parser,
code: `import * as a from "./${folder}/a"; var {b:{c:{ e }}} = a`,
errors: [ "'e' not found in deeply imported namespace 'a.b.c'." ],
}),
],
}))
})

ruleTester.run('namespace', rule, { valid, invalid })

0 comments on commit b3ca8de

Please sign in to comment.