test_helpers.h 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #ifndef CARBON_TOOLCHAIN_LEX_TEST_HELPERS_H_
  5. #define CARBON_TOOLCHAIN_LEX_TEST_HELPERS_H_
  6. #include <gmock/gmock.h>
  7. #include <array>
  8. #include "common/check.h"
  9. #include "common/string_helpers.h"
  10. #include "toolchain/diagnostics/emitter.h"
  11. namespace Carbon::Testing {
  12. // A diagnostic converter for tests that lex a single token. Produces
  13. // locations such as "`12.5`:1:3" to refer to the third character in the token.
  14. class SingleTokenDiagnosticEmitter : public Diagnostics::Emitter<const char*> {
  15. public:
  16. // Form a converter for a given token. The string provided here must refer
  17. // to the same character array that we are going to lex.
  18. explicit SingleTokenDiagnosticEmitter(Diagnostics::Consumer* consumer,
  19. llvm::StringRef token)
  20. : Emitter(consumer), token_(token) {}
  21. protected:
  22. // Implements `DiagnosticConverter::ConvertLoc`.
  23. auto ConvertLoc(const char* pos, ContextFnT /*context_fn*/) const
  24. -> Diagnostics::ConvertedLoc override {
  25. CARBON_CHECK(StringRefContainsPointer(token_, pos),
  26. "invalid diagnostic location");
  27. llvm::StringRef prefix = token_.take_front(pos - token_.begin());
  28. auto [before_last_newline, this_line] = prefix.rsplit('\n');
  29. if (before_last_newline.size() == prefix.size()) {
  30. // On first line.
  31. return {.loc = {.line_number = 1,
  32. .column_number =
  33. static_cast<int32_t>(pos - token_.begin() + 1)},
  34. .last_byte_offset = -1};
  35. } else {
  36. // On second or subsequent lines. Note that the line number here is 2
  37. // more than the number of newlines because `rsplit` removed one newline
  38. // and `line_number` is 1-based.
  39. return {
  40. .loc = {.line_number =
  41. static_cast<int32_t>(before_last_newline.count('\n') + 2),
  42. .column_number = static_cast<int32_t>(this_line.size() + 1)},
  43. .last_byte_offset = -1};
  44. }
  45. }
  46. private:
  47. llvm::StringRef token_;
  48. };
  49. } // namespace Carbon::Testing
  50. #endif // CARBON_TOOLCHAIN_LEX_TEST_HELPERS_H_