Skip to content

Commit

Permalink
feature(import/default): support default export in TSExportAssignment.
Browse files Browse the repository at this point in the history
  • Loading branch information
joaovieira committed Oct 30, 2019
1 parent 112a0bf commit 86d2eff
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 13 deletions.
42 changes: 31 additions & 11 deletions src/ExportMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -514,30 +514,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
2 changes: 2 additions & 0 deletions tests/files/typescript-default-reexport.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import { getFoo } from './typescript';
export = getFoo;
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() {};
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 @@ -157,3 +157,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-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 @@ -284,7 +284,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 86d2eff

Please sign in to comment.