1//===-- ConfigTesting.h - Helpers for configuration tests -------*- 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#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_UNITTESTS_CONFIGTESTING_H
10#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_UNITTESTS_CONFIGTESTING_H
11
12#include "Protocol.h"
13#include "llvm/Support/ScopedPrinter.h"
14#include "llvm/Support/SourceMgr.h"
15#include "gmock/gmock.h"
16#include <functional>
17#include <optional>
18
19namespace clang {
20namespace clangd {
21namespace config {
22
23// Provides a DiagnosticsCallback that records diganostics.
24// Unlike just pushing them into a vector, underlying storage need not survive.
25struct CapturedDiags {
26 std::function<void(const llvm::SMDiagnostic &)> callback() {
27 return [this](const llvm::SMDiagnostic &D) {
28 if (Files.empty() || Files.back() != D.getFilename())
29 Files.push_back(x: D.getFilename().str());
30
31 if (D.getKind() > llvm::SourceMgr::DK_Warning)
32 return;
33
34 Diagnostics.emplace_back();
35 Diag &Out = Diagnostics.back();
36 Out.Message = D.getMessage().str();
37 Out.Kind = D.getKind();
38 Out.Pos.line = D.getLineNo() - 1;
39 Out.Pos.character = D.getColumnNo(); // Zero-based - bug in SourceMgr?
40 if (!D.getRanges().empty()) {
41 const auto &R = D.getRanges().front();
42 Out.Rng.emplace();
43 Out.Rng->start.line = Out.Rng->end.line = Out.Pos.line;
44 Out.Rng->start.character = R.first;
45 Out.Rng->end.character = R.second;
46 }
47 };
48 }
49 struct Diag {
50 std::string Message;
51 llvm::SourceMgr::DiagKind Kind;
52 Position Pos;
53 std::optional<Range> Rng;
54
55 friend void PrintTo(const Diag &D, std::ostream *OS) {
56 *OS << (D.Kind == llvm::SourceMgr::DK_Error ? "error: " : "warning: ")
57 << D.Message << "@" << llvm::to_string(Value: D.Pos);
58 }
59 };
60 std::vector<Diag> Diagnostics; // Warning or higher.
61 std::vector<std::string> Files; // Filename from diagnostics including notes.
62
63 void clear() {
64 Diagnostics.clear();
65 Files.clear();
66 }
67};
68
69MATCHER_P(diagMessage, M, "") { return arg.Message == M; }
70MATCHER_P(diagKind, K, "") { return arg.Kind == K; }
71MATCHER_P(diagPos, P, "") { return arg.Pos == P; }
72MATCHER_P(diagRange, R, "") { return arg.Rng == R; }
73
74inline Position toPosition(llvm::SMLoc L, const llvm::SourceMgr &SM) {
75 auto LineCol = SM.getLineAndColumn(Loc: L);
76 Position P;
77 P.line = LineCol.first - 1;
78 P.character = LineCol.second - 1;
79 return P;
80}
81
82inline Range toRange(llvm::SMRange R, const llvm::SourceMgr &SM) {
83 return Range{.start: toPosition(L: R.Start, SM), .end: toPosition(L: R.End, SM)};
84}
85
86} // namespace config
87} // namespace clangd
88} // namespace clang
89
90#endif
91

source code of clang-tools-extra/clangd/unittests/ConfigTesting.h