Highlighter.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*
  2. * Copyright (c) 2020-2022, the SerenityOS developers.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Noncopyable.h>
  8. #include <AK/WeakPtr.h>
  9. #include <LibGfx/Palette.h>
  10. #include <LibSyntax/Document.h>
  11. #include <LibSyntax/HighlighterClient.h>
  12. #include <LibSyntax/Language.h>
  13. namespace Syntax {
  14. class Highlighter {
  15. AK_MAKE_NONCOPYABLE(Highlighter);
  16. AK_MAKE_NONMOVABLE(Highlighter);
  17. public:
  18. virtual ~Highlighter() = default;
  19. virtual Language language() const = 0;
  20. virtual Optional<StringView> comment_prefix() const = 0;
  21. virtual Optional<StringView> comment_suffix() const = 0;
  22. virtual void rehighlight(Palette const&) = 0;
  23. virtual void highlight_matching_token_pair();
  24. virtual bool is_identifier(u64) const { return false; }
  25. virtual bool is_navigatable(u64) const { return false; }
  26. void attach(HighlighterClient&);
  27. void detach();
  28. void cursor_did_change();
  29. struct MatchingTokenPair {
  30. u64 open;
  31. u64 close;
  32. };
  33. Vector<MatchingTokenPair> matching_token_pairs() const;
  34. template<typename T>
  35. bool fast_is() const = delete;
  36. // FIXME: When other syntax highlighters start using a language server, we should add a common base class here.
  37. virtual bool is_cpp_semantic_highlighter() const { return false; }
  38. protected:
  39. Highlighter() = default;
  40. // FIXME: This should be WeakPtr somehow
  41. HighlighterClient* m_client { nullptr };
  42. virtual Vector<MatchingTokenPair> matching_token_pairs_impl() const = 0;
  43. virtual bool token_types_equal(u64, u64) const = 0;
  44. void register_nested_token_pairs(Vector<MatchingTokenPair>);
  45. void clear_nested_token_pairs() { m_nested_token_pairs.clear(); }
  46. size_t first_free_token_kind_serial_value() const { return m_nested_token_pairs.size(); }
  47. struct BuddySpan {
  48. int index { -1 };
  49. TextDocumentSpan span_backup;
  50. };
  51. bool m_has_brace_buddies { false };
  52. BuddySpan m_brace_buddies[2];
  53. HashTable<MatchingTokenPair> m_nested_token_pairs;
  54. };
  55. class ProxyHighlighterClient final : public Syntax::HighlighterClient {
  56. public:
  57. ProxyHighlighterClient(Syntax::HighlighterClient& client, TextPosition start, u64 nested_kind_start_value, StringView source)
  58. : m_document(client.get_document())
  59. , m_text(source)
  60. , m_start(start)
  61. , m_nested_kind_start_value(nested_kind_start_value)
  62. {
  63. }
  64. Vector<TextDocumentSpan> corrected_spans() const
  65. {
  66. Vector<TextDocumentSpan> spans { m_spans };
  67. for (auto& entry : spans) {
  68. entry.range.start() = {
  69. entry.range.start().line() + m_start.line(),
  70. entry.range.start().line() == 0 ? entry.range.start().column() + m_start.column() : entry.range.start().column(),
  71. };
  72. entry.range.end() = {
  73. entry.range.end().line() + m_start.line(),
  74. entry.range.end().line() == 0 ? entry.range.end().column() + m_start.column() : entry.range.end().column(),
  75. };
  76. if (entry.data != (u64)-1)
  77. entry.data += m_nested_kind_start_value;
  78. }
  79. return spans;
  80. }
  81. Vector<TextDocumentFoldingRegion> corrected_folding_regions() const
  82. {
  83. Vector<TextDocumentFoldingRegion> folding_regions { m_folding_regions };
  84. for (auto& entry : folding_regions) {
  85. entry.range.start() = {
  86. entry.range.start().line() + m_start.line(),
  87. entry.range.start().line() == 0 ? entry.range.start().column() + m_start.column() : entry.range.start().column(),
  88. };
  89. entry.range.end() = {
  90. entry.range.end().line() + m_start.line(),
  91. entry.range.end().line() == 0 ? entry.range.end().column() + m_start.column() : entry.range.end().column(),
  92. };
  93. }
  94. return folding_regions;
  95. }
  96. Vector<Syntax::Highlighter::MatchingTokenPair> corrected_token_pairs(Vector<Syntax::Highlighter::MatchingTokenPair> pairs) const
  97. {
  98. for (auto& pair : pairs) {
  99. pair.close += m_nested_kind_start_value;
  100. pair.open += m_nested_kind_start_value;
  101. }
  102. return pairs;
  103. }
  104. private:
  105. virtual Vector<TextDocumentSpan> const& spans() const override { return m_spans; }
  106. virtual void set_span_at_index(size_t index, TextDocumentSpan span) override { m_spans.at(index) = move(span); }
  107. virtual Vector<TextDocumentFoldingRegion>& folding_regions() override { return m_folding_regions; }
  108. virtual Vector<TextDocumentFoldingRegion> const& folding_regions() const override { return m_folding_regions; }
  109. virtual ByteString highlighter_did_request_text() const override { return m_text; }
  110. virtual void highlighter_did_request_update() override { }
  111. virtual Document& highlighter_did_request_document() override { return m_document; }
  112. virtual TextPosition highlighter_did_request_cursor() const override { return {}; }
  113. virtual void highlighter_did_set_spans(Vector<TextDocumentSpan> spans) override { m_spans = move(spans); }
  114. virtual void highlighter_did_set_folding_regions(Vector<TextDocumentFoldingRegion> folding_regions) override { m_folding_regions = folding_regions; }
  115. Vector<TextDocumentSpan> m_spans;
  116. Vector<TextDocumentFoldingRegion> m_folding_regions;
  117. Document& m_document;
  118. StringView m_text;
  119. TextPosition m_start;
  120. u64 m_nested_kind_start_value { 0 };
  121. };
  122. }
  123. template<>
  124. struct AK::Traits<Syntax::Highlighter::MatchingTokenPair> : public AK::DefaultTraits<Syntax::Highlighter::MatchingTokenPair> {
  125. static unsigned hash(Syntax::Highlighter::MatchingTokenPair const& pair)
  126. {
  127. return pair_int_hash(u64_hash(pair.open), u64_hash(pair.close));
  128. }
  129. static bool equals(Syntax::Highlighter::MatchingTokenPair const& a, Syntax::Highlighter::MatchingTokenPair const& b)
  130. {
  131. return a.open == b.open && a.close == b.close;
  132. }
  133. };