SyntaxHighlighter.cpp 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. /*
  2. * Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2022, the SerenityOS developers.
  4. * Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org>
  5. *
  6. * SPDX-License-Identifier: BSD-2-Clause
  7. */
  8. #include "SyntaxHighlighter.h"
  9. #include "Lexer.h"
  10. #include <LibGfx/Palette.h>
  11. namespace GUI::GML {
  12. static Gfx::TextAttributes style_for_token_type(Gfx::Palette const& palette, Token::Type type)
  13. {
  14. switch (type) {
  15. case Token::Type::LeftCurly:
  16. case Token::Type::RightCurly:
  17. return { palette.syntax_punctuation() };
  18. case Token::Type::ClassMarker:
  19. return { palette.syntax_keyword() };
  20. case Token::Type::ClassName:
  21. return { palette.syntax_identifier(), {}, true };
  22. case Token::Type::Identifier:
  23. return { palette.syntax_identifier() };
  24. case Token::Type::JsonValue:
  25. return { palette.syntax_string() };
  26. case Token::Type::Comment:
  27. return { palette.syntax_comment() };
  28. default:
  29. return { palette.base_text() };
  30. }
  31. }
  32. bool SyntaxHighlighter::is_identifier(u64 token) const
  33. {
  34. auto ini_token = static_cast<Token::Type>(token);
  35. return ini_token == Token::Type::Identifier;
  36. }
  37. void SyntaxHighlighter::rehighlight(Palette const& palette)
  38. {
  39. auto text = m_client->get_text();
  40. Lexer lexer(text);
  41. auto tokens = lexer.lex();
  42. Vector<Token> folding_region_start_tokens;
  43. Vector<GUI::TextDocumentSpan> spans;
  44. Vector<GUI::TextDocumentFoldingRegion> folding_regions;
  45. for (auto& token : tokens) {
  46. GUI::TextDocumentSpan span;
  47. span.range.set_start({ token.m_start.line, token.m_start.column });
  48. span.range.set_end({ token.m_end.line, token.m_end.column });
  49. span.attributes = style_for_token_type(palette, token.m_type);
  50. span.is_skippable = false;
  51. span.data = static_cast<u64>(token.m_type);
  52. spans.append(span);
  53. // Create folding regions for {} blocks
  54. if (token.m_type == Token::Type::LeftCurly) {
  55. folding_region_start_tokens.append(token);
  56. } else if (token.m_type == Token::Type::RightCurly) {
  57. if (!folding_region_start_tokens.is_empty()) {
  58. auto left_curly = folding_region_start_tokens.take_last();
  59. GUI::TextDocumentFoldingRegion region;
  60. region.range.set_start({ left_curly.m_end.line, left_curly.m_end.column });
  61. region.range.set_end({ token.m_start.line, token.m_start.column });
  62. folding_regions.append(region);
  63. }
  64. }
  65. }
  66. m_client->do_set_spans(move(spans));
  67. m_client->do_set_folding_regions(move(folding_regions));
  68. m_has_brace_buddies = false;
  69. highlight_matching_token_pair();
  70. m_client->do_update();
  71. }
  72. Vector<SyntaxHighlighter::MatchingTokenPair> SyntaxHighlighter::matching_token_pairs_impl() const
  73. {
  74. static Vector<MatchingTokenPair> pairs;
  75. if (pairs.is_empty()) {
  76. pairs.append({ static_cast<u64>(Token::Type::LeftCurly), static_cast<u64>(Token::Type::RightCurly) });
  77. }
  78. return pairs;
  79. }
  80. bool SyntaxHighlighter::token_types_equal(u64 token1, u64 token2) const
  81. {
  82. return static_cast<Token::Type>(token1) == static_cast<Token::Type>(token2);
  83. }
  84. }