1 //===--- FeatureModulesTests.cpp -------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "Annotations.h" 10 #include "FeatureModule.h" 11 #include "Selection.h" 12 #include "TestTU.h" 13 #include "refactor/Tweak.h" 14 #include "support/Logger.h" 15 #include "clang/Lex/PreprocessorOptions.h" 16 #include "llvm/Support/Error.h" 17 #include "gmock/gmock.h" 18 #include "gtest/gtest.h" 19 #include <memory> 20 21 namespace clang { 22 namespace clangd { 23 namespace { 24 25 TEST(FeatureModulesTest, ContributesTweak) { 26 static constexpr const char *TweakID = "ModuleTweak"; 27 struct TweakContributingModule final : public FeatureModule { 28 struct ModuleTweak final : public Tweak { 29 const char *id() const override { return TweakID; } 30 bool prepare(const Selection &Sel) override { return true; } 31 Expected<Effect> apply(const Selection &Sel) override { 32 return error("not implemented"); 33 } 34 std::string title() const override { return id(); } 35 llvm::StringLiteral kind() const override { 36 return llvm::StringLiteral(""); 37 }; 38 }; 39 40 void contributeTweaks(std::vector<std::unique_ptr<Tweak>> &Out) override { 41 Out.emplace_back(new ModuleTweak); 42 } 43 }; 44 45 FeatureModuleSet Set; 46 Set.add(std::make_unique<TweakContributingModule>()); 47 48 auto AST = TestTU::withCode("").build(); 49 auto Tree = 50 SelectionTree::createRight(AST.getASTContext(), AST.getTokens(), 0, 0); 51 auto Actual = prepareTweak( 52 TweakID, Tweak::Selection(nullptr, AST, 0, 0, std::move(Tree), nullptr), 53 &Set); 54 ASSERT_TRUE(bool(Actual)); 55 EXPECT_EQ(Actual->get()->id(), TweakID); 56 } 57 58 TEST(FeatureModulesTest, SuppressDiags) { 59 struct DiagModifierModule final : public FeatureModule { 60 struct Listener : public FeatureModule::ASTListener { 61 void sawDiagnostic(const clang::Diagnostic &Info, 62 clangd::Diag &Diag) override { 63 Diag.Severity = DiagnosticsEngine::Ignored; 64 } 65 }; 66 std::unique_ptr<ASTListener> astListeners() override { 67 return std::make_unique<Listener>(); 68 }; 69 }; 70 FeatureModuleSet FMS; 71 FMS.add(std::make_unique<DiagModifierModule>()); 72 73 Annotations Code("[[test]]; /* error-ok */"); 74 TestTU TU; 75 TU.Code = Code.code().str(); 76 77 { 78 auto AST = TU.build(); 79 EXPECT_THAT(*AST.getDiagnostics(), testing::Not(testing::IsEmpty())); 80 } 81 82 TU.FeatureModules = &FMS; 83 { 84 auto AST = TU.build(); 85 EXPECT_THAT(*AST.getDiagnostics(), testing::IsEmpty()); 86 } 87 } 88 89 TEST(FeatureModulesTest, BeforeExecute) { 90 struct BeforeExecuteModule final : public FeatureModule { 91 struct Listener : public FeatureModule::ASTListener { 92 void beforeExecute(CompilerInstance &CI) override { 93 CI.getPreprocessor().SetSuppressIncludeNotFoundError(true); 94 } 95 }; 96 std::unique_ptr<ASTListener> astListeners() override { 97 return std::make_unique<Listener>(); 98 }; 99 }; 100 FeatureModuleSet FMS; 101 FMS.add(std::make_unique<BeforeExecuteModule>()); 102 103 TestTU TU = TestTU::withCode(R"cpp( 104 /*error-ok*/ 105 #include "not_found.h" 106 107 void foo() { 108 #include "not_found_not_preamble.h" 109 } 110 )cpp"); 111 112 { 113 auto AST = TU.build(); 114 EXPECT_THAT(*AST.getDiagnostics(), testing::Not(testing::IsEmpty())); 115 } 116 117 TU.FeatureModules = &FMS; 118 { 119 auto AST = TU.build(); 120 EXPECT_THAT(*AST.getDiagnostics(), testing::IsEmpty()); 121 } 122 } 123 124 } // namespace 125 } // namespace clangd 126 } // namespace clang 127