xref: /llvm-project/clang-tools-extra/clangd/unittests/ConfigTesting.h (revision f71ffd3b735b4d6ae3c12be1806cdd6205b3b378)
1f12cd99cSSam McCall //===-- ConfigTesting.h - Helpers for configuration tests -------*- C++ -*-===//
2f12cd99cSSam McCall //
3f12cd99cSSam McCall // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4f12cd99cSSam McCall // See https://llvm.org/LICENSE.txt for license information.
5f12cd99cSSam McCall // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f12cd99cSSam McCall //
7f12cd99cSSam McCall //===----------------------------------------------------------------------===//
8f12cd99cSSam McCall 
9f12cd99cSSam McCall #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_UNITTESTS_CONFIGTESTING_H
10f12cd99cSSam McCall #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_UNITTESTS_CONFIGTESTING_H
11f12cd99cSSam McCall 
12f12cd99cSSam McCall #include "Protocol.h"
13f12cd99cSSam McCall #include "llvm/Support/ScopedPrinter.h"
14f12cd99cSSam McCall #include "llvm/Support/SourceMgr.h"
15f12cd99cSSam McCall #include "gmock/gmock.h"
16f12cd99cSSam McCall #include <functional>
1771f55735SKazu Hirata #include <optional>
18f12cd99cSSam McCall 
19f12cd99cSSam McCall namespace clang {
20f12cd99cSSam McCall namespace clangd {
21f12cd99cSSam McCall namespace config {
22f12cd99cSSam McCall 
23f12cd99cSSam McCall // Provides a DiagnosticsCallback that records diganostics.
24f12cd99cSSam McCall // Unlike just pushing them into a vector, underlying storage need not survive.
25f12cd99cSSam McCall struct CapturedDiags {
callbackCapturedDiags26f12cd99cSSam McCall   std::function<void(const llvm::SMDiagnostic &)> callback() {
27f12cd99cSSam McCall     return [this](const llvm::SMDiagnostic &D) {
28fed9af29SSam McCall       if (Files.empty() || Files.back() != D.getFilename())
29fed9af29SSam McCall         Files.push_back(D.getFilename().str());
30fed9af29SSam McCall 
31fed9af29SSam McCall       if (D.getKind() > llvm::SourceMgr::DK_Warning)
32fed9af29SSam McCall         return;
33fed9af29SSam McCall 
34f12cd99cSSam McCall       Diagnostics.emplace_back();
35f12cd99cSSam McCall       Diag &Out = Diagnostics.back();
36f12cd99cSSam McCall       Out.Message = D.getMessage().str();
37f12cd99cSSam McCall       Out.Kind = D.getKind();
38f12cd99cSSam McCall       Out.Pos.line = D.getLineNo() - 1;
39f12cd99cSSam McCall       Out.Pos.character = D.getColumnNo(); // Zero-based - bug in SourceMgr?
40f12cd99cSSam McCall       if (!D.getRanges().empty()) {
41f12cd99cSSam McCall         const auto &R = D.getRanges().front();
427dcc3858SSam McCall         Out.Rng.emplace();
437dcc3858SSam McCall         Out.Rng->start.line = Out.Rng->end.line = Out.Pos.line;
447dcc3858SSam McCall         Out.Rng->start.character = R.first;
457dcc3858SSam McCall         Out.Rng->end.character = R.second;
46f12cd99cSSam McCall       }
47f12cd99cSSam McCall     };
48f12cd99cSSam McCall   }
49f12cd99cSSam McCall   struct Diag {
50f12cd99cSSam McCall     std::string Message;
51f12cd99cSSam McCall     llvm::SourceMgr::DiagKind Kind;
52f12cd99cSSam McCall     Position Pos;
53*f71ffd3bSKazu Hirata     std::optional<Range> Rng;
54f12cd99cSSam McCall 
PrintToCapturedDiags::Diag55f12cd99cSSam McCall     friend void PrintTo(const Diag &D, std::ostream *OS) {
56f12cd99cSSam McCall       *OS << (D.Kind == llvm::SourceMgr::DK_Error ? "error: " : "warning: ")
57f12cd99cSSam McCall           << D.Message << "@" << llvm::to_string(D.Pos);
58f12cd99cSSam McCall     }
59f12cd99cSSam McCall   };
60fed9af29SSam McCall   std::vector<Diag> Diagnostics;  // Warning or higher.
61fed9af29SSam McCall   std::vector<std::string> Files; // Filename from diagnostics including notes.
62fed9af29SSam McCall 
clearCapturedDiags63fed9af29SSam McCall   void clear() {
64fed9af29SSam McCall     Diagnostics.clear();
65fed9af29SSam McCall     Files.clear();
66fed9af29SSam McCall   }
67f12cd99cSSam McCall };
68f12cd99cSSam McCall 
698edfc2f8SChristian Kühnel MATCHER_P(diagMessage, M, "") { return arg.Message == M; }
708edfc2f8SChristian Kühnel MATCHER_P(diagKind, K, "") { return arg.Kind == K; }
718edfc2f8SChristian Kühnel MATCHER_P(diagPos, P, "") { return arg.Pos == P; }
728edfc2f8SChristian Kühnel MATCHER_P(diagRange, R, "") { return arg.Rng == R; }
73f12cd99cSSam McCall 
toPosition(llvm::SMLoc L,const llvm::SourceMgr & SM)74f12cd99cSSam McCall inline Position toPosition(llvm::SMLoc L, const llvm::SourceMgr &SM) {
75f12cd99cSSam McCall   auto LineCol = SM.getLineAndColumn(L);
76f12cd99cSSam McCall   Position P;
77f12cd99cSSam McCall   P.line = LineCol.first - 1;
78f12cd99cSSam McCall   P.character = LineCol.second - 1;
79f12cd99cSSam McCall   return P;
80f12cd99cSSam McCall }
81f12cd99cSSam McCall 
toRange(llvm::SMRange R,const llvm::SourceMgr & SM)82f12cd99cSSam McCall inline Range toRange(llvm::SMRange R, const llvm::SourceMgr &SM) {
83f12cd99cSSam McCall   return Range{toPosition(R.Start, SM), toPosition(R.End, SM)};
84f12cd99cSSam McCall }
85f12cd99cSSam McCall 
86f12cd99cSSam McCall } // namespace config
87f12cd99cSSam McCall } // namespace clangd
88f12cd99cSSam McCall } // namespace clang
89f12cd99cSSam McCall 
90f12cd99cSSam McCall #endif
91