90 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			90 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===-- ConfigTesting.h - Helpers for configuration tests -------*- C++ -*-===//
 | |
| //
 | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | |
| // See https://llvm.org/LICENSE.txt for license information.
 | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_UNITTESTS_CONFIGTESTING_H
 | |
| #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_UNITTESTS_CONFIGTESTING_H
 | |
| 
 | |
| #include "Protocol.h"
 | |
| #include "llvm/Support/ScopedPrinter.h"
 | |
| #include "llvm/Support/SourceMgr.h"
 | |
| #include "gmock/gmock.h"
 | |
| #include <functional>
 | |
| 
 | |
| namespace clang {
 | |
| namespace clangd {
 | |
| namespace config {
 | |
| 
 | |
| // Provides a DiagnosticsCallback that records diganostics.
 | |
| // Unlike just pushing them into a vector, underlying storage need not survive.
 | |
| struct CapturedDiags {
 | |
|   std::function<void(const llvm::SMDiagnostic &)> callback() {
 | |
|     return [this](const llvm::SMDiagnostic &D) {
 | |
|       if (Files.empty() || Files.back() != D.getFilename())
 | |
|         Files.push_back(D.getFilename().str());
 | |
| 
 | |
|       if (D.getKind() > llvm::SourceMgr::DK_Warning)
 | |
|         return;
 | |
| 
 | |
|       Diagnostics.emplace_back();
 | |
|       Diag &Out = Diagnostics.back();
 | |
|       Out.Message = D.getMessage().str();
 | |
|       Out.Kind = D.getKind();
 | |
|       Out.Pos.line = D.getLineNo() - 1;
 | |
|       Out.Pos.character = D.getColumnNo(); // Zero-based - bug in SourceMgr?
 | |
|       if (!D.getRanges().empty()) {
 | |
|         const auto &R = D.getRanges().front();
 | |
|         Out.Rng.emplace();
 | |
|         Out.Rng->start.line = Out.Rng->end.line = Out.Pos.line;
 | |
|         Out.Rng->start.character = R.first;
 | |
|         Out.Rng->end.character = R.second;
 | |
|       }
 | |
|     };
 | |
|   }
 | |
|   struct Diag {
 | |
|     std::string Message;
 | |
|     llvm::SourceMgr::DiagKind Kind;
 | |
|     Position Pos;
 | |
|     llvm::Optional<Range> Rng;
 | |
| 
 | |
|     friend void PrintTo(const Diag &D, std::ostream *OS) {
 | |
|       *OS << (D.Kind == llvm::SourceMgr::DK_Error ? "error: " : "warning: ")
 | |
|           << D.Message << "@" << llvm::to_string(D.Pos);
 | |
|     }
 | |
|   };
 | |
|   std::vector<Diag> Diagnostics;  // Warning or higher.
 | |
|   std::vector<std::string> Files; // Filename from diagnostics including notes.
 | |
| 
 | |
|   void clear() {
 | |
|     Diagnostics.clear();
 | |
|     Files.clear();
 | |
|   }
 | |
| };
 | |
| 
 | |
| MATCHER_P(DiagMessage, M, "") { return arg.Message == M; }
 | |
| MATCHER_P(DiagKind, K, "") { return arg.Kind == K; }
 | |
| MATCHER_P(DiagPos, P, "") { return arg.Pos == P; }
 | |
| MATCHER_P(DiagRange, R, "") { return arg.Rng == R; }
 | |
| 
 | |
| inline Position toPosition(llvm::SMLoc L, const llvm::SourceMgr &SM) {
 | |
|   auto LineCol = SM.getLineAndColumn(L);
 | |
|   Position P;
 | |
|   P.line = LineCol.first - 1;
 | |
|   P.character = LineCol.second - 1;
 | |
|   return P;
 | |
| }
 | |
| 
 | |
| inline Range toRange(llvm::SMRange R, const llvm::SourceMgr &SM) {
 | |
|   return Range{toPosition(R.Start, SM), toPosition(R.End, SM)};
 | |
| }
 | |
| 
 | |
| } // namespace config
 | |
| } // namespace clangd
 | |
| } // namespace clang
 | |
| 
 | |
| #endif
 |