Skip to content

Commit 24fe35f

Browse files
author
Josh Goldberg
authored
Defaulted --comment globs to --typescript settings (#707)
1 parent 85cacbc commit 24fe35f

File tree

7 files changed

+115
-22
lines changed

7 files changed

+115
-22
lines changed

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,22 @@ Each of these flags is optional:
5454
#### `comments`
5555

5656
```shell
57-
npx tslint-to-eslint-config --comments 'src/**/*.ts'
57+
npx tslint-to-eslint-config --comments
5858
```
5959

6060
_Default: none_
6161

62-
File glob path(s) to convert [TSLint rule flags](https://palantir.github.io/tslint/usage/rule-flags) to [ESLint inline comments](https://eslint.org/docs/user-guide/configuring#disabling-rules-with-inline-comments) in.
62+
Indicates to convert from [TSLint rule flags](https://palantir.github.io/tslint/usage/rule-flags) to [ESLint inline comments](https://eslint.org/docs/user-guide/configuring#disabling-rules-with-inline-comments).
6363
Comments such as `// tslint:disable: tslint-rule-name` will be converted to equivalents like `// eslint-disable eslint-rule-name`.
6464

65+
If passed without arguments, respects the `excludes`, `files`, and `includes` in your TypeScript configuration.
66+
67+
Alternately, you can specify which files to convert comments in as globs:
68+
69+
```shell
70+
npx tslint-to-eslint-config --comments 'src/**/*.ts'
71+
```
72+
6573
#### `config`
6674

6775
```shell

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"commander": "6.1.0",
1515
"eslint-config-prettier": "6.11.0",
1616
"glob": "7.1.6",
17+
"minimatch": "^3.0.4",
1718
"strip-json-comments": "3.1.1",
1819
"tslint": "6.1.3",
1920
"typescript": "4.0.2"
@@ -27,6 +28,7 @@
2728
"@types/eslint-config-prettier": "6.11.0",
2829
"@types/glob": "7.1.3",
2930
"@types/jest": "26.0.13",
31+
"@types/minimatch": "^3.0.3",
3032
"@types/node": "12.12.21",
3133
"@typescript-eslint/eslint-plugin": "4.1.0",
3234
"@typescript-eslint/parser": "4.1.0",

src/cli/runCli.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,7 @@ export const runCli = async (
1919
const command = new Command()
2020
.storeOptionsAsProperties(false)
2121
.usage("[options] <file ...> --language [language]")
22-
.option(
23-
"--comments [files]",
24-
"convert tslint:disable rule flags in globbed files (experimental)",
25-
)
22+
.option("--comments [files]", "convert tslint:disable rule flags in files (experimental)")
2623
.option("--config [config]", "eslint configuration file to output to")
2724
.option("--editor [editor]", "editor configuration file to convert")
2825
.option("--eslint [eslint]", "eslint configuration file to convert using")

src/comments/convertComments.test.ts

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const createStubDependencies = (
55
overrides: Partial<ConvertCommentsDependencies> = {},
66
): ConvertCommentsDependencies => ({
77
convertFileComments: jest.fn(),
8-
globAsync: jest.fn().mockResolvedValue(["src/index.ts"]),
8+
globAsync: jest.fn().mockResolvedValue(["src/a.ts", "src/b.ts"]),
99
...overrides,
1010
});
1111

@@ -24,7 +24,7 @@ describe("convertComments", () => {
2424
});
2525
});
2626

27-
it("returns an error when --comments is given as a boolean value", async () => {
27+
it("returns an error when --comments is given as a boolean value without a TypeScript configuration", async () => {
2828
// Arrange
2929
const dependencies = createStubDependencies();
3030

@@ -38,6 +38,57 @@ describe("convertComments", () => {
3838
});
3939
});
4040

41+
it("includes TypeScript files when --comments is given as a boolean value with a TypeScript files configuration", async () => {
42+
// Arrange
43+
const dependencies = createStubDependencies({
44+
globAsync: jest.fn().mockResolvedValue(["src/a.ts"]),
45+
});
46+
47+
// Act
48+
const result = await convertComments(dependencies, true, {
49+
files: ["src/a.ts"],
50+
});
51+
52+
// Assert
53+
expect(result).toEqual({
54+
data: ["src/a.ts"],
55+
status: ResultStatus.Succeeded,
56+
});
57+
});
58+
59+
it("includes TypeScript inclusions when --comments is given as a boolean value with a TypeScript include configuration", async () => {
60+
// Arrange
61+
const dependencies = createStubDependencies();
62+
63+
// Act
64+
const result = await convertComments(dependencies, true, {
65+
include: ["src/*.ts"],
66+
});
67+
68+
// Assert
69+
expect(result).toEqual({
70+
data: ["src/a.ts", "src/b.ts"],
71+
status: ResultStatus.Succeeded,
72+
});
73+
});
74+
75+
it("excludes TypeScript exclusions when --comments is given as a boolean value with a TypeScript excludes configuration", async () => {
76+
// Arrange
77+
const dependencies = createStubDependencies();
78+
79+
// Act
80+
const result = await convertComments(dependencies, true, {
81+
exclude: ["src/b.ts"],
82+
include: ["src/*.ts"],
83+
});
84+
85+
// Assert
86+
expect(result).toEqual({
87+
data: ["src/a.ts"],
88+
status: ResultStatus.Succeeded,
89+
});
90+
});
91+
4192
it("returns an error when there are no file path globs", async () => {
4293
// Arrange
4394
const dependencies = createStubDependencies();
@@ -95,7 +146,7 @@ describe("convertComments", () => {
95146

96147
// Assert
97148
expect(result).toEqual({
98-
data: ["src/index.ts"],
149+
data: ["src/a.ts", "src/b.ts"],
99150
status: ResultStatus.Succeeded,
100151
});
101152
});

src/comments/convertComments.ts

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
import minimatch from "minimatch";
2+
13
import { GlobAsync } from "../adapters/globAsync";
24
import { SansDependencies } from "../binding";
5+
import { TypeScriptConfiguration } from "../input/findTypeScriptConfiguration";
36
import { ResultStatus, ResultWithDataStatus } from "../types";
47
import { separateErrors, uniqueFromSources, isError } from "../utils";
58
import { convertFileComments } from "./convertFileComments";
@@ -9,29 +12,48 @@ export type ConvertCommentsDependencies = {
912
globAsync: GlobAsync;
1013
};
1114

12-
const noGlobsResult: ResultWithDataStatus<string[]> = {
13-
errors: [new Error("--comments requires file path globs to be passed.")],
14-
status: ResultStatus.Failed,
15-
};
16-
1715
export const convertComments = async (
1816
dependencies: ConvertCommentsDependencies,
1917
filePathGlobs: true | string | string[] | undefined,
18+
typescriptConfiguration?: TypeScriptConfiguration,
2019
): Promise<ResultWithDataStatus<string[] | undefined>> => {
20+
let fromTypeScriptConfiguration: TypeScriptConfiguration | undefined;
21+
22+
if (filePathGlobs === true) {
23+
if (!typescriptConfiguration) {
24+
return {
25+
errors: [
26+
new Error(
27+
"--comments indicated to convert files listed in a tsconfig.json, but one was not found on disk or specified by with --typescript.",
28+
),
29+
],
30+
status: ResultStatus.Failed,
31+
};
32+
}
33+
34+
filePathGlobs = [
35+
...(typescriptConfiguration.files ?? []),
36+
...(typescriptConfiguration.include ?? []),
37+
];
38+
fromTypeScriptConfiguration = typescriptConfiguration;
39+
}
40+
2141
if (filePathGlobs === undefined) {
2242
return {
2343
data: undefined,
2444
status: ResultStatus.Succeeded,
2545
};
2646
}
27-
28-
if (filePathGlobs === true) {
29-
return noGlobsResult;
30-
}
31-
3247
const uniqueFilePathGlobs = uniqueFromSources(filePathGlobs);
3348
if (uniqueFilePathGlobs.join("") === "") {
34-
return noGlobsResult;
49+
return {
50+
errors: [
51+
new Error(
52+
"--comments found no files. Consider passing no globs to it, to default to all TypeScript files.",
53+
),
54+
],
55+
status: ResultStatus.Failed,
56+
};
3557
}
3658

3759
const [fileGlobErrors, globbedFilePaths] = separateErrors(
@@ -45,7 +67,13 @@ export const convertComments = async (
4567
}
4668

4769
const ruleConversionCache = new Map<string, string | undefined>();
48-
const uniqueGlobbedFilePaths = uniqueFromSources(...globbedFilePaths);
70+
const uniqueGlobbedFilePaths = uniqueFromSources(...globbedFilePaths).filter(
71+
(filePathGlob) =>
72+
!fromTypeScriptConfiguration?.exclude?.some((exclude) =>
73+
minimatch(filePathGlob, exclude),
74+
),
75+
);
76+
4977
const fileFailures = (
5078
await Promise.all(
5179
uniqueGlobbedFilePaths.map(async (filePath) =>

src/conversion/convertLintConfig.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,10 @@ export const convertLintConfig = async (
6161
}
6262

6363
// 5. Files to transform comments in have source text rewritten using the same rule conversion logic
64-
const commentsResult = await dependencies.convertComments(settings.comments);
64+
const commentsResult = await dependencies.convertComments(
65+
settings.comments,
66+
originalConfigurations.data.typescript,
67+
);
6568

6669
// 6. A summary of the results is printed to the user's console
6770
await dependencies.reportConversionResults(settings.config, summarizedConfiguration);

src/input/findTypeScriptConfiguration.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ export type TypeScriptConfiguration = {
88
lib?: string[];
99
target?: string;
1010
};
11+
exclude?: string[];
12+
files?: string[];
13+
include?: string[];
1114
};
1215

1316
const defaultTypeScriptConfiguration = {
@@ -29,6 +32,7 @@ export const findTypeScriptConfiguration = async (
2932
return rawConfiguration instanceof Error
3033
? rawConfiguration
3134
: {
35+
...rawConfiguration,
3236
compilerOptions: {
3337
...defaultTypeScriptConfiguration.compilerOptions,
3438
...rawConfiguration.compilerOptions,

0 commit comments

Comments
 (0)