Skip to content

Commit

Permalink
[New] import/default: support default export in TSExportAssignment
Browse files Browse the repository at this point in the history
Fixes #1527
  • Loading branch information
joaovieira authored and ljharb committed Oct 30, 2019
1 parent 9516152 commit 381267a
Show file tree
Hide file tree
Showing 10 changed files with 112 additions and 13 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel

## [Unreleased]

### Added
- [`import/default`]: support default export in TSExportAssignment ([#1528], thanks [@joaovieira])

### Fixed
- [`group-exports`]: Flow type export awareness ([#1702], thanks [@ernestostifano])
- [`order`]: Recognize pathGroup config for first group ([#1719], [#1724], thanks [@forivall], [@xpl])
Expand Down Expand Up @@ -697,6 +700,7 @@ for info on changes for earlier releases.
[#1560]: https://github.com/benmosher/eslint-plugin-import/pull/1560
[#1551]: https://github.com/benmosher/eslint-plugin-import/pull/1551
[#1542]: https://github.com/benmosher/eslint-plugin-import/pull/1542
[#1528]: https://github.com/benmosher/eslint-plugin-import/pull/1528
[#1526]: https://github.com/benmosher/eslint-plugin-import/pull/1526
[#1521]: https://github.com/benmosher/eslint-plugin-import/pull/1521
[#1519]: https://github.com/benmosher/eslint-plugin-import/pull/1519
Expand Down
42 changes: 31 additions & 11 deletions src/ExportMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -530,30 +530,50 @@ ExportMap.parse = function (path, content, context) {

// This doesn't declare anything, but changes what's being exported.
if (n.type === 'TSExportAssignment') {
const moduleDecls = ast.body.filter((bodyNode) =>
bodyNode.type === 'TSModuleDeclaration' && bodyNode.id.name === n.expression.name
const exportedName = n.expression.name
const declTypes = [
'VariableDeclaration',
'ClassDeclaration',
'TSDeclareFunction',
'TSEnumDeclaration',
'TSTypeAliasDeclaration',
'TSInterfaceDeclaration',
'TSAbstractClassDeclaration',
'TSModuleDeclaration',
]
const exportedDecls = ast.body.filter(({ type, id, declarations }) =>
declTypes.includes(type) &&
(id && id.name === exportedName || declarations.find(d => d.id.name === exportedName))
)
moduleDecls.forEach((moduleDecl) => {
if (moduleDecl && moduleDecl.body && moduleDecl.body.body) {
moduleDecl.body.body.forEach((moduleBlockNode) => {
if (exportedDecls.length === 0) {
// Export is not referencing any local declaration, must be re-exporting
m.namespace.set('default', captureDoc(source, docStyleParsers, n))
return
}
exportedDecls.forEach((decl) => {
if (decl.type === 'TSModuleDeclaration' && decl && decl.body && decl.body.body) {
decl.body.body.forEach((moduleBlockNode) => {
// Export-assignment exports all members in the namespace, explicitly exported or not.
const exportedDecl = moduleBlockNode.type === 'ExportNamedDeclaration' ?
const namespaceDecl = moduleBlockNode.type === 'ExportNamedDeclaration' ?
moduleBlockNode.declaration :
moduleBlockNode

if (exportedDecl.type === 'VariableDeclaration') {
exportedDecl.declarations.forEach((decl) =>
recursivePatternCapture(decl.id,(id) => m.namespace.set(
if (namespaceDecl.type === 'VariableDeclaration') {
namespaceDecl.declarations.forEach((d) =>
recursivePatternCapture(d.id, (id) => m.namespace.set(
id.name,
captureDoc(source, docStyleParsers, decl, exportedDecl, moduleBlockNode))
captureDoc(source, docStyleParsers, decl, namespaceDecl, moduleBlockNode))
)
)
} else {
m.namespace.set(
exportedDecl.id.name,
namespaceDecl.id.name,
captureDoc(source, docStyleParsers, moduleBlockNode))
}
})
} else {
// Export as default
m.namespace.set('default', captureDoc(source, docStyleParsers, decl))
}
})
}
Expand Down
1 change: 1 addition & 0 deletions tests/files/typescript-default.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default function foobar() {};
2 changes: 2 additions & 0 deletions tests/files/typescript-export-assign-default-reexport.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import { getFoo } from './typescript';
export = getFoo;
3 changes: 3 additions & 0 deletions tests/files/typescript-export-assign-default.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export = foobar;

declare const foobar: number;
11 changes: 11 additions & 0 deletions tests/files/typescript-export-assign-mixed.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export = foobar;

declare function foobar(): void;
declare namespace foobar {
type MyType = string
enum MyEnum {
Foo,
Bar,
Baz
}
}
File renamed without changes.
55 changes: 54 additions & 1 deletion tests/src/rules/default.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { test, SYNTAX_CASES } from '../utils'
import { test, SYNTAX_CASES, getTSParsers } from '../utils'
import { RuleTester } from 'eslint'

import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve'
Expand Down Expand Up @@ -152,3 +152,56 @@ if (!CASE_SENSITIVE_FS) {
],
})
}

context('TypeScript', function () {
getTSParsers().forEach((parser) => {
ruleTester.run(`default`, rule, {
valid: [
test({
code: `import foobar from "./typescript-default"`,
parser: parser,
settings: {
'import/parsers': { [parser]: ['.ts'] },
'import/resolver': { 'eslint-import-resolver-typescript': true },
},
}),
test({
code: `import foobar from "./typescript-export-assign-default"`,
parser: parser,
settings: {
'import/parsers': { [parser]: ['.ts'] },
'import/resolver': { 'eslint-import-resolver-typescript': true },
},
}),
test({
code: `import foobar from "./typescript-export-assign-mixed"`,
parser: parser,
settings: {
'import/parsers': { [parser]: ['.ts'] },
'import/resolver': { 'eslint-import-resolver-typescript': true },
},
}),
test({
code: `import foobar from "./typescript-export-assign-default-reexport"`,
parser: parser,
settings: {
'import/parsers': { [parser]: ['.ts'] },
'import/resolver': { 'eslint-import-resolver-typescript': true },
},
}),
],

invalid: [
test({
code: `import foobar from "./typescript"`,
parser: parser,
settings: {
'import/parsers': { [parser]: ['.ts'] },
'import/resolver': { 'eslint-import-resolver-typescript': true },
},
errors: ['No default export found in imported module "./typescript".'],
}),
],
})
})
})
7 changes: 6 additions & 1 deletion tests/src/rules/named.js
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,12 @@ ruleTester.run('named (export *)', rule, {

context('TypeScript', function () {
getTSParsers().forEach((parser) => {
['typescript', 'typescript-declare', 'typescript-export-assign', 'typescript-export-assign-merged'].forEach((source) => {
[
'typescript',
'typescript-declare',
'typescript-export-assign-namespace',
'typescript-export-assign-namespace-merged',
].forEach((source) => {
ruleTester.run(`named`, rule, {
valid: [
test({
Expand Down

0 comments on commit 381267a

Please sign in to comment.