Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support export type named exports from typescript #1304

Merged
merged 4 commits into from
Apr 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ rules:

You may use the following shortcut or assemble your own config using the granular settings described below.

Make sure you have installed the [`@typescript-eslint/parser`] which is used in the following configuration. Unfortunately NPM does not allow to list optional peer dependencies.
Make sure you have installed [`@typescript-eslint/parser`] which is used in the following configuration. Unfortunately NPM does not allow to list optional peer dependencies.

```yaml
extends:
Expand Down Expand Up @@ -344,14 +344,16 @@ directly using webpack, for example:
# .eslintrc.yml
settings:
import/parsers:
typescript-eslint-parser: [ .ts, .tsx ]
@typescript-eslint/parser: [ .ts, .tsx ]
```

In this case, [`typescript-eslint-parser`](https://github.com/eslint/typescript-eslint-parser) must be installed and require-able from
the running `eslint` module's location (i.e., install it as a peer of ESLint).
In this case, [`@typescript-eslint/parser`](https://www.npmjs.com/package/@typescript-eslint/parser)
must be installed and require-able from the running `eslint` module's location
(i.e., install it as a peer of ESLint).

This is currently only tested with `typescript-eslint-parser` but should theoretically
work with any moderately ESTree-compliant parser.
This is currently only tested with `@typescript-eslint/parser` (and its predecessor,
`typescript-eslint-parser`) but should theoretically work with any moderately
ESTree-compliant parser.

It's difficult to say how well various plugin features will be supported, too,
depending on how far down the rabbit hole goes. Submit an issue if you find strange
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
},
"homepage": "https://github.com/benmosher/eslint-plugin-import",
"devDependencies": {
"@typescript-eslint/parser": "^1.5.0",
"babel-eslint": "^8.2.6",
"babel-plugin-istanbul": "^4.1.6",
"babel-preset-es2015-argon": "latest",
Expand All @@ -67,9 +68,10 @@
"nyc": "^11.9.0",
"redux": "^3.7.2",
"rimraf": "^2.6.3",
"semver": "^6.0.0",
"sinon": "^2.4.1",
"typescript": "^3.2.2",
"typescript-eslint-parser": "^21.0.2"
ljharb marked this conversation as resolved.
Show resolved Hide resolved
"typescript-eslint-parser": "^22.0.0"
},
"peerDependencies": {
"eslint": "2.x - 5.x"
Expand Down
1 change: 1 addition & 0 deletions src/ExportMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,7 @@ ExportMap.parse = function (path, content, context) {
case 'TypeAlias': // flowtype with babel-eslint parser
case 'InterfaceDeclaration':
case 'TSEnumDeclaration':
case 'TSTypeAliasDeclaration':
case 'TSInterfaceDeclaration':
case 'TSAbstractClassDeclaration':
case 'TSModuleDeclaration':
Expand Down
6 changes: 6 additions & 0 deletions tests/dep-time-travel.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@

npm install --no-save eslint@$ESLINT_VERSION --ignore-scripts || true

# completely remove the new typescript parser for ESLint < v5
if [[ "$ESLINT_VERSION" -lt "5" ]]; then
echo "Removing @typescript-eslint/parser..."
npm uninstall @typescript-eslint/parser
fi

# use these alternate typescript dependencies for ESLint < v4
if [[ "$ESLINT_VERSION" -lt "4" ]]; then
echo "Downgrading babel-eslint..."
Expand Down
6 changes: 6 additions & 0 deletions tests/src/core/getExports.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { expect } from 'chai'
import semver from 'semver'
import { linter } from 'eslint'
import ExportMap from '../../../src/ExportMap'

import * as fs from 'fs'
Expand Down Expand Up @@ -317,6 +319,10 @@ describe('ExportMap', function () {
['array form', { 'typescript-eslint-parser': ['.ts', '.tsx'] }],
]

if (semver.satisfies(linter.version, '>5.0.0')) {
configs.push(['array form', { '@typescript-eslint/parser': ['.ts', '.tsx'] }])
}

configs.forEach(([description, parserConfig]) => {

describe(description, function () {
Expand Down
197 changes: 103 additions & 94 deletions tests/src/rules/named.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { test, SYNTAX_CASES } from '../utils'
import { RuleTester } from 'eslint'
import { RuleTester, linter } from 'eslint'
import semver from 'semver'

import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve'

Expand Down Expand Up @@ -254,99 +255,107 @@ ruleTester.run('named (export *)', rule, {
})


context("Typescript", function () {
context('Typescript', function () {
// Typescript
ruleTester.run("named", rule, {
valid: [
test({
code: 'import { MyType } from "./typescript"',
parser: 'typescript-eslint-parser',
settings: {
'import/parsers': { 'typescript-eslint-parser': ['.ts'] },
'import/resolver': { 'eslint-import-resolver-typescript': true },
},
}),
test({
code: 'import { Foo } from "./typescript"',
parser: 'typescript-eslint-parser',
settings: {
'import/parsers': { 'typescript-eslint-parser': ['.ts'] },
'import/resolver': { 'eslint-import-resolver-typescript': true },
},
}),
test({
code: 'import { Bar } from "./typescript"',
parser: 'typescript-eslint-parser',
settings: {
'import/parsers': { 'typescript-eslint-parser': ['.ts'] },
'import/resolver': { 'eslint-import-resolver-typescript': true },
},
}),
test({
code: 'import { getFoo } from "./typescript"',
parser: 'typescript-eslint-parser',
settings: {
'import/parsers': { 'typescript-eslint-parser': ['.ts'] },
'import/resolver': { 'eslint-import-resolver-typescript': true },
},
}),
test({
code: 'import { MyEnum } from "./typescript"',
parser: 'typescript-eslint-parser',
settings: {
'import/parsers': { 'typescript-eslint-parser': ['.ts'] },
'import/resolver': { 'eslint-import-resolver-typescript': true },
},
}),
test({
code: `
import { MyModule } from "./typescript"
MyModule.ModuleFunction()
`,
parser: 'typescript-eslint-parser',
settings: {
'import/parsers': { 'typescript-eslint-parser': ['.ts'] },
'import/resolver': { 'eslint-import-resolver-typescript': true },
},
}),
test({
code: `
import { MyNamespace } from "./typescript"
MyNamespace.NSModule.NSModuleFunction()
`,
parser: 'typescript-eslint-parser',
settings: {
'import/parsers': { 'typescript-eslint-parser': ['.ts'] },
'import/resolver': { 'eslint-import-resolver-typescript': true },
},
}),
],

invalid: [
test({
code: 'import { MissingType } from "./typescript"',
parser: 'typescript-eslint-parser',
settings: {
'import/parsers': { 'typescript-eslint-parser': ['.ts'] },
'import/resolver': { 'eslint-import-resolver-typescript': true },
},
errors: [{
message: "MissingType not found in './typescript'",
type: 'Identifier',
}],
}),
test({
code: 'import { NotExported } from "./typescript"',
parser: 'typescript-eslint-parser',
settings: {
'import/parsers': { 'typescript-eslint-parser': ['.ts'] },
'import/resolver': { 'eslint-import-resolver-typescript': true },
},
errors: [{
message: "NotExported not found in './typescript'",
type: 'Identifier',
}],
}),
]
const parsers = ['typescript-eslint-parser']

if (semver.satisfies(linter.version, '>5.0.0')) {
parsers.push('@typescript-eslint/parser')
}

parsers.forEach((parser) => {
ruleTester.run('named', rule, {
valid: [
test({
code: 'import { MyType } from "./typescript"',
parser: parser,
settings: {
'import/parsers': { [parser]: ['.ts'] },
'import/resolver': { 'eslint-import-resolver-typescript': true },
},
}),
test({
code: 'import { Foo } from "./typescript"',
parser: parser,
settings: {
'import/parsers': { [parser]: ['.ts'] },
'import/resolver': { 'eslint-import-resolver-typescript': true },
},
}),
test({
code: 'import { Bar } from "./typescript"',
parser: parser,
settings: {
'import/parsers': { [parser]: ['.ts'] },
'import/resolver': { 'eslint-import-resolver-typescript': true },
},
}),
test({
code: 'import { getFoo } from "./typescript"',
parser: parser,
settings: {
'import/parsers': { [parser]: ['.ts'] },
'import/resolver': { 'eslint-import-resolver-typescript': true },
},
}),
test({
code: 'import { MyEnum } from "./typescript"',
parser: parser,
settings: {
'import/parsers': { [parser]: ['.ts'] },
'import/resolver': { 'eslint-import-resolver-typescript': true },
},
}),
test({
code: `
import { MyModule } from "./typescript"
MyModule.ModuleFunction()
`,
parser: parser,
settings: {
'import/parsers': { [parser]: ['.ts'] },
'import/resolver': { 'eslint-import-resolver-typescript': true },
},
}),
test({
code: `
import { MyNamespace } from "./typescript"
MyNamespace.NSModule.NSModuleFunction()
`,
parser: parser,
settings: {
'import/parsers': { [parser]: ['.ts'] },
'import/resolver': { 'eslint-import-resolver-typescript': true },
},
}),
],

invalid: [
test({
code: 'import { MissingType } from "./typescript"',
parser: parser,
settings: {
'import/parsers': { [parser]: ['.ts'] },
'import/resolver': { 'eslint-import-resolver-typescript': true },
},
errors: [{
message: "MissingType not found in './typescript'",
type: 'Identifier',
}],
}),
test({
code: 'import { NotExported } from "./typescript"',
parser: parser,
settings: {
'import/parsers': { [parser]: ['.ts'] },
'import/resolver': { 'eslint-import-resolver-typescript': true },
},
errors: [{
message: "NotExported not found in './typescript'",
type: 'Identifier',
}],
}),
],
})
})
})
20 changes: 18 additions & 2 deletions tests/src/rules/order.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { test } from '../utils'
import { test, testVersion } from '../utils'

import { RuleTester } from 'eslint'

Expand Down Expand Up @@ -1276,5 +1276,21 @@ ruleTester.run('order', rule, {
message: '`fs` import should occur before import of `async`',
}],
}),
],
// fix incorrect order with @typescript-eslint/parser
testVersion('>5.0.0', {
code: `
var async = require('async');
var fs = require('fs');
`,
output: `
var fs = require('fs');
var async = require('async');
`,
parser: '@typescript-eslint/parser',
errors: [{
ruleId: 'order',
message: '`fs` import should occur before import of `async`',
}],
}),
].filter((t) => !!t),
})
6 changes: 6 additions & 0 deletions tests/src/utils.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import path from 'path'
import { linter } from 'eslint'
import semver from 'semver'

// warms up the module cache. this import takes a while (>500ms)
import 'babel-eslint'
Expand All @@ -9,6 +11,10 @@ export function testFilePath(relativePath) {

export const FILENAME = testFilePath('foo.js')

export function testVersion(specifier, t) {
return semver.satisfies(linter.version) && test(t)
}

export function test(t) {
return Object.assign({
filename: FILENAME,
Expand Down