-
Notifications
You must be signed in to change notification settings - Fork 889
Ordered imports grouping #4134
Ordered imports grouping #4134
Conversation
Thanks for your interest in palantir/tslint, @abierbaum! Before we can accept your pull request, you need to sign our contributor license agreement - just visit https://cla.palantir.com/ and follow the instructions. Once you sign, I'll automatically update this pull request. |
7cc27f4
to
daab755
Compare
@johnwiseheart @giladgray et al: Is there anything more I need to add before review? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this looks really good @abierbaum! just a handful of questions, nothing major
src/rules/orderedImportsRule.ts
Outdated
@@ -42,7 +42,7 @@ export class Rule extends Lint.Rules.AbstractRule { | |||
import * as bar from "b"; | |||
- Groups of imports are delineated by blank lines. You can use these to group imports | |||
however you like, e.g. by first- vs. third-party or thematically or can you can | |||
enforce a grouping of third-party, parent directories and the current directory.`, | |||
enforce a group order and content.`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
funky language here. "can you can" on line above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have cleaned up this language:
Groups of imports are delineated by blank lines. You can use this rule to group
imports however you like, e.g. by first- vs. third-party or thematically or
you can define groups based upon patterns in import path names.`
src/rules/orderedImportsRule.ts
Outdated
match: { type: "string" }, | ||
order: { type: "number" } | ||
}, | ||
required: ["match", "order"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can order default to index? so you can simply provide an already-ordered array in the simplest case.
whoa actually the simplest case then would be an array of match strings. so it' could be string[] | Object[]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated it to support passing a string[] or an Object[].
src/rules/orderedImportsRule.ts
Outdated
|
||
const defaultGroups: JsonGroupOption[] = [ | ||
{ name: "parent directories", match: "^[.][.]", order: 20 }, | ||
{ name: "current directory", match: "^[.]", order: 30 }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
prefer \.
over [.]
- more obvious
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree but as far as I can tell that isn't allowed in TS/JS inside a string passed to the RegExp.
For example:
> RegExp('^\.').test('foo')
> true
> RegExp('^[.]').test('foo')
> false
Looks like Javascript will process the "." escape character when assigning the string and just turn it into "." before it get's to the regex.
Other tools I saw that tried to do similar sorting ended up configuring it with [.][.] as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah good point on the string. how about \\.
? i guess that's the same length, but [.]
relies on the weird truth that .
in a character class is treated as the literal .
character, not the "match-anything" that it means in other contexts.
src/rules/orderedImportsRule.ts
Outdated
|
||
interface JsonGroupOption { | ||
name?: string; | ||
match: string | null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
null
is not documented above. is it valid in the options?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i might prefer not supporting null and expecting a .*
match-everything pattern. bit of an API question there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could see that. The reason I allowed match to null originally was an implementation detail that could probably be avoided now. I will change it and see how it works out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It worked out well so I removed it. I still use an defaultGroup object internally for unmatched values, but now I use match of /.*/
there.
src/rules/orderedImportsRule.ts
Outdated
const { | ||
"grouped-imports": isGrouped = false, | ||
"import-sources-order": sources = "case-insensitive", | ||
"named-imports-order": named = "case-insensitive", | ||
"module-source-path": path = "full", | ||
} = optionSet === undefined ? {} : optionSet; | ||
groups: groups = defaultGroups |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need for : groups
since the name is the same. please remove
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done. good catch.
src/rules/orderedImportsRule.ts
Outdated
@@ -299,49 +403,90 @@ class Walker extends Lint.AbstractWalker<Options> { | |||
} | |||
} | |||
|
|||
/** | |||
* Check all import blogs stopping at the first failure. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
import blocks?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed.
b19b7d2
to
1d560b9
Compare
@giladgray I think I addressed all your comments and also added support for the items you suggested. Thanks for taking the time to review this PR. Please let me know if you see anything else. |
1d560b9
to
c92e44c
Compare
@abierbaum please do not amend and force push commits that have already been reviewed. it ruins the diff and makes it hard to incrementally review. we squash everything to one commit when merging anyways, so the default branch is always clean. |
@giladgray no problem. Sorry about that, I didn’t know what convention was for this project. |
destroying history shouldn't be part of your default workflow 😄 |
@giladgray Any more changes need or is this good to go? |
i would prefer to use |
@giladgray Good idea. I made the changes. You will see in the diff I also added a space in the failure message to get separation between the last pattern name and the ending period of the sentence. This was to help make the message less confusing in cases like:
Let me know if you see anything else. Thanks for reviewing so quickly. |
@giladgray Anything else I can do to help get this finished off and merged? |
@giladgray Just checking in again on status of this PR. Our team is excited to get using it after it gets merged. |
@giladgray We have been using this now for a couple weeks in production with no issues. Do you think this could get merged in so it can make the next release? |
Any progress on getting this PR merged? It would really help my team's |
I don't know of anything left to do. We have been using it in production with a custom build of tslint for a month. I would like to get back to mainline though. Just waiting to hear from @giladgray or @johnwiseheart on acceptability of the PR. |
@giladgray and @johnwiseheart . Just checking in again on the status of this PR. If this can't land into tslint, let me know so I can put it into a separate extension project like vrsource-tslint-rules |
ebc0fa3
to
724d46d
Compare
@JoshuaKGoldberg I just fixed up the branch on top of the latest tslint:master. I had to rerun prettier to remove some merge conflicts. Anything else you need? |
@abierbaum great, nothing else from me! Other TSLint maintainers (read: with more experience maintaining) have been swamped lately so there's work going on trying to find more folks. I'm holding off from merging larger PRs for a while to give them a chance to either find a full-time maintainer or get to this themselves. I know that's not a particularly satisfying answer, and neither is the suggested workaround of publishing this a a standalone rule in your own npm package. But expect more soon! |
@JoshuaKGoldberg Ok. Thanks for the update. I know there are a number of us hoping to get some of these larger improvements through so we can start using them more widely in production. |
- Change the message shown when items are not grouped as expected The new message is more clear and understandable - Use a better default group name If a group has a regex and no name, the default name is now: /regex/ This makes it more clear in the output that it is a regex and helps to keep the boundaries of the regex string more clear.
This check is already handled by the check for groups needing to be sorted. The idea is that once the first block of imports is found that has an import that is out of order, then all future blocks also have blocks out of order. So instead of flagging all blocks we just flag the first block that is causing the issue and provide a fix that will fix all blocks. This makes the case for manually fixing the import ordering much more clear because people can solve one item at a time. The automattic fixing is also more clear because we don't end up with multiple failures that have the same fix.
@adidahiya I think I am ready for you to take a look at the changes I made in response to your review. Thank you for the great comments. As far as running this change on the tslint codebase, I am more than happy to do that but I must admit I don't know how to run tslint with fix across the tslint codebase. If you can point me in the right direction I can submit a PR after this change gets through. |
@abierbaum the |
@adidahiya Looks like you did the lint fix update already on master (95d9d95). Thanks for getting that done and thank you so much for the review. I hope the new code ends up useful for everyone. |
@abierbaum yeah, I realized that the open PR (#4420) had no conflicts so it was ready to go as-is. thanks for the PR |
Thanks for this, it's awesome work. Do we know a date when this gonna be deployed? 🚢 |
Do you know when it gonna be release? |
* master: (60 commits) Added tslint-brunch to the list of 3rd party tools (palantir#4251) Switch to tslint-plugin-prettier, clean up rule options config syntax (palantir#4488) Enable grouped-imports for ordered-imports rule in tslint:all config (palantir#4420) Ordered imports grouping (palantir#4134) trailing-comma: check for a closing parenthesis (palantir#4457) Update index.md (palantir#4473) [bugfix] `no-unsafe-any`: allow implicitly downcasting `any` to `unknown` (palantir#4442) Add v5.12.1 changelog Bump version to 5.12.1 Fix quotemark avoid-template issues (palantir#4408) Skip linting JSON files entirely (palantir#4001) Fix strict-type-predicate for unknown (palantir#4444) restrict increment-decrement fixer while fixing the postfix unary expressions (palantir#4415) Mention file names in script parse failures (palantir#4397) Revert breaking change to tslint:recommended, update tslint:latest (palantir#4404) Fix quotemark avoid-template issues (palantir#4408) Bump tslint dev dependency to 5.12.0 (palantir#4452) Skip linting JSON files entirely (palantir#4001) Fix strict-type-predicate for unknown (palantir#4444) [README] Update link for Webstorm (palantir#4450) ...
@jukben @scote Thanks for the feedback. I am very interested in a release as well. Our team is currently running an old version of tslint from a branch with this change. I am guessing @adidahiya or @JoshuaKGoldberg are the right people to ask about next release timeframes. |
@abierbaum #4482 (comment) I just got this response from @adidahiya to my PR so I guess these two will go together pretty soonish! 🙌 |
cannot wait, please release it! @adidahiya 🌼 |
Waiting for release |
@adidahiya Any news on a release date or is there a way to use latest HEAD from npm so people can start using this update? |
[OT] @abierbaum yep, you can use git repo url with NPM, Yarn. But I'd like to see release as well. Although I'm afraid it's better to explore ways how to lint TS with ESLint, which going to be a more preferred way in the future. |
@jukben I am hoping they do another release before holding up for moving to ESLint. I don't have the time right now to try to learn a new system and port the rules our team relies up. :( As far as using git repo url, I haven't found a way to do that with tslint. When I have tried the packages are not built correctly for use. Have you had luck doing that? If so I would love to know how. |
Sorry @abierbaum you are right, there has to be build process, my bad. Yeah, I hope for the same, I'm waiting for release as well. I might end up forking this... |
Concerning the TSLint to ESLint migration I'd like to add that ESLint still doesn't support some of the concepts present in TSLint and that many rules are still missing, including external ones. So even you have the time it wouldn't make sense to completely migrate over to ESLint now as you'd potentially lose many of the rules in-use. An example is the Angular linting package Codelyzer which is still in TSLint and will only be ported once some TSLint features are merged into ESLint. So given that it may take at least a few months to get ESLint all the missing features of TSLint it will then at least take some more months for the rest of the linting packages like Codelyzer to also migrate to ESLint. So would be nice to just have this one final release before the inevitable long wait before we are able to actually migrate to ESLint without having regressions. |
We are still committed to supporting TSLint for a few months and will continue to do releases to push out PRs like this. "Migrating to ESLint without having any regressions" is of concern to the TSLint community and all of Palantir's TypeScript codebases as well; we want to make that process as smooth as possible. I started this new issue thread to answer questions and clear up doubts about the deprecation path / migration path to ESLint: #4534. Thanks for your patience as I work to get this PR released. |
I just released v5.13.0, please try it out and open new issues if you have problems with this feature. thanks again @abierbaum! |
@abierbaum Awesome job! I have a couple questions:
I would like to put them in their own group.
Before:
After:
|
@abierbaum it'll be very useful if those features supported in typescript-eslint |
PR checklist
Overview of change:
This PR adds support for configuring custom groups with the ordered-import rule.
Previously the rule would only group into third-party, parent directories, and current directory. This change allows for fully customizing the grouping but still keeps a default that provides exactly the same as was there previously.
An example configuration would be something like this:
This would enforce an ordering where all rxjs and angular imports would come in first group sorted, then all application imports, then all additional third-party imports, then relative parent imports, and finally current directory imports.
This provides the flexibility to support just many use cases and can be adapted easily.
There are other projects such as vscode import-sorter and a few unsupported tslint extensions that try to address this issue but it seems like this is something that would best be handled by tslint since it can already reorder imports.
One of the goals of this change is to allow using the fixer to automatically reformat imports on the fly. So for example when using vscode or another editor with tslint support the user could enable the fixer to be run upon file save and have tslint restructure all imports to meet the given team's conventions.
Is there anything you'd like reviewers to focus on?
I tried to add some solid test examples but I may have missed a corner case. Please let me know if you see something I should check.
I tried to keep the changes to a minimum, but I did refactor some of the existing code to make the grouping implementation a bit more clear and straight forward. I also added some comments to clarify a few places in the code that tripped me up. If you would like these stripped back out just let me know.
Note: There are a number of code style changes that were made by prettier as part of the precommit hook that is now part of tslint. (just so you know I didn't go try to change the original authors coding style :) )
CHANGELOG.md entry:
[enhancement]
ordered-imports
now supports a groups option to provide custom grouping rules.