aaron.ballman added inline comments.
================ Comment at: clang-tidy/ClangTidyDiagnosticConsumer.cpp:839-840 + case NolintCommentType::Nolint: + Message = "there is no diagnostics on this line, " + "the NOLINT comment is redundant"; + break; ---------------- xgsa wrote: > aaron.ballman wrote: > > xgsa wrote: > > > aaron.ballman wrote: > > > > xgsa wrote: > > > > > aaron.ballman wrote: > > > > > > I don't think the user is going to care about the distinction > > > > > > between no diagnostics being triggered and the expected diagnostic > > > > > > not being triggered. Also, it's dangerous to claim the lint comment > > > > > > is redundant because it's possible the user has NOLINT(foo, bar) > > > > > > and while foo is not triggered, bar still is. The NOLINT comment > > > > > > itself isn't redundant, it's that the check specified doesn't occur. > > > > > > > > > > > > I would consolidate those scenarios into a single diagnostic: > > > > > > "expected diagnostic '%0' not generated" and "expected diagnostic > > > > > > '%0' not generated for the following line". > > > > > > > > > > > > One concern I have with this functionality is: how should users > > > > > > silence a lint diagnostic that's target sensitive? e.g., a > > > > > > diagnostic that triggers based on the underlying type of size_t or > > > > > > the signedness of plain char. In that case, the diagnostic may > > > > > > trigger for some targets but not others, but on the targets where > > > > > > the diagnostic is not triggered, they now get a diagnostic they > > > > > > cannot silence. There should be a way to silence the "bad NOLINT" > > > > > > diagnostics. > > > > > > I don't think the user is going to care about the distinction > > > > > > between no diagnostics being triggered and the expected diagnostic > > > > > > not being triggered. Also, it's dangerous to claim the lint comment > > > > > > is redundant because it's possible the user has NOLINT(foo, bar) > > > > > > and while foo is not triggered, bar still is. The NOLINT comment > > > > > > itself isn't redundant, it's that the check specified doesn't occur. > > > > > > > > > > > > I would consolidate those scenarios into a single diagnostic: > > > > > > "expected diagnostic '%0' not generated" and "expected diagnostic > > > > > > '%0' not generated for the following line". > > > > > > > > > > This branch of `if (NolintEntry.first.CheckName == > > > > > NolintCommentsCollector::AnyCheck)` reports only about > > > > > `NOLINT`/`NOLINTNEXTLINE` comments without check list, so I suppose > > > > > it's fair to claim that this comment is redundant (we have already > > > > > checked that no single check reported diagnostics on the line). The > > > > > `else`-branch reports the diagnostics for the definite check in a > > > > > list in case of `NOLINT(foo, bar)` (actually, if neither `foo` nor > > > > > `bar` checks reported diagnostics for the line, there will be a few > > > > > diagnostics from `nolint-usage` - not sure if it's good, but it seems > > > > > acceptable). That is why, I suppose, it is necessary to distinct > > > > > these cases. > > > > > > > > > > > One concern I have with this functionality is: how should users > > > > > > silence a lint diagnostic that's target sensitive? e.g., a > > > > > > diagnostic that triggers based on the underlying type of size_t or > > > > > > the signedness of plain char. In that case, the diagnostic may > > > > > > trigger for some targets but not others, but on the targets where > > > > > > the diagnostic is not triggered, they now get a diagnostic they > > > > > > cannot silence. There should be a way to silence the "bad NOLINT" > > > > > > diagnostics. > > > > > > > > > > There is such mechanism: it is possible to specify `// > > > > > NOLINT(nolint-usage)` or `//NOLINT(check1, check2, nolint-usage) to > > > > > silence the `nolint-usage`-mechanism. Please, see tests for details > > > > > and more examples. > > > > Can you provide an example where this distinction will make a > > > > difference to the user and help clarify a confusing situation? I cannot > > > > think of one, and it would be nice to simplify this code. > > > > > > > > Thank you for the explanation about nolint-usage. This is not > > > > terminology I've seen before -- is this your invention, or is it a > > > > documented feature for NOLINT comments? > > > >> Can you provide an example where this distinction will make a > > > >> difference to the user and help clarify a confusing situation? I > > > >> cannot think of one, and it would be nice to simplify this code. > > > > > > Example for the diagnostics emitted in the `if`-branch: > > > ``` > > > class A2 { explicit A2(int i); }; // NOLINT > > > => warning: there is no diagnostics on this line, the NOLINT comment is > > > redundant > > > ``` > > > Thus, the whole NOLINT comment should be removed. > > > > > > Example for the diagnostics emitted in the `else`-branch: > > > ``` > > > // Case: NO_LINT for the specific check on line with an error on another > > > check. > > > class A4 { A4(int i); }; // NOLINT(misc-unused-parameters, > > > google-explicit-constructor) > > > => warning: there is no diagnostics for the 'misc-unused-parameters' > > > check on this line, the NOLINT comment is redundant > > > ``` > > > In this case, only misc-unused-parameters check should be removed from > > > the list, but not the whole NOLINT. > > > > > > Note also that if in the last example there is only > > > misc-unused-parameters in the NOLINT checks list, the diagnostics will be > > > the same. However, I suppose it's acceptable, because even if a user > > > removed only a check name from the check list without removing NOLINT > > > itself, clang-tidy will suggest removing NOLINT itself on the next run. > > > > > > > > > >> Thank you for the explanation about nolint-usage. This is not > > > >> terminology I've seen before -- is this your invention, or is it a > > > >> documented feature for NOLINT comments? > > > > > > It's my invention, I suppose, from the user point of view it's logical to > > > consider this mechanism as a check. > > Thank you for the examples, but I don't think they would add any > > clarification for the user, either. That said, I think we could collapse > > all four diagnostics into: "there are no diagnostics %select{|for '%2'}0 on > > %select{this|the next}1 line" where %0 distinguishes between NOLINT with > > and without an explicit check name, %1 distinguishes between NOLINT and > > NOLINTNEXTLINE, and %2 is the name of the check in question (if any). > > > > >> Thank you for the explanation about nolint-usage. This is not > > >> terminology I've seen before -- is this your invention, or is it a > > >> documented feature for NOLINT comments? > > > It's my invention, I suppose, from the user point of view it's logical to > > > consider this mechanism as a check. > > > > I think we should devise a better way of expressing this unless there's > > industry practice suggesting a specific term or syntax. nolint-usage isn't > > very discoverable. Whatever we wind up with, it should work naturally for > > constructs like your first example. In the first example, diagnosing that > > NOLINT is redundant only makes sense in some circumstances, such as when > > the construct is in a source file that is not compiled with > > google-explicit-constructor enabled. However, if the code is in a shared > > header file where some (but not all) source code is checked with > > google-explicit-constructor enabled, it serves a purpose and removing it > > would be incorrect. The same holds for NOLINT(check). > > > > Ultimately, I think that diagnosing NOLINT on a line that issues no > > diagnostics should not be enabled by default. It's highly likely that the > > NOLINT directive is due to reasons unknowable to the implementation, and > > suggesting the user remove the comment seems unhelpful. My example above is > > one plausible case where NOLINT may serve a purpose. Another example is > > code checked by clang-tidy as well as other tools; the NOLINT may be > > silencing the other tools. I think it should take extra work by the user to > > enable this functionality in a catch-all manner -- either via different > > syntax or enabled only through an explicit flag. > > > > I think that diagnosing NOLINT(check-name) when that diagnostic is not > > triggered is useful by default because the user is explicitly expecting a > > diagnostic by name. However, I think the user needs an almost-trivial way > > to silence the "not triggered" diagnostic on a case-by-case basis. Target > > specific diagnostics as well as shared code are both examples of situations > > where the NOLINT comment may be accurate but for situations unknown to > > clang-tidy. Telling the user to remove the NOLINT comment would be the > > wrong thing to do. > If to look at cpplint, which I suppose, NOLINT syntax was taken from, it also > reports diagnostics for incorrect usage of NOLINT as messages in category > 'readability/nolint' [1]. > > In spite of the fact, that `nolint-usage` is technically not a check, it > mimics the behavior of a simple check: it is only enabled if `nolint-usage` > is enabled via `-check` option (explicitly or via *) or configuration; it > reports diagnostics for this category and allows this diagnostics to be > suppressed via NOLINT. The only missing thing for now is documentation page > for the `nolint-usage` check and I am going to work on this after this patch > is approved. Thus, I don't think that this approach is not discoverable and > it seems more natural than adding a separate command line option and a > separate way of suppressing NOLINT diagnostics. > > I agree that this diagnostics will only be useful if NOLINT comments are > carefully maintained exactly for clang-tidy. I don't think that if they are > also added for another tool, the check names or even diagnostics lines will > match. Thus, for these cases the check just shouldn't be enabled in > configuration. The same thing is for headers. I suppose, that typically the > list of checks is the same for the whole project, thus diagnostics for > headers won't be an issue, but if it is not the case, the `nolint-usage` > check could just be disabled for some modules. Anyway, I don't see the way to > determine if a header contains the diagnostics been included from the other > source files. > > If it is necessary, some configuration options could be added for this check > (e.g. an option to check only `NOLINT` comments in source files, but no > headers; or to check only `NOLINT` comments with/without explicit list of > checks specification). > > [1] - > https://github.com/google/styleguide/blob/9663cabfeeea8f1307b1acde59471f74953b8fa9/cpplint/cpplint.py#L577 > In spite of the fact, that nolint-usage is technically not a check That's part of what concerns me about this in terms of discoverability and usability -- it's not a real check but it sort of behaves like one. Does this get listed with -list-checks? If the user passes `-nolint-*` on the command line does it still get disabled? Also, all of this is predicated by the fact that these nolint warnings are going to trigger in such a way that sometimes needs to be silenced. What I think isn't very intuitive is that the recommended way to silence a nolint-comment-related diagnostic is to use another nolint comment to disable reporting bugs with nolint comments. However, documentation can help with that, so perhaps it's not bad. ================ Comment at: clang-tidy/ClangTidyDiagnosticConsumer.cpp:117 +const StringRef ClangDiagnosticsPrefix = "clang-diagnostic-"; +const StringRef NolintCheckName = "readability-nolint-usage"; +enum class NolintCommentType : uint8_t { ---------------- Why "readability"? That module is generally for code readability issues like redundant code or naming conventions. I think this should probably be in "misc" or perhaps "bugprone". Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D41326 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits