Skip to content
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

Allow skipping checks with @("nolint(...)") and @nolint("...") #936

Merged
merged 17 commits into from
Oct 13, 2023

Conversation

ricardaxel
Copy link
Contributor

@ricardaxel ricardaxel commented Oct 8, 2023

Related #935

Here is the basic idea I had in mind to locally disable checks : one can attach a user defined attribute to any declaration (function declaration, variable declaration, ..). If this happens, the given check is disabled for the given declaration.

Example :

@("NOLINT(useless_initializer)")
int a = 0; // No warning emited

One could have done that with comment (like clang-tidy does) but I think UDAs are great since they are directly included in AST. They have a limitation though : according to libdparse D grammar, attributes can only be paired with 'declaration2'. So this would be a little hard to disable checks at other levels than declaration. For example, delete_check is applied on a deleteExpression.

Looking forward your reviews, I will try yo extend this proof of concept to all warnings in next few days if you're are okay with this direction.

@ricardaxel ricardaxel marked this pull request as draft October 8, 2023 16:10
Copy link
Member

@WebFreak001 WebFreak001 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you also add a check to the ModuleDeclaration that checks for the UDAs and then just returns or continues with recursion? Also people might use whitespace within NOLINT() and maybe we just want to lowercase it instead of uppercasing, since non-string UDA equivalents would be all lower-case or camel-case

_messages.insert(Message(diagnostic, supplemental, key, getName(), autofixes));
}

void reenableErrorMessage()
in(this.errorMsgDisabled > 0)
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you have mixed spaces and tabs everywhere in this file, try to stay consistent with the existing style (only tabs in this case)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you use any formatter ? I can't find any config, this would be easier to maintain style conventions.

src/dscanner/analysis/useless_initializer.d Show resolved Hide resolved
@ricardaxel
Copy link
Contributor Author

ricardaxel commented Oct 10, 2023

Also people might use whitespace within NOLINT() and maybe we just want to lowercase it instead of uppercasing, since non-string UDA equivalents would be all lower-case or camel-case

No problem, I'll draft a second version with regex (case insensitive and ignoring spaces)

EDIT: Done Here --> 39757e1 and 06b5ff5

I was thinking about some forms that could be accepted :

- @("nolint(useless_initializer)") // skip useless_initializer check
- @("nolint(useless_assert_check, useless_assert_check)") // skip useless_initializer and useless_assert_check checks
- @("nolint") // skip ALL checks
- @("nolint(useless_*)") // skip all check that begin with 'useless'

@ricardaxel
Copy link
Contributor Author

can you also add a check to the ModuleDeclaration that checks for the UDAs and then just returns or continues with recursion?

Not sure to understand well. Do you mean something like that ?

override void visit(const ModuleDeclaration mod)
{
    if(hasNoLintUda(mod))
       return;
    else
      accept(this)
}

@WebFreak001
Copy link
Member

re module declaration: yes like that

also I think all your suggestions for UDA match format are nice and would be useful

@ricardaxel ricardaxel force-pushed the ignore-lint-uda branch 5 times, most recently from e294481 to f2497f1 Compare October 11, 2023 20:28
@ricardaxel ricardaxel marked this pull request as ready for review October 11, 2023 20:29
@ricardaxel
Copy link
Contributor Author

Soo I think this is a first mergeable version.

I think I'll keep other improvements for futures PRs, especially :

  • adding support and unittest for all checks one by one
  • adding support for @("nolint"), @("nolint(useless_*)"), ...

Just a question : what do you expect when a malformed UDA is given ? For example @nolint("useles_initializer") (it contains a typo). I guess raising an error is pretty extrem, and dump a warning could be confusing with real D-Scanner warning, no ? For now, such cases are silently ignored

@WebFreak001
Copy link
Member

we could probably add a dscanner checker to check for misconfigured dscanner UDAs later

Copy link
Member

@WebFreak001 WebFreak001 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need to make the nolint check check for error message IDs (in most linters this is the enum KEY member)

If you want to keep the optimization that it doesn't traverse into code, in the base analyzer class you probably want to add a abstract string[] getAvailableErrorKeys(); to be able to check all of them where you currently only check for the check name, however there would need to be another check in the actual addErrorMessage code that will check before emitting the warning for real.

src/dscanner/analysis/nolint.d Outdated Show resolved Hide resolved
src/dscanner/analysis/useless_initializer.d Outdated Show resolved Hide resolved
src/dscanner/analysis/useless_initializer.d Outdated Show resolved Hide resolved
src/dscanner/analysis/style.d Outdated Show resolved Hide resolved
@ricardaxel ricardaxel force-pushed the ignore-lint-uda branch 3 times, most recently from 2cfc347 to 7456fa0 Compare October 12, 2023 19:53
@ricardaxel
Copy link
Contributor Author

we need to make the nolint check check for error message IDs

I totally missed that one analyzer could handle multiple checks. I made some refacto to handle this.
The optimization to avoid the traversal is gone for now, and will probably be delayed for a future PR.

ah the idea was here that the nolint would apply to the entire file

I also completely misunderstood that, this is fixed :)

Hope I didn't miss anything else

@ricardaxel ricardaxel force-pushed the ignore-lint-uda branch 2 times, most recently from 57b0119 to 0a50cae Compare October 12, 2023 20:32
@ricardaxel ricardaxel force-pushed the ignore-lint-uda branch 2 times, most recently from a830b3f to 959e469 Compare October 12, 2023 20:39
@WebFreak001 WebFreak001 changed the title Skip lint when detection UDA @("NOLINT(...)") Allow skipping checks with @("nolint(...)") and @nolint("...") Oct 13, 2023
@WebFreak001 WebFreak001 merged commit 1e8f1ec into dlang-community:master Oct 13, 2023
19 checks passed
@ricardaxel ricardaxel deleted the ignore-lint-uda branch October 13, 2023 07:34
@AndrejMitrovic
Copy link

Great to see this feature in and thanks so much for working on this!

But I can't seem to silence this error for example:

// test.d
@("nolint(dscanner.exception_check)")
void main() {
    try {
    } catch (Error) {
    }
}
$ dscanner lint ./test.d

.\test.d(4:14): Warning: Catching Error or Throwable is almost always a bad idea. (exception_check)
    } catch (Error) {
             ^^^^^

Using master of dscanner.

Also it would be nice to have this feature documented in --help, I only found out about it by accident.

And does #935 need closing?

@ricardaxel
Copy link
Contributor Author

Great to see this feature in and thanks so much for working on this!

But I can't seem to silence this error for example:

// test.d
@("nolint(dscanner.exception_check)")
void main() {
    try {
    } catch (Error) {
    }
}

To silence an error, one has to use its ID (and not its name !), which is in this case dscanner.suspicious.catch_em_all, as we can see here. This is pretty confusing since the name and the key ID can be different, and this is the name which is used in the dscanner.ini configuration file...

Also it would be nice to have this feature documented in --help, I only found out about it by accident.

And does #935 need closing?

The 'nolint' feature is pretty experimental, it has not been widely tested and would require some more polish (see previous messages of this PR + PR #941. I personally think that one should also work on adding coherence between names and IDs. So there is still some work to do). I think this is the reason for the lack of documentation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants