-
Notifications
You must be signed in to change notification settings - Fork 889
Proposal: Conditional lint configuration #3447
Comments
If you put your tests and production code in separate directories, you wouldn't need such a feature. If you do not provide a config file as CLI argument, TSLint uses the nearest I get that many Angular and React projects put tests in the same directory as the corresponding production code. Personally I think this is a bad practice. I've seen enough people (accidentally) importing symbols from tests in production code. IMO the proposed feature adds a lot of complexity. The implementation may not be that hard, but it makes the config file difficult to read and understand. We'd also need to discuss how it works when extending configurations. In which order are the overrides applied? |
True, you could just separate the code, but it hurts ergonomics. Either you have
and That path gets ugly in our monorepo where files are often very deep in the tree. or you have
which is too many tslint.json files |
On the topic of overrides: I'd say the overrides apply in the same order rules are applied. I don't know what that is, and I couldn't find documentation, but intuitively I'd think it'd be like this: // a.json
{"rules": {"foo": [true, 1]}}
// b.json
{"rules": {"foo": [true, 2]}}
// c.json
{
"extends": ["a.json", "b.json"],
"rules": {"foo": [true, 3]}
} would result in rule "foo" having the argument 3. If that rule wasn't in For overrides, I'd expect the same order to be applied. It makes sense to me to use the last override that matches the supplied regex, taking into account the order in which 'extends' rules are considered. A single file example: {
"rules": {"a": [true, 1]},
"override": [
{"match": "test|spec", "rules": {"a": [true, 2]}},
{"match": "test", "rules": {"a": [true, 3]}}
]
} would have value 2 for rule "foo" when the file path contains "spec", 3 if it contains "test", and 1 otherwise. (obviously, not a very useful set of overrides, since "test" might as well be omitted from the first, but you get the idea) Does that make sense and answer your question? |
@calebegg There are some other edge cases to consider: // a.json
{
"rules": {"foo": [true, 1]},
"override": {"match": "test|spec", "rules": {"foo": [true, 2]}}
}
// b.json
{
"extends": "./a.json"
"rules": {"foo": false}
} What's the expected result?
Same here, what is the expected result: // c.json
{
"rules": {"foo": [true, 1]},
"override": {"match": "test|spec", "rules": {"foo": false}}
}
// d.json
{
"extends": "./a.json"
"rules": {"foo": {"options": 2}},
"override": {"match": "test|spec", "rules": {"foo": {"options": 3}}}
} |
Just a random thought: Why not just match the patterns in order and (partially) override the previous match: {
"rules": { // same as "*"
"rule-one": true,
"rule-two": true
},
"*.js?(x)": { // we could get rid of "jsRules" with this
"rule-two": false
},
"*.{t,j}sx": {
"jsx-rule": true
},
"*.spec.*" {
"rule-one": false
}
} Some examples:
I just don't know where to put this inside the config. The same level as Another problem is extending configs. If we apply all overrides from the base config and then the overrides from the current config, it's rather difficult to understand. It also makes the code more complex. Currently the configs are merged during parsing. With this proposal the final config is only known when we have a file name. |
Hello, This feature will be great. I think Eslint is supporting this feature: https://eslint.org/docs/user-guide/configuring#configuration-based-on-glob-patterns. So, syntax and semantic could be the same, to avoid confusion. |
@minomikula Thanks a lot. I searched the ESLint docs before but didn't find this section. Their approach makes sense. To summarize:
There are some things to consider when porting this behavior to TSLint:
Thoughts or comments @adidahiya @calebegg @alexeagle @minomikula? |
Oh, wow, yeah, that approach seems reasonable to me. I should have also looked for prior art. |
This would be an awesome addition! The eslint approach works great when conditionally disabling some rules in test files. |
@calebegg do you still plan to push this forward when you find time? |
Yes, I'd definitely like to work on this. @ajafff Are you generally happy with starting with the ESLint approach and iterating in PRs? Or do you think there are design questions we should talk about first?
It makes sense to me to deprecate, but I don't feel very strongly either way. |
@calebegg I'm fine with the ESLint approach. I implemented a very similar concept in my POC linter runtime https://github.com/fimbullinter/wotan/tree/master/packages/wotan#overrides Integration in the current TSLint API could be tough, because currently it merges all configurations while parsing. This needs to be deferred until the file's name is known and needs to be done for every file. This is certainly a breaking API change. |
@calebegg @mitchlloyd @ajafff @alexeagle i see little benefit in this feature over simply nesting |
Nesting does not solve the issues discussed here. Many people do want their tests in the same directory structure as the code it tests, and there is simply no good way to do that with tslint right now. |
There are loads of projects putting spec files in the same directory as sources. This has become a best practice in many environments, Angular CLI generates a project structure like that etc. I don’t think it’s realistic nesting tslint config files is going to work for all these people. |
I agree that my project structure should not be dictated by a linting tool. Instead the linting tool should support common existing patterns. Colocating tests and source files is a common pattern. |
@giladgray The requested change supports a scenario where users put their tests and production files next to each other like this:
How would "nesting |
@giladgray angular guidelines recommend you put your tests alongside your files. So 99% of angular projects do this. Due to tslint being backwards every angular project I worked on had issues. Your last comment is confounding and myopic. If you can't/don't want to accept this incredibly useful suggestion then I think you are far too conservative to be the one making decisions for us on such an important project. This issue has been making our angular project work difficult for years. |
@ohjames Let’s stay on topic and avoid veering toward personal attacks, okay? Suggesting that someone isn’t fit to maintain their own project is not the way to influence OSS, and certainly isn’t going to help what we’re all arguing for here. |
It makes sense to want overrides for files that don't fit into a nested structure as mentioned above. It seems to me like @giladgray's comment was intended to determine if there was still significant community interest in this change, given that there had been no activity on this issue for more than 6 months. This is specifically evidenced by his comment on the open PR (#3708):
@ohjames I'd suggest you reconsider your comment - as @DanielSchaffer mentioned, personal attacks are not going to help you here, or anywhere in open source software. Everyone is trying their best to create good, reliable and feature-rich software, and attacking people in no way contributes to that. |
Is there any update on this topic? |
As I've commented on the related #1063, my use case would be that using tslint-microsoft-contrib currently bombs on Vue single-file components for some rules. This might either be a Vue issue, or a TSLint issue, and those teams might or might not get around to fixing the specific problem - disabling the offending rules until that happens seems like a simple workaround that's not too cumbersome. Compared to either having to add the same disable directive to every single .vue file, and update it in all those places as the rule support changes. It also doesn't make sense to split up a project into .vue and .ts files, it would be a very awkward structure. |
This issue is currently flagged as 'Needs proposal', but I think we already a proposal in #3447 (comment)? |
@RoystonS @ajafff's proposal mentioned a few loose ends that should be addressed:
There should also be consensus from the folks in the palantirtech org on this before moving forward, since it's a pretty substantial feature. |
Just stumbled upon this myself, and just want to voice my interest for this kind of feature. We ended up relaxing some linting rules that affect production code and let's see how it goes. ): |
I'd love to see this feature |
subscribing - Also need this. |
I need this so badly :( |
Same here! We are using typescript with Vuejs and our unit test files are not together in a tests directory but everywhere along component source code. |
Would love to see this feature, we're currently using a slightly wonky setup that results in vscode highlighting different linting errors than what our command line lint highlights to get around this issue. |
This comment has been minimized.
This comment has been minimized.
I Propose to apply the concept git repository uses for files in the .gitIgnore... to the tsLint rules. Usage of your current hierarchal position as context to the linter, along with an override file, when linting a particular subdirectory. Then you can include or exclude, setup any config at any directory level you want. e.g. |
@redevill It does help people writing test in a |
Agreed - but with minor change: (Which could be automated with template generator (CLI Style) The idea could still work. |
Huge fan of this proposal. YES PLEASE! My preference would be the Overrides concept. |
Btw, given the deprecation announcement of tslint, I can't really imagine that such a large change will be made at this stage, and my team's moving over to eslint, which already has per-rule + per-file override facilities. |
The aforementioned announcement: https://medium.com/palantir/tslint-in-2019-1a144c2317a9 |
We use an Angular project. We need the overrides concept. Otherwise, it is pain to manage |
There are some situations where we'd like to conditionally enforce a lint check based on whether the code being linted is test code or not. For instance, we'd like to ban 'any' from production code, since it's unsafe. But in tests, 'any' can be useful to supply fake or mock implementations of services, or to cast through it so you can call private methods. Or we might want to ban a different set of methods in tests vs in production code, for example.
What I propose is a way to conditionally enable lint checks based on a regex match on the filename. This could also be useful for turning off lint checks for certain directories (containing "legacy" code, for instance), or for .tsx or .d.ts files, etc.
Here are some syntax strawman ideas; I'm open to suggestions too.
Sections object
"Other" would be things that don't match any of the regexes. This is pretty concise, but I think the readability of the rules section suffers a bit.
"Override" rules
(this should perhaps be an array, to allow for multiple overrides too).
The text was updated successfully, but these errors were encountered: