mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-12 19:01:55 +00:00
Add support for NOLINT and NOLINTNEXTLINE comments mentioning specific check names.
Supports a comma-separated list of check names to be disabled on the given line. Also supports * as a wildcard to disable all lint diagnostic messages on that line. Patch by Anton (xgsa). llvm-svn: 320713
This commit is contained in:
parent
f902ef0a5d
commit
3d161ab6f4
@ -21,6 +21,7 @@
|
||||
#include "clang/AST/ASTDiagnostic.h"
|
||||
#include "clang/Basic/DiagnosticOptions.h"
|
||||
#include "clang/Frontend/DiagnosticRenderer.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
@ -290,7 +291,38 @@ void ClangTidyDiagnosticConsumer::finalizeLastError() {
|
||||
LastErrorPassesLineFilter = false;
|
||||
}
|
||||
|
||||
static bool LineIsMarkedWithNOLINT(SourceManager &SM, SourceLocation Loc) {
|
||||
static bool IsNOLINTFound(StringRef NolintDirectiveText, StringRef Line,
|
||||
unsigned DiagID, const ClangTidyContext &Context) {
|
||||
const size_t NolintIndex = Line.find(NolintDirectiveText);
|
||||
if (NolintIndex == StringRef::npos)
|
||||
return false;
|
||||
|
||||
size_t BracketIndex = NolintIndex + NolintDirectiveText.size();
|
||||
// Check if the specific checks are specified in brackets.
|
||||
if (BracketIndex < Line.size() && Line[BracketIndex] == '(') {
|
||||
++BracketIndex;
|
||||
const size_t BracketEndIndex = Line.find(')', BracketIndex);
|
||||
if (BracketEndIndex != StringRef::npos) {
|
||||
StringRef ChecksStr =
|
||||
Line.substr(BracketIndex, BracketEndIndex - BracketIndex);
|
||||
// Allow disabling all the checks with "*".
|
||||
if (ChecksStr != "*") {
|
||||
StringRef CheckName = Context.getCheckName(DiagID);
|
||||
// Allow specifying a few check names, delimited with comma.
|
||||
SmallVector<StringRef, 1> Checks;
|
||||
ChecksStr.split(Checks, ',', -1, false);
|
||||
llvm::transform(Checks, Checks.begin(),
|
||||
[](StringRef S) { return S.trim(); });
|
||||
return llvm::find(Checks, CheckName) != Checks.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool LineIsMarkedWithNOLINT(SourceManager &SM, SourceLocation Loc,
|
||||
unsigned DiagID,
|
||||
const ClangTidyContext &Context) {
|
||||
bool Invalid;
|
||||
const char *CharacterData = SM.getCharacterData(Loc, &Invalid);
|
||||
if (Invalid)
|
||||
@ -301,8 +333,7 @@ static bool LineIsMarkedWithNOLINT(SourceManager &SM, SourceLocation Loc) {
|
||||
while (*P != '\0' && *P != '\r' && *P != '\n')
|
||||
++P;
|
||||
StringRef RestOfLine(CharacterData, P - CharacterData + 1);
|
||||
// FIXME: Handle /\bNOLINT\b(\([^)]*\))?/ as cpplint.py does.
|
||||
if (RestOfLine.find("NOLINT") != StringRef::npos)
|
||||
if (IsNOLINTFound("NOLINT", RestOfLine, DiagID, Context))
|
||||
return true;
|
||||
|
||||
// Check if there's a NOLINTNEXTLINE on the previous line.
|
||||
@ -329,16 +360,17 @@ static bool LineIsMarkedWithNOLINT(SourceManager &SM, SourceLocation Loc) {
|
||||
--P;
|
||||
|
||||
RestOfLine = StringRef(P, LineEnd - P + 1);
|
||||
if (RestOfLine.find("NOLINTNEXTLINE") != StringRef::npos)
|
||||
if (IsNOLINTFound("NOLINTNEXTLINE", RestOfLine, DiagID, Context))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool LineIsMarkedWithNOLINTinMacro(SourceManager &SM,
|
||||
SourceLocation Loc) {
|
||||
static bool LineIsMarkedWithNOLINTinMacro(SourceManager &SM, SourceLocation Loc,
|
||||
unsigned DiagID,
|
||||
const ClangTidyContext &Context) {
|
||||
while (true) {
|
||||
if (LineIsMarkedWithNOLINT(SM, Loc))
|
||||
if (LineIsMarkedWithNOLINT(SM, Loc, DiagID, Context))
|
||||
return true;
|
||||
if (!Loc.isMacroID())
|
||||
return false;
|
||||
@ -355,7 +387,8 @@ void ClangTidyDiagnosticConsumer::HandleDiagnostic(
|
||||
if (Info.getLocation().isValid() && DiagLevel != DiagnosticsEngine::Error &&
|
||||
DiagLevel != DiagnosticsEngine::Fatal &&
|
||||
LineIsMarkedWithNOLINTinMacro(Diags->getSourceManager(),
|
||||
Info.getLocation())) {
|
||||
Info.getLocation(), Info.getID(),
|
||||
Context)) {
|
||||
++Context.Stats.ErrorsIgnoredNOLINT;
|
||||
// Ignored a warning, should ignore related notes as well
|
||||
LastErrorWasIgnored = true;
|
||||
|
@ -261,6 +261,8 @@ Improvements to clang-tidy
|
||||
- `hicpp-use-nullptr <http://clang.llvm.org/extra/clang-tidy/checks/hicpp-use-nullptr.html>`_
|
||||
- `hicpp-vararg <http://clang.llvm.org/extra/clang-tidy/checks/hicpp-vararg.html>`_
|
||||
|
||||
- Added the ability to suppress specific checks (or all checks) in a ``NOLINT`` or ``NOLINTNEXTLINE`` comment.
|
||||
|
||||
Improvements to include-fixer
|
||||
-----------------------------
|
||||
|
||||
|
@ -250,6 +250,56 @@ An overview of all the command-line options:
|
||||
value: 'some value'
|
||||
...
|
||||
|
||||
:program:`clang-tidy` diagnostics are intended to call out code that does
|
||||
not adhere to a coding standard, or is otherwise problematic in some way.
|
||||
However, if it is known that the code is correct, the check-specific ways
|
||||
to silence the diagnostics could be used, if they are available (e.g.
|
||||
bugprone-use-after-move can be silenced by re-initializing the variable after
|
||||
it has been moved out, misc-string-integer-assignment can be suppressed by
|
||||
explicitly casting the integer to char, readability-implicit-bool-conversion
|
||||
can also be suppressed by using explicit casts, etc.). If they are not
|
||||
available or if changing the semantics of the code is not desired,
|
||||
the ``NOLINT`` or ``NOLINTNEXTLINE`` comments can be used instead. For example:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
class Foo
|
||||
{
|
||||
// Silent all the diagnostics for the line
|
||||
Foo(int param); // NOLINT
|
||||
|
||||
// Silent only the specified checks for the line
|
||||
Foo(double param); // NOLINT(google-explicit-constructor, google-runtime-int)
|
||||
|
||||
// Silent only the specified diagnostics for the next line
|
||||
// NOLINTNEXTLINE(google-explicit-constructor, google-runtime-int)
|
||||
Foo(bool param);
|
||||
};
|
||||
|
||||
The formal syntax of ``NOLINT``/``NOLINTNEXTLINE`` is the following:
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
lint-comment:
|
||||
lint-command
|
||||
lint-command lint-args
|
||||
|
||||
lint-args:
|
||||
**(** check-name-list **)**
|
||||
|
||||
check-name-list:
|
||||
*check-name*
|
||||
check-name-list **,** *check-name*
|
||||
|
||||
lint-command:
|
||||
**NOLINT**
|
||||
**NOLINTNEXTLINE**
|
||||
|
||||
Note that whitespaces between ``NOLINT``/``NOLINTNEXTLINE`` and the opening
|
||||
parenthesis are not allowed (in this case the comment will be treated just as
|
||||
``NOLINT``/``NOLINTNEXTLINE``), whereas in check names list (inside
|
||||
the parenthesis) whitespaces can be used and will be ignored.
|
||||
|
||||
.. _LibTooling: http://clang.llvm.org/docs/LibTooling.html
|
||||
.. _How To Setup Tooling For LLVM: http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
|
||||
|
||||
|
@ -13,7 +13,18 @@ class A { A(int i); };
|
||||
|
||||
class B { B(int i); }; // NOLINT
|
||||
|
||||
class C { C(int i); }; // NOLINT(we-dont-care-about-categories-yet)
|
||||
class C { C(int i); }; // NOLINT(for-some-other-check)
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: single-argument constructors must be marked explicit
|
||||
|
||||
class C1 { C1(int i); }; // NOLINT(*)
|
||||
|
||||
class C2 { C2(int i); }; // NOLINT(not-closed-bracket-is-treated-as-skip-all
|
||||
|
||||
class C3 { C3(int i); }; // NOLINT(google-explicit-constructor)
|
||||
|
||||
class C4 { C4(int i); }; // NOLINT(some-check, google-explicit-constructor)
|
||||
|
||||
class C5 { C5(int i); }; // NOLINT without-brackets-skip-all, another-check
|
||||
|
||||
void f() {
|
||||
int i;
|
||||
@ -35,4 +46,4 @@ MACRO_NOLINT
|
||||
#define DOUBLE_MACRO MACRO(H) // NOLINT
|
||||
DOUBLE_MACRO
|
||||
|
||||
// CHECK-MESSAGES: Suppressed 8 warnings (8 NOLINT)
|
||||
// CHECK-MESSAGES: Suppressed 12 warnings (12 NOLINT)
|
||||
|
@ -4,8 +4,24 @@ class A { A(int i); };
|
||||
// NOLINTNEXTLINE
|
||||
class B { B(int i); };
|
||||
|
||||
// NOLINTNEXTLINE(we-dont-care-about-categories-yet)
|
||||
// NOLINTNEXTLINE(for-some-other-check)
|
||||
class C { C(int i); };
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: single-argument constructors must be marked explicit
|
||||
|
||||
// NOLINTNEXTLINE(*)
|
||||
class C1 { C1(int i); };
|
||||
|
||||
// NOLINTNEXTLINE(not-closed-bracket-is-treated-as-skip-all
|
||||
class C2 { C2(int i); };
|
||||
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
class C3 { C3(int i); };
|
||||
|
||||
// NOLINTNEXTLINE(some-check, google-explicit-constructor)
|
||||
class C4 { C4(int i); };
|
||||
|
||||
// NOLINTNEXTLINE without-brackets-skip-all, another-check
|
||||
class C5 { C5(int i); };
|
||||
|
||||
|
||||
// NOLINTNEXTLINE
|
||||
@ -28,6 +44,6 @@ MACRO(G)
|
||||
// NOLINTNEXTLINE
|
||||
MACRO_NOARG
|
||||
|
||||
// CHECK-MESSAGES: Suppressed 4 warnings (4 NOLINT)
|
||||
// CHECK-MESSAGES: Suppressed 8 warnings (8 NOLINT)
|
||||
|
||||
// RUN: %check_clang_tidy %s google-explicit-constructor %t --
|
||||
|
Loading…
x
Reference in New Issue
Block a user