File: semantic_highlighting_expectations_test.rb

package info (click to toggle)
ruby-ruby-lsp 0.26.7-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 27,676 kB
  • sloc: ruby: 35,294; javascript: 29; sh: 7; makefile: 4
file content (135 lines) | stat: -rw-r--r-- 3,681 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# typed: true
# frozen_string_literal: true

require "test_helper"
require_relative "support/expectations_test_runner"

class SemanticHighlightingExpectationsTest < ExpectationsTestRunner
  expectations_tests RubyLsp::Requests::SemanticHighlighting, "semantic_highlighting"

  def run_expectations(source)
    @global_state.apply_options({ capabilities: { general: { positionEncodings: ["utf-8"] } } })
    document = RubyLsp::RubyDocument.new(
      source: source,
      version: 1,
      uri: URI("file:///fake.rb"),
      global_state: @global_state,
    )
    range = @__params&.any? ? @__params.first : nil

    if range
      start_line = range.dig(:start, :line)
      end_line = range.dig(:end, :line)
      processed_range = start_line..end_line
    end

    dispatcher = Prism::Dispatcher.new
    listener = RubyLsp::Requests::SemanticHighlighting.new(
      @global_state,
      dispatcher,
      document,
      nil,
      range: processed_range,
    )

    dispatcher.dispatch(document.ast)
    listener.perform
  end

  def assert_expectations(source, expected)
    actual = run_expectations(source).data
    assert_equal(json_expectations(expected).to_json, decode_tokens(actual).to_json)
  end

  def test_semantic_highlighting_addon
    source = <<~RUBY
      class Post
        custom_method :foo
        before_create :set_defaults
      end
    RUBY

    begin
      create_semantic_highlighting_addon

      with_server(source) do |server, uri|
        server.process_message({
          id: 1,
          method: "textDocument/semanticTokens/full",
          params: { textDocument: { uri: uri } },
        })

        result = server.pop_response
        assert_instance_of(RubyLsp::Result, result)

        decoded_response = decode_tokens(result.response.data)
        assert_equal(
          { delta_line: 0, delta_start_char: 6, length: 4, token_type: 2, token_modifiers: 1 },
          decoded_response[0],
        )
        assert_equal(
          { delta_line: 1, delta_start_char: 2, length: 13, token_type: 13, token_modifiers: 0 },
          decoded_response[1],
        )
        # This is the token modified by the add-on
        assert_equal(
          { delta_line: 1, delta_start_char: 2, length: 13, token_type: 15, token_modifiers: 1 },
          decoded_response[2],
        )
      end
    ensure
      RubyLsp::Addon.addon_classes.clear
    end
  end

  private

  def create_semantic_highlighting_addon
    Class.new(RubyLsp::Addon) do
      def create_semantic_highlighting_listener(response_builder, dispatcher)
        klass = Class.new do
          include RubyLsp::Requests::Support::Common

          def initialize(response_builder, dispatcher)
            @response_builder = response_builder
            dispatcher.register(self, :on_call_node_enter)
          end

          def on_call_node_enter(node)
            current_token = @response_builder.last
            if node.message == "before_create" && @response_builder.last_token_matches?(node.message_loc)
              current_token.replace_type(:keyword)
              current_token.replace_modifier([:declaration])
            end
          end
        end

        klass.new(response_builder, dispatcher)
      end

      def activate(global_state, outgoing_queue); end

      def deactivate; end

      def name; end

      def version
        "0.1.0"
      end
    end
  end

  def decode_tokens(array)
    tokens = []
    array.each_slice(5) do |token|
      tokens << {
        delta_line: token[0],
        delta_start_char: token[1],
        length: token[2],
        token_type: token[3],
        token_modifiers: token[4],
      }
    end
    tokens
  end
end