From 37279e056d92f4f84b8b004b32d60c57609b3d2a Mon Sep 17 00:00:00 2001 From: Braden Napier Date: Tue, 19 Mar 2019 15:18:50 -0700 Subject: [PATCH 1/4] support export type named exports from typescript --- src/ExportMap.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ExportMap.js b/src/ExportMap.js index 61900db03..20ed009d7 100644 --- a/src/ExportMap.js +++ b/src/ExportMap.js @@ -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': From 3134ad36e1658b2bd0f0677aaeccbc07299d1e34 Mon Sep 17 00:00:00 2001 From: Andrew Schmadel Date: Mon, 1 Apr 2019 14:02:14 -0400 Subject: [PATCH 2/4] Test both typescript-eslint-parser and @typescript-eslint/parser augments https://github.com/benmosher/eslint-plugin-import/pull/1304 --- README.md | 14 +-- package.json | 3 +- tests/src/core/getExports.js | 1 + tests/src/rules/named.js | 190 ++++++++++++++++++----------------- tests/src/rules/order.js | 16 +++ 5 files changed, 124 insertions(+), 100 deletions(-) diff --git a/README.md b/README.md index 7695ac368..3e60280a8 100644 --- a/README.md +++ b/README.md @@ -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: @@ -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 diff --git a/package.json b/package.json index 51fd070ed..601f6a4f4 100644 --- a/package.json +++ b/package.json @@ -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", @@ -69,7 +70,7 @@ "rimraf": "^2.6.3", "sinon": "^2.4.1", "typescript": "^3.2.2", - "typescript-eslint-parser": "^21.0.2" + "typescript-eslint-parser": "^22.0.0" }, "peerDependencies": { "eslint": "2.x - 5.x" diff --git a/tests/src/core/getExports.js b/tests/src/core/getExports.js index 80e9d843e..00c96f40f 100644 --- a/tests/src/core/getExports.js +++ b/tests/src/core/getExports.js @@ -315,6 +315,7 @@ describe('ExportMap', function () { const configs = [ // ['string form', { 'typescript-eslint-parser': '.ts' }], ['array form', { 'typescript-eslint-parser': ['.ts', '.tsx'] }], + ['array form', { '@typescript-eslint/parser': ['.ts', '.tsx'] }], ] configs.forEach(([description, parserConfig]) => { diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js index 569f3158a..0cf9a07b6 100644 --- a/tests/src/rules/named.js +++ b/tests/src/rules/named.js @@ -254,99 +254,103 @@ 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', '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', + }], + }), + ], + }) }) }) diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js index 23487dac9..c338bd388 100644 --- a/tests/src/rules/order.js +++ b/tests/src/rules/order.js @@ -1276,5 +1276,21 @@ ruleTester.run('order', rule, { message: '`fs` import should occur before import of `async`', }], }), + // fix incorrect order with @typescript-eslint/parser + test({ + 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`', + }], + }), ], }) From f0eb91761de3c5f42f4b7c8d742873dfa9366335 Mon Sep 17 00:00:00 2001 From: Andrew Schmadel Date: Wed, 3 Apr 2019 10:31:08 -0400 Subject: [PATCH 3/4] skip @typescript-eslint/parser tests on older eslint versions --- package.json | 1 + tests/src/core/getExports.js | 7 ++++++- tests/src/rules/named.js | 9 +++++++-- tests/src/rules/order.js | 6 +++--- tests/src/utils.js | 6 ++++++ 5 files changed, 23 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 601f6a4f4..2cafc4fe5 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,7 @@ "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": "^22.0.0" diff --git a/tests/src/core/getExports.js b/tests/src/core/getExports.js index 00c96f40f..7207ff34a 100644 --- a/tests/src/core/getExports.js +++ b/tests/src/core/getExports.js @@ -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' @@ -315,9 +317,12 @@ describe('ExportMap', function () { const configs = [ // ['string form', { 'typescript-eslint-parser': '.ts' }], ['array form', { 'typescript-eslint-parser': ['.ts', '.tsx'] }], - ['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 () { diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js index 0cf9a07b6..a3f55b35e 100644 --- a/tests/src/rules/named.js +++ b/tests/src/rules/named.js @@ -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' @@ -256,7 +257,11 @@ ruleTester.run('named (export *)', rule, { context('Typescript', function () { // Typescript - const parsers = ['@typescript-eslint/parser', 'typescript-eslint-parser'] + 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, { diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js index c338bd388..dde5ae6cb 100644 --- a/tests/src/rules/order.js +++ b/tests/src/rules/order.js @@ -1,4 +1,4 @@ -import { test } from '../utils' +import { test, testVersion } from '../utils' import { RuleTester } from 'eslint' @@ -1277,7 +1277,7 @@ ruleTester.run('order', rule, { }], }), // fix incorrect order with @typescript-eslint/parser - test({ + testVersion('>5.0.0', { code: ` var async = require('async'); var fs = require('fs'); @@ -1292,5 +1292,5 @@ ruleTester.run('order', rule, { message: '`fs` import should occur before import of `async`', }], }), - ], + ].filter((t) => !!t), }) diff --git a/tests/src/utils.js b/tests/src/utils.js index 52e2d23cd..70c5971a6 100644 --- a/tests/src/utils.js +++ b/tests/src/utils.js @@ -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' @@ -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, From 49af9d80754b6ed7fb1adb2848d37e228b6a448b Mon Sep 17 00:00:00 2001 From: Andrew Schmadel Date: Mon, 8 Apr 2019 11:53:32 -0400 Subject: [PATCH 4/4] Remove @typescript-eslint/parser before running ESLint