diff --git a/clang-tools-extra/clangd/Diagnostics.cpp b/clang-tools-extra/clangd/Diagnostics.cpp --- a/clang-tools-extra/clangd/Diagnostics.cpp +++ b/clang-tools-extra/clangd/Diagnostics.cpp @@ -727,29 +727,29 @@ // Handle the new main diagnostic. flushLastDiag(); - if (Adjuster) { + // FIXME: Merge with feature modules. + if (Adjuster) DiagLevel = Adjuster(DiagLevel, Info); - if (DiagLevel == DiagnosticsEngine::Ignored) { - LastPrimaryDiagnosticWasSuppressed = true; - return; - } - } - LastPrimaryDiagnosticWasSuppressed = false; LastDiag = Diag(); FillDiagBase(*LastDiag); LastDiagLoc.emplace(Info.getLocation(), Info.getSourceManager()); LastDiagOriginallyError = OriginallyError; + LastPrimaryDiagnosticWasSuppressed = false; + if (DiagCB) + DiagCB(Info, *LastDiag); + if (LastDiag->Severity == DiagnosticsEngine::Ignored) { + LastPrimaryDiagnosticWasSuppressed = true; + return; + } if (!Info.getFixItHints().empty()) AddFix(true /* try to invent a message instead of repeating the diag */); if (Fixer) { - auto ExtraFixes = Fixer(DiagLevel, Info); + auto ExtraFixes = Fixer(LastDiag->Severity, Info); LastDiag->Fixes.insert(LastDiag->Fixes.end(), ExtraFixes.begin(), ExtraFixes.end()); } - if (DiagCB) - DiagCB(Info, *LastDiag); } else { // Handle a note to an existing diagnostic. @@ -781,7 +781,7 @@ } void StoreDiags::flushLastDiag() { - if (!LastDiag) + if (!LastDiag || LastPrimaryDiagnosticWasSuppressed) return; auto Finish = llvm::make_scope_exit([&, NDiags(Output.size())] { if (Output.size() == NDiags) // No new diag emitted. diff --git a/clang-tools-extra/clangd/unittests/FeatureModulesTests.cpp b/clang-tools-extra/clangd/unittests/FeatureModulesTests.cpp --- a/clang-tools-extra/clangd/unittests/FeatureModulesTests.cpp +++ b/clang-tools-extra/clangd/unittests/FeatureModulesTests.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "Annotations.h" #include "FeatureModule.h" #include "Selection.h" #include "TestTU.h" @@ -53,6 +54,37 @@ EXPECT_EQ(Actual->get()->id(), TweakID); } +TEST(FeatureModulesTest, SuppressDiags) { + struct DiagModifierModule final : public FeatureModule { + struct Listener : public FeatureModule::ASTListener { + void sawDiagnostic(const clang::Diagnostic &Info, + clangd::Diag &Diag) override { + Diag.Severity = DiagnosticsEngine::Ignored; + } + }; + std::unique_ptr astListeners() override { + return std::make_unique(); + }; + }; + FeatureModuleSet FMS; + FMS.add(std::make_unique()); + + Annotations Code("[[test]]; /* error-ok */"); + TestTU TU; + TU.Code = Code.code().str(); + + { + auto AST = TU.build(); + EXPECT_THAT(*AST.getDiagnostics(), testing::Not(testing::IsEmpty())); + } + + TU.FeatureModules = &FMS; + { + auto AST = TU.build(); + EXPECT_THAT(*AST.getDiagnostics(), testing::IsEmpty()); + } +} + } // namespace } // namespace clangd } // namespace clang