浏览代码

LibWeb: Fix off-by-one error in SyntaxHighlighter

This changes the HTML SyntaxHighlighter to conform to the now-fixed
rendering of syntax highlighting spans in GUI::TextEditor. It also
avoids emitting tokens if they have a zero or negative length.

This fixes a bug where single-character tokens were not highlighted
properly.
Max Wipfli 4 年之前
父节点
当前提交
44c438d0ca
共有 1 个文件被更改,包括 8 次插入5 次删除
  1. 8 5
      Userland/Libraries/LibWeb/HTML/SyntaxHighlighter/SyntaxHighlighter.cpp

+ 8 - 5
Userland/Libraries/LibWeb/HTML/SyntaxHighlighter/SyntaxHighlighter.cpp

@@ -40,6 +40,10 @@ void SyntaxHighlighter::rehighlight(Palette const& palette)
 
 
     Vector<GUI::TextDocumentSpan> spans;
     Vector<GUI::TextDocumentSpan> spans;
     auto highlight = [&](auto start_line, auto start_column, auto end_line, auto end_column, Gfx::TextAttributes attributes, AugmentedTokenKind kind) {
     auto highlight = [&](auto start_line, auto start_column, auto end_line, auto end_column, Gfx::TextAttributes attributes, AugmentedTokenKind kind) {
+        if (start_line > end_line || (start_line == end_line && start_column >= end_column)) {
+            dbgln_if(SYNTAX_HIGHLIGHTING_DEBUG, "(HTML::SyntaxHighlighter) discarding ({}-{}) to ({}-{}) because it has zero or negative length", start_line, start_column, end_line, end_column);
+            return;
+        }
         dbgln_if(SYNTAX_HIGHLIGHTING_DEBUG, "(HTML::SyntaxHighlighter) highlighting ({}-{}) to ({}-{}) with color {}", start_line, start_column, end_line, end_column, attributes.color);
         dbgln_if(SYNTAX_HIGHLIGHTING_DEBUG, "(HTML::SyntaxHighlighter) highlighting ({}-{}) to ({}-{}) with color {}", start_line, start_column, end_line, end_column, attributes.color);
         spans.empend(
         spans.empend(
             GUI::TextRange {
             GUI::TextRange {
@@ -59,7 +63,7 @@ void SyntaxHighlighter::rehighlight(Palette const& palette)
     } state { State::HTML };
     } state { State::HTML };
     for (;;) {
     for (;;) {
         auto token = tokenizer.next_token();
         auto token = tokenizer.next_token();
-        if (!token.has_value())
+        if (!token.has_value() || token.value().is_end_of_file())
             break;
             break;
         dbgln_if(SYNTAX_HIGHLIGHTING_DEBUG, "(HTML::SyntaxHighlighter) got token of type {}", token->to_string());
         dbgln_if(SYNTAX_HIGHLIGHTING_DEBUG, "(HTML::SyntaxHighlighter) got token of type {}", token->to_string());
 
 
@@ -88,17 +92,16 @@ void SyntaxHighlighter::rehighlight(Palette const& palette)
             highlight(
             highlight(
                 token->start_position().line,
                 token->start_position().line,
                 token->start_position().column,
                 token->start_position().column,
-                token->start_position().line,
-                token->start_position().column,
+                token->end_position().line,
+                token->end_position().column,
                 { palette.syntax_comment(), {} },
                 { palette.syntax_comment(), {} },
                 AugmentedTokenKind::Comment);
                 AugmentedTokenKind::Comment);
         } else if (token->is_start_tag() || token->is_end_tag()) {
         } else if (token->is_start_tag() || token->is_end_tag()) {
-            // FIXME: This breaks with single-character tag names.
             highlight(
             highlight(
                 token->start_position().line,
                 token->start_position().line,
                 token->start_position().column + token_start_offset,
                 token->start_position().column + token_start_offset,
                 token->start_position().line,
                 token->start_position().line,
-                token->start_position().column + token->tag_name().length() + token_start_offset - 1,
+                token->start_position().column + token_start_offset + token->tag_name().length(),
                 { palette.syntax_keyword(), {}, false, true },
                 { palette.syntax_keyword(), {}, false, true },
                 token->is_start_tag() ? AugmentedTokenKind::OpenTag : AugmentedTokenKind::CloseTag);
                 token->is_start_tag() ? AugmentedTokenKind::OpenTag : AugmentedTokenKind::CloseTag);