-
-
Notifications
You must be signed in to change notification settings - Fork 40
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
feat: add control for executing rules based on Svelte/SvelteKit context #980
Conversation
🦋 Changeset detectedLatest commit: 0e28cc1 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
commit: |
@ota-meshi |
packages/eslint-plugin-svelte/src/rules/no-export-load-in-svelte-module-in-kit-pages.ts
Outdated
Show resolved
Hide resolved
Hi @baseballyama, I am looking at the three alternative proposals (this one, #957, #943) and I am a little bit torn. Implementation-wise, I like this one the most because it "just works". However, I think this one will also be the hardest to explain to the users (such as me :D) clearly, because it somewhat boils down to "This will magically disable rules, trust us". In this "understandability" regard, I think the approach with separate rulesets seems easier to grasp. However, it introduces additional complexity for users, which is probably not the best choice. Additionally, I expect that at some point in the future, obsolete versions of Svelte will be dropped altogether, so it'd be great to design this such that the users don't need to re-do their config once again at that point. |
@marekdedic This issue can also be addressed by changing perspectives. Instead of seeing it as “magic,” we can treat it as a feature to eliminate false positives. For example, if a user is only using Svelte 5, there shouldn’t be any reports related to SvelteKit rules. However, AST-based inspections may still produce false positives. With this PR, false positives can be completely eliminated. Similarly, enabling SvelteKit-specific rules without actually using SvelteKit can also cause issues. This PR prevents such problems as well. I plan to completely review the rules included in the recommended config from scratch after merging this PR. |
Yeah, I agree... Let me rephrase: I think this is probably the best of the 3 alternatives. At the same time, I think it will require a good explanation in the documentation so that the users that do want to configure eslint understand what's happening in the recommended config. |
Sorry, looking at it more, I have a question to the design of this feature: Why is the checking of applicability of the rule left to the rule implementation? Isn't it something that could be configured in the rule meta and checked automatically? It seems to me that that would be less error-prone (especially when 3rd party contributors such as me add new rules) and maybe could be used to indicate the support in docs as well? But maybe I am missing something, I don't know the rule meta stuff that good... |
Is it possible to control whether a rule is invoked by accessing its meta information at runtime? (AFAIK, there is no way) export default createRule('rule-name', {
meta: {
executeCondition: {
svelte: [5],
isKitRule: true,
kitRouteTypes: ["+page.svelte", "+page.js"]
},
...
},
create(context) {
return executeIf(this.meta.executeCondition, (context) => {
// ... implement rule ...
});
}
}); We can easily check that |
I think it might be possible by injecting the check here:
|
Ahh. Nice! I will update the PR tomorrow. (It’s already night in Japan, so I’m going to sleep.) |
…n and SvelteKit routes etc.
7d2c565
to
cb70fea
Compare
@marekdedic What do you think about the current implementation? I want to add tests somehow but before that I would like to ask your opinion. |
|
||
export type SvelteContext = { | ||
svelteVersion: string; | ||
fileType: '.svelte' | '.svelte.[js|ts]'; |
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.
Hmm, I don't like the design of having separate fileType
and svelteKitFileType
. I see 2 ways to do it better:
- Merge them
- Don't provide these, but go conceptually one level further - why would we want to know the file type? Maybe what we actually want to know is things like
- Are we in a SFC file?
- Are we in the server context?
- etc.
I think the second solution is more work (and requires quite careful design), but ultimately serves us better, because rules are fundamentally going to be enabled based on the properties of the current context/file, not based on its type...
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.
At here, it’s better to keep things simple and store only basic information. This is because the definition of "context" can change depending on the rules. For example, we might want to create a rule that prevents placing files like xxx.svelte.js
in the same directory as +page.svelte
.
Another example is that xxx.svelte.js
might be used for implementing composables, and we might want to enforce a rule that their names must start with useX
.
In short, since the definition of "context" depends on the rules, it’s better to just manage file types here.
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'm still not convinced. I think we should instead add something like a fileContext
field where we add some information about the file and we can possibly extend it in the future. I am not sure your first example is possible in eslint, as it operates on files separately. But anyway, we would probably need a separate flag for .svelte.js/ts
files. But I don't think it is useful to have a way to distinguish +page.js
, +page.server.js
, +layout.js
and +layout.server.js
- what you would actually want in most situations is 2 flags - "Is this a layout file?" and "Is this a server-only file?"
Does that make sense to you or am I being too convoluted?
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 is one of specific example why "Is this a layout file?" and "Is this a server-only file" is not enough.
#438
This rule should check only +layout.(js|ts)
. (+layout.svelte
should not check.)
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.
Hmm, maybe I'm wrong (I haven't used SvelteKit server-side yet), but #438 should also check +page.(js|ts)
, no? Then it's exactly what I've been getting at :D The differentiator isn't really a list of filename suffixes, but a role the file plays in SvelteKit...
Anyway, if my change is not accepted, then I would like to think a little bit more about how fileType
and svelteKitFileType
interact...
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.
And yes, the list of "file role flags" would probably be longer and would need to expand over time and some rules would check multiple flags at once...
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.
And yes, the list of "file role flags" would probably be longer and would need to expand over time and some rules would check multiple flags at once...
Yes. In that case, we can add helper functions for common validation patterns.
I think it’s best to start with basic functionality and then add more convenient features later if they prove to be valuable.
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.
Hmm, maybe I'm wrong (I haven't used SvelteKit server-side yet), but #438 should also check +page.(js|ts),
Yes. We need to check +page.(js|ts)
also, but what I wanted to say is that "Is this a layout file?" and "Is this a server-only file" is not enough.
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.
Yes. In that case, we can add helper functions for common validation patterns.
Hmm, yeah, that's probably a good enough alternative.
I was thinking about the fileType
a little bit more as well. I get that in svelteKitFileType
, the list of file suffixes makes sense, but I think it gets confusing with fileType
pretty quickly - if I understand it correctly, a +page.svelte
would havea file type .svelte
and +page.js
would have a file type of .svelte.js
- which is a little counterintuitive. Maybe fileType
could have values "component"|"plain"
or something similar? Then it wouldn't give the illusion of being a filename extension, which it isn't in case of SvelteKit files...
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.
rename to svelteFileType
.
if I understand it correctly, a +page.svelte would havea file type .svelte and +page.js would have a file type of .svelte.js
No. .svelte.[js|ts]
will be used for xxx.svelte.js
or xxx.svelte.ts
. But not +page.js
,
.svelte
and .svelte.[js|ts]
is taken from the docs. (I intended svelteFileType
to be determined by the file extension.)
https://svelte.dev/docs/svelte/svelte-js-files
svelteFileType
should be null for +page.js
, so I fixed this bug.
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.
Thanks for the changes, unfortunately, I have more questions/comments... But I think we are getting there, good work on this!
|
||
export type SvelteContext = { | ||
svelteVersion: string; | ||
fileType: '.svelte' | '.svelte.[js|ts]'; |
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.
Hmm, maybe I'm wrong (I haven't used SvelteKit server-side yet), but #438 should also check +page.(js|ts)
, no? Then it's exactly what I've been getting at :D The differentiator isn't really a list of filename suffixes, but a role the file plays in SvelteKit...
Anyway, if my change is not accepted, then I would like to think a little bit more about how fileType
and svelteKitFileType
interact...
|
||
export type SvelteContext = { | ||
svelteVersion: string; | ||
fileType: '.svelte' | '.svelte.[js|ts]'; |
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.
And yes, the list of "file role flags" would probably be longer and would need to expand over time and some rules would check multiple flags at once...
if ( | ||
isNotSatisfies(svelteContext.svelteVersion, condition.svelteVersions) || | ||
isNotSatisfies(svelteContext.fileType, condition.fileTypes) || | ||
isNotSatisfies(svelteContext.runes, condition.runes) || |
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.
runes
are a boolean, isNotSatisfies
doesn't work for that...
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 already changed it to array. How can I make "runes" even more plural?😅
Thank you for the review again! Some points that felt like personal preferences were not changed at this time. There are still a few remaining points to discuss, so I’d appreciate your input on those as well. It would be great if we could merge this today. That would bring us significantly closer to v3! |
Hi @baseballyama, I think we are getting there (honestly now it's just a few small details). Thanks for taking the time! |
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.
One final thing and then we're done :)
186c8ab
to
afd422d
Compare
eab3041
to
f686b4d
Compare
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.
The new SvelteContext
is much clearer, thanks! Unfortunately, that means there's new things for me not to understand :D
export type SvelteContext = ( | ||
| ({ | ||
svelteVersion: '3/4'; | ||
} & { |
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.
Why is this split into 2?
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.
For more strict typing. Reinforcing the types eliminates improbable patterns.
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 don't understant, I thought {a: string} & {b: int}
is equal to {a: string; b: int}
, isn't it?
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.
updated: 0e28cc1
| { | ||
svelteFileType: '.svelte' | '.svelte.[js|ts]'; | ||
/** If a user uses a parser other than `svelte-eslint-parser`, `undetermined` will be set. */ | ||
runes: boolean | 'undetermined'; |
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.
Hmm, I'm having a hard time understanding the difference between null
and 'undetermined'
here - they both mean we couldn't figure it out, no?
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.
We can automatically recognize this via typing.
- null: The concept of runes itself does not exist.
- true: Using runes
- false: Not using runes
- undetermined: The concept of runes exists but I don't know if it is used
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, ok. Is there any menaingful difference between runes don't exist
and not using runes
? Because they semm to me to be equivalent in all useful aspects...
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 think only facts should be expressed here, as usefulness depends on context
Thank you for taking the time to review this! I think we are in agreement on almost areas and will merge to move forward.👍 |
Great, thanks for the work on this, I think this design is pretty great now :) |
This PR introduces the
getSvelteContext
function. This function will be invoked at the beginning of every rule before the release of eslint-plugin-svelte v3. It enables the conditional execution of linting based on factors such as the Svelte version SvelteKit route etc. By doing so, it allows users can userecommended
config regardless of the Svelte version they are using. As a result, unnecessary rules will be effectively disabled automatically.After merging this PR and applying the changes to all rules, I plan to update the recommended config and release v3. Consequently, I will close #957.