Skip to content

Commit 34484ad

Browse files
author
Josh Goldberg
authored
Refactored converters to have names match intent (#714)
* Refactored file structure to have names match intent * Lint disable * One last name fix for a merger * Fix merger/ruleMerger imports * Fixed up ruleEquivalents pipelines and tested it * Spruced up convertComments * Fix tsc again; start on docs * Update architecture docs * A few touchups
1 parent 6c72e6f commit 34484ad

File tree

488 files changed

+1756
-1586
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

488 files changed

+1756
-1586
lines changed

docs/Architecture.md

Lines changed: 0 additions & 68 deletions
This file was deleted.

docs/Architecture/Comments.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Comments
2+
3+
Comment conversions in `src/converters/comments/convertComments.ts` are the last root-level converter to be run.
4+
The `ruleEquivalents` map it receives is filled out with the rule equivalents from earlier converters, i.e. lint rule converters.
5+
6+
In general, its flow is:
7+
8+
1. If no comments are requested to be converted, immediately report it out and mark this as passed.
9+
2. Create the list of include and possibly exclude globs to search on.
10+
3. Search for files matching those globs to have their comments converted.
11+
4. Convert comments in the contents of each file, storing equivalents in a cache.
12+
5. Report out the results of converting the unique globbed file paths.
13+
14+
## File Manipulations
15+
16+
Source files are parsed into TypeScript files by `src/comments/parseFileComments.ts`, which then extracts their comment nodes.
17+
Those comments are parsed for TSLint rule disable or enable comments.
18+
19+
Comments that match will be rewritten in their their file to their new ESLint rule equivalent in `src/comments/replaceFileComments.ts`, as determined by:
20+
21+
1. First, if the `ruleEquivalents` cache received from configuration convertion has the TSLint rule's ESLint equivalents listed, those are used.
22+
2. Failing that, a comment-specific `ruleCommentsCache` is populated with rules converted ad-hoc with no arguments.

docs/Architecture/Editors.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Editors
2+
3+
Editor lint configurations are converted by `src/converters/editorConfigs/convertEditorConfig.ts`.
4+
Any setting that matches a known built-in TSLint setting will be replaced with the ESLint equivalent.
5+
6+
For now, only VS Code editor settings are accounted for.
7+
Eventually this will be refactored to allow other editors such as Atom.
8+
9+
1. An existing editor configuration is read from disk.
10+
2. If the existing configuration is not found or errored, nothing else needs to be done.
11+
3. Configuration settings are converted to their ESLint equivalents.
12+
4. Those ESLint equivalents are written to the configuration file.
13+
5. Results from converting are reported to the user.

docs/Architecture/Linters.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Linters
2+
3+
TSLint-to-ESLint linter configuration conversion is the first root-level converter run.
4+
Within `src/converters/lintConfigs/convertLintConfig.ts`, the following steps occur:
5+
6+
1. Raw TSLint rules are mapped to their ESLint equivalents.
7+
2. Those ESLint equivalents are deduplicated and relevant preset(s) detected.
8+
3. Those deduplicated rules and metadata are written to the output configuration file.
9+
4. A summary of conversion results is printed, along with any now-missing packages.
10+
11+
## Rule Conversion
12+
13+
The parts of linter configurations most users focus on are the rule converters.
14+
Those are run by `src/converters/lintConfigs/rules/convertRules.ts`, which takes the following steps on each original TSLint rule:
15+
16+
1. The raw TSLint rule is converted to a standardized format.
17+
2. The appropriate converter is run for the rule.
18+
3. If the rule is missing or the conversion failed, this is marked.
19+
4. For each output rule equivalent given by the conversion:
20+
* The output rule name is added to the TSLint rule's equivalency set.
21+
* The TSLint rule's config severity is mapped to its ESLint equivalent.
22+
* If this is the first time the output ESLint rule is seen, it's directly marked as converted.
23+
* If not, a rule merger is run to combine it with its existing output settings.
24+
25+
### Rule Converters
26+
27+
Each TSLint rule should output at least one ESLint rule as the equivalent.
28+
"Converters" for TSLint rules are located in `src/rules/converters/`, and keyed under their names by the map in `src/rules/converters.ts`.
29+
30+
Each converter for a TSLint rule takes an arguments object for the rule, and returns an array of objects containing:
31+
32+
- `rules`: At least one equivalent ESLint rule and options
33+
- `notices`: Any extra info that should be printed after conversion
34+
- `plugins`: Any plugins that should now be installed if not already
35+
36+
The `rules` output is an array of objects containing:
37+
38+
- `ruleName`: Equivalent ESLint rule name that should be enabled
39+
- `ruleArguments`: Any arguments for that ESLint rule
40+
41+
Multiple objects must be supported because some general-use TSLint rules can only be represented by two or more ESLint rules.
42+
For example, TSLint's `no-banned-terms` is represented by ESLint's `no-caller` and `no-eval`.
43+
44+
### Rule Mergers
45+
46+
It's possible that one ESLint rule will be output by multiple converters.
47+
"Mergers" for those ESLint rules should take in two configurations to the same rule and output the equivalent single configuration.
48+
These are located in `src/rules/mergers/`, and keyed under their names by the map in `src/rules/mergers.ts`.
49+
50+
For example, `@typescript-eslint/ban-types` spreads both arguments' `types` members into one large `types` object.
51+
52+
## Package Summaries
53+
54+
ESLint configurations are summarized based on extended ESLint and TSLint presets.
55+
56+
- If no output rules conflict with `eslint-config-prettier`, it's added in.
57+
- Any ESLint rules that are configured the same as an extended preset are trimmed.

docs/Architecture/README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Architecture
2+
3+
tslint-to-eslint-config is a heavily tested CLI app with application flow starting in `bin/tslint-to-eslint-config`:
4+
5+
1. `src/cli/main.ts`'s `main` is called with `process.argv` as the program arguments.
6+
* This file sets up all function dependencies and bound functions that call to each other.
7+
2. `src/cli/runCli.ts`'s `runCli` is called with those bound dependencies and raw arguments.
8+
9+
> See [Dependencies.md](./Dependencies.md) for more info on functions and their dependencies are bound together.
10+
11+
## CLI Runner
12+
13+
Within `runCli`:
14+
15+
1. CLI options are parsed from the raw arguments into a commands object.
16+
2. If the version should be printed, we do that and stop execution.
17+
3. Any existing linter and TypeScript configurations are read from disk.
18+
4. Each converter is run, halting execution if it fails.
19+
20+
### Converters
21+
22+
Within that flow, there are three "root-level" converters directly called by `runCli`, in order:
23+
24+
1. **[Linters.md](./Linters.md)**: Converting from an original TSLint configuration to the equivalent TSLint configuration.
25+
2. **[Editors.md](./Editors.md)**: Creating new IDE settings for ESLint equivalent to any existing TSLint settings.
26+
3. **[Comments.md](./Comments.md)**: Converting inline `tslint:disable` lint disable comments to their `eslint-disable` equivalents.

docs/Dependencies.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,8 @@ Suppose your method `myMethod`, should take in a `fileSystem`, a `string`, and a
6262
myMethod: SansDependencies<typeof myMethod>;
6363
};
6464
```
65+
66+
### Adapters
67+
68+
Global Node constructs as `console` are never written to directly by functions; instead, "adapter" wrappers are set up in `src/adapters/*.ts` and provided as dependencies to functions.
69+
This enables native calls to be directly tested in tests without stubbing out their global equivalents.

docs/Development.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@ Compile with `npm run tsc` and run tests with `npm run test`.
2121

2222
## Further Reading
2323

24-
- [Architecture](./Architecture.md): How the general app structure operates
24+
- [Architecture](./Architecture/README.md): How the general app structure operates
2525
- [Dependencies](./Dependencies.md): How functions pass and receive static dependencies
2626
- [Testing](./Testing.md): Unit tests

jest.config.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ module.exports = {
44
"!./src/**/*.d.ts",
55
"!./src/**/*.stubs.ts",
66
"!./src/adapters/*.ts",
7-
"!./src/rules/rulesConverters.ts",
8-
"!./src/editorSettings/editorSettingsConverters.ts",
9-
"!./src/rules/mergers.ts",
107
"!./src/cli/main.ts",
8+
"!./src/converters/editorConfigs/editorSettingsConverters.ts",
9+
"!./src/converters/lintConfigs/rules/ruleConverters.ts",
10+
"!./src/converters/lintConfigs/rules/ruleMergers.ts",
1111
],
1212
coverageThreshold: {
1313
global: {

0 commit comments

Comments
 (0)