-
Notifications
You must be signed in to change notification settings - Fork 25
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
New major version -- what do we want to change #22
Comments
Overall, I support the project of slimming down the options.
|
You did a great job summarizing this. 👍
Since I didn't write the original plugin, I'm not sure about the edge cases. Though in general we need to keep in mind that auto detection can fail for unusual use cases (e.g. if somebody runs prettier programatically?). I'd say we apply auto detection (if that's possible) when
I think you're right, case-insensitive is probably the preferred approach here. But just to be clear, do you suggest that all type imports should come before value imports (
Personally I'd also put type import first if I have to do it manually.
Just for reference, could you post a sample of how your imports look like, and how your
Yeah, more and more packages are moving towards scopes and it's not too hard to image that sooner or later most if not all packages could be scoped.That was just a wild suggestion. I'm more concerned with a sensible default anyways, and |
@fbartho @blutorange thanks for the detailed proposals here. Overall, I think we're all in agreement, with perhaps a few small details to work out.
What problems have you been having? Maybe you can open a new issue for it?
Just curious, why do you both prefer that? My rationale for putting value imports first was that value imports feel more "important", and they're also often times shorter (especially including the
|
type-import-grouping
It's definitely subjective, but it feels like the very top things are the least important, because you're going up to check on them from reading the code and scanning back up to the references. Putting the
|
Yes, I consider resolving imported modules and applying TS specific logic to check whether an import is a type or a value to be beyond the scope of what this plugin can and should do.
That's really just my gut feeling. I don't look much at imports in general, but perhaps I'm just not working on large enough projects? As I've said, personally I only want a reasonable default (canonical) behavior I can apply to all of our projects, with the same configuration (if any) for all. If I had to give a reason, I'd put all And perhaps by the same token, I'd use the order But come to think of it, if somebody uses So: // mode: separate
import type { A, Y } from "a"
import { B, X } from "a"
// mode: mixed
import { type A, B, X, type Y } from "a" Other than that, I'd say we also consider how it's being done in various projects and what seems to be most common Several widely-used packages I looked at use eslint-plugin-simple-import-sort (https://github.com/mongodb/node-mongodb-native/blob/main/package.json#L60, prisma). That plugin has only one option:
Not sure how this plugin handles it, but as mentioned by the eslint-plugin-simple-import-sort, if we sort case-insensitively, we need to make sure that we break ties by falling back to case-sensitive sorting (or we end up with non-deterministic formatting). E.g. import { a } from "someTHING";
import { a } from "SOMEthing"; |
Let's discuss the ordering of the Good point about breaking ties with imports that differ only by capitalization. That's something we should check. I've opened #23 so we don't forget. |
Yes, let's how it goes. The main purpose of this issue was to find a direction for where we want to take this plugin, and it seems we all agree on that. |
How do we want to proceed? I'm happy to charge ahead on this. Proposal: Can we get #19 and #20 to merge on the understanding that we're not going to ship it that way, and then we build from there? |
Hey @blutorange @IanVS I still want to make progress on what we talked about! — Can we get #19 & #20 to merge, as additive options — that we’ll delete pretty quickly? I’d be happy to roll forwards with the other refactors to prepare a major release as we discussed up-thread? |
Sounds good. I'll finish reviewing your existing PRs as soon as I can. |
I'm preparing to address #22, and as the first step I've created a `next` branch for us to begin working on which will become version 4.0. This PR also lays some groundwork by updating some dependencies and modernizing a few things: - Typescript 4.8.4 -> 5.0.4 - Built files ES5 -> ES2021 (Node 16+) - Jest -> Vitest (tests run in 5 seconds vs 14) - `.npmignore` -> `files` in package.json (safer) - Some other minor dep updates Node 14 is going to be EOL at the end of this month, and I don't think there's a reason to keep shipping ES5, which is very old by now, so I set up the tsconfig to support Node 16. That's actually the only real user-facing change in this PR, and I'm willing to reconsider it if anyone feels differently about it.
Reference: #22 This is the first step towards removing some options from this plugin, to make it a bit more opinionated and easy to configure (and maintain). This PR removes the option for `importOrderBuiltinModulesToTop`, and instead sorts builtins to the top always. We could potentially add a special flag for use in `importOrder` if someone wants to control the order of where the builtins appear, but I'd like to avoid doing that unless it becomes necessary.
Reference #22 This removes the `importOrderCaseInsensitive` option, making sorts always case-insensitive.
Ref #22 This removes the `importOrderGroupNamespaceSpecifiers` option in an effort to simplify the plugin and make it easier to understand and set up. There's no replacement currently, but if we hear from lots of folks who really want this, I think we could re-implement it using a special term in `importOrder`. I haven't done that here, as I would prefer to keep it simple.
Ref #22 This removes the `importOrderGroupNamespaceSpecifiers`, and always sort the specifiers (i.e. the option is always turned on). I removed a few tests as well that are no longer useful due to removed options.
I wanted to remove
So instead, I'm going to experiment with enabling the option by default, with the possibility for the user to disable it if they're using an older version of TypeScript. Flow has supported the syntax forever, so it's not a problem there at least. |
We could offer a |
Ref: #22 This removes the `importOrderMergeDuplicateImports` option. I can't think of a reason you'd need to have multiple imports from the same module in different statements, and it can cause confusion if you do have them.
Hmmm, that's an interesting thought. Can you talk a bit more about how you might envision that working, @fbartho? If I understand you correctly, we'd add a setting like I think I like it. It should be clear to the user what the value should be set to (they don't have to make a decision), and still allows us to be opinionated about the formatting. I guess the issue would be what do to if the user doesn't supply a version. The safest thing would be to assume it's 4.4 or below, and let them opt into new features by specifying their version. That would avoid unintentional breaking changes in the future as well as new features are potentially released for newer versions. |
@IanVS You exactly understood what I was suggesting. For now this would be limited to this one edge case. I would suggest we say “absence means we’ll generate the most modern output”. It’s not like we have a habit or need to generally downgrade typescript-dependent syntax, so we may never use it again, but this way it’s not a flag that says “include option 45”. By defaulting to the most modern output, we can avoid having most users need to specify this. |
I see your point, and I considered defaulting to most modern, but I foresee that causing two problems:
By defaulting to the least-modern, we avoid those issues, at the cost of not merging type and value imports for TypeScript users unless they provide a version of 4.5 or above. In that situation, their code at least still works, and since we'll have very few options in the plugin by then, it'll be easy to discover and opt-in to that feature. |
You have me pretty convinced @IanVS -- I defer to your decision. For what it's worth, auto-detecting typescript version is as simple as: function loadTargetTSVersion({ importOrderTypescriptVersion }: PrettierOptions) {
if (importOrderTypescriptVersion != null) {
return importOrderTypescriptVersion;
}
try {
const ts = require("type" + "script");
// choose your favorite way to defeat a bundler.
// Alternatively `import("typescript")` would work if async is acceptable.
// ts.version '4.9.5'
// ts.versionMajorMinor '4.9'
return ts.version;
} catch (e) {
// Typescript is not installed
return "1.0.0";
}
} And if we auto-detect, then only people that use this plugin in a "multi-typescript" environment, or people with typescript only available as a |
That's an interesting approach to detecting the TS version, and I think it would work in most cases. However, it could return bad results if someone has multiple versions of typescript installed in their I guess the best of both worlds would be to auto-detect the version and still allow folks the ability to override the setting with their config. |
…ScriptVersion` (#67) Ref #22 This removes the `importOrderCombineTypeAndValueImports` option, and defaults merging to true for Flow projects (technically anything other than TypeScript, but Flow is the only one). For TypeScript, we need to be sure that we can use the `import {type Foo} from …` syntax, which was only added in 4.5. To that end, this adds a new option, `importOrderTypeScriptVersion`, which the user should set to the version of TS they're using in their project, and we will use that to generate appropriate import statements. And possibly in the future we can make other adjustments based on the TS version as well. Detecting the version automatically is tricky, but maybe we can try doing that sometime in the future as well. By default, we set the TS version to something ridiculously low, `1.0.0`, meaning that by default we won't combine type and value unless the user sets their version.
I think the last thing remaining that we talked about for 4.0 is a way to automatically detect which parser plugins should be used (#24). It seems like the current defaults are working for most users, or at least we haven't heard from users that it's a problem. I'm tempted to release 4.0 without that feature, and perhaps consider it together with automatically detecting the typescript version as we also discussed above. If that's the case, I think there are two more issues that we can look into and try to solve as part of 4.0:
Lastly, I think we should look through upstream issues/PRs/releases/discussions to see if there's anything we want to pull in or address here. Let me know if you think there's anything else I'm forgetting about before we can release 4.0. |
I think we can release 4.0 without #24 and address that later — if it’s a big pain point. It’s only a pain for new plugin adopters though, so we may not get many complaints. #9 and #54 seem related, and are indeed important. I think what’s going on is that comments in certain positions are considered “attached” to the import syntax node, and we either render that attachment wrong (injecting a new line) or reformat the comment, and eat a new line. |
If you have a little time, would you like to look into that and see if you can fix it? I can take a pass through the upstream repo to see if there's anything else important for us. |
Yeah, added a bunch of annoyingly bugged test cases, now to fix them all |
Now that #71 is merged, do we have any more outstanding work that we wanted to get done before 4.0.0? (note: trivial cleanup in #74) I don't think we to advertise prettier-3 support yet since that's still in alpha, and also, see: #75 (comment) |
I'm going to release another prerelease after reviewing your PRs, then the only other thing I planned to do was take a look through the upstream issues and PRs to see if there's anything we can quickly tackle. |
I almost forgot we wanted to change the default |
Some upstream issues/prs we might want to consider:
|
I don’t think we should do:
I don’t think we’re subject to trivago/prettier-plugin-sort-imports#203 — is that something we’re seeing? (Worth adding a test-case maybe?) No opinion on
|
No, I don't think that's the way to do it, but we could potentially use the
I didn't confirm yet, but I think that would be more likely to just cause an error to be thrown than to disable the plugin. And if they're using normal javascript, no plugins are needed to process the code, so there'd be no change. We could consider adding a
Perhaps. Or maybe we just need to do something like Vite does, and use |
Alright, I think we've done what we want to do for the 4.0 release. I'll close out this issue, and let the beta cook for a few days while before releasing 4.0 stable. Thanks for the excellent discussion and planning here in this issue! |
Regarding #4, now might be a good a time as any to start a new major release and get rid of some of the legacy weight. Especially now that the number of users is still rather low. Perhaps we can start by brainstorming what we would like to change.
As a general guideline, I also don't think we need to make a plugin that can be customized to suit for everybody's code style. For one thing, there are other plugins such as @trivago/prettier-plugin-sort-imports.
And, more importantly, prettier itself is already an opinionated code formatter that prescribes a certain code style. For reference, here's is their rationale: https://prettier.io/docs/en/option-philosophy.html
They only want options that are required for some purpose, such as to support external tools. But no options that are just people's opinions on how the code style should look like.
Also: people who need a very particular code style won't be using prettier, and in extension, they also wouldn't use this plugin. I beliebe prettier plugins should keep at least somewhat to the spirit of prettier. Having a single plugin that by now probably has accumulated more options than the program for which the plugin is meant feels a bit strange. Having many options also makes tests and maintenance a pain, since you now have to test various combinations of options, or get lots of bug reports if you don't.
Let's review the options we've got
true
?importOrderParserPlugins
, I feel like this should be the main option of this plugin, if not the only one.[]
, which I feel is a pretty bad default. It just sorts everything alphabetically, including relative imports etc.@scope
manually. Adding a new dependency now requires you to review and sometimes change the prettier config for this plugin.@scope/...
imports, builtin imports, and relative imports automatically.importOrder: ["builtins", "unscoped", "@ui", "relatives", "@typescript", "scoped" ]
For the new options proposed by #4
Two more options are definitely too much. If anything, since some people might prefer separate type imports, I'd propose a single option
importOrderMergeTypeImports
with two valuesseparate
andmixed
. Default beingmixed
.mixed
combines all type and value importsimport {foo, type bar} from "a"
separete
actively splits all type and value imports, ensuring a consistent style. So it would changeimport {foo, type bar} from "a"
intoimport {foo} from "a";
import type {bar} from "a"``Although I'd also be fine with not having this option and just defaulting to
mixed
.What we need to check
We should take a look at common, default ESLint / TypeScript ESLint options and check if they conflict with the way this plugins formats code.
The text was updated successfully, but these errors were encountered: