Class: RubyLsp::Requests::SemanticHighlighting

Inherits:
BaseRequest
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/ruby_lsp/requests/semantic_highlighting.rb

Overview

The [semantic highlighting](microsoft.github.io/language-server-protocol/specification#textDocument_semanticTokens) request informs the editor of the correct token types to provide consistent and accurate highlighting for themes.

# Example

“‘ruby def foo

var = 1 # --> semantic highlighting: local variable
some_invocation # --> semantic highlighting: method invocation
var # --> semantic highlighting: local variable

end “‘

Defined Under Namespace

Classes: SemanticToken

Constant Summary collapse

TOKEN_TYPES =
T.let([
  :variable,
  :method,
  :namespace,
].freeze, T::Array[Symbol])
TOKEN_MODIFIERS =
T.let({
  declaration: 0,
  definition: 1,
  readonly: 2,
  static: 3,
  deprecated: 4,
  abstract: 5,
  async: 6,
  modification: 7,
  documentation: 8,
  default_library: 9,
}.freeze, T::Hash[Symbol, Integer])

Instance Method Summary collapse

Methods inherited from BaseRequest

#range_from_syntax_tree_node

Constructor Details

#initialize(document, encoder: nil) ⇒ SemanticHighlighting

Returns a new instance of SemanticHighlighting.



49
50
51
52
53
54
55
# File 'lib/ruby_lsp/requests/semantic_highlighting.rb', line 49

def initialize(document, encoder: nil)
  super(document)

  @encoder = encoder
  @tokens = T.let([], T::Array[SemanticToken])
  @tree = T.let(document.tree, SyntaxTree::Node)
end

Instance Method Details

#add_token(location, type, modifiers = []) ⇒ Object



173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/ruby_lsp/requests/semantic_highlighting.rb', line 173

def add_token(location, type, modifiers = [])
  length = location.end_char - location.start_char
  modifiers_indices = modifiers.filter_map { |modifier| TOKEN_MODIFIERS[modifier] }
  @tokens.push(
    SemanticToken.new(
      location: location,
      length: length,
      type: T.must(TOKEN_TYPES.index(type)),
      modifier: modifiers_indices
    )
  )
end

#runObject



65
66
67
68
69
70
# File 'lib/ruby_lsp/requests/semantic_highlighting.rb', line 65

def run
  visit(@tree)
  return @tokens unless @encoder

  @encoder.encode(@tokens)
end

#visit_a_ref_field(node) ⇒ Object



73
74
75
# File 'lib/ruby_lsp/requests/semantic_highlighting.rb', line 73

def visit_a_ref_field(node)
  add_token(node.collection.value.location, :variable)
end

#visit_call(node) ⇒ Object



78
79
80
81
82
# File 'lib/ruby_lsp/requests/semantic_highlighting.rb', line 78

def visit_call(node)
  visit(node.receiver)
  add_token(node.message.location, :method)
  visit(node.arguments)
end

#visit_command(node) ⇒ Object



85
86
87
88
# File 'lib/ruby_lsp/requests/semantic_highlighting.rb', line 85

def visit_command(node)
  add_token(node.message.location, :method)
  visit(node.arguments)
end

#visit_command_call(node) ⇒ Object



91
92
93
94
95
# File 'lib/ruby_lsp/requests/semantic_highlighting.rb', line 91

def visit_command_call(node)
  visit(node.receiver)
  add_token(node.message.location, :method)
  visit(node.arguments)
end

#visit_const(node) ⇒ Object



98
99
100
# File 'lib/ruby_lsp/requests/semantic_highlighting.rb', line 98

def visit_const(node)
  add_token(node.location, :namespace)
end

#visit_def(node) ⇒ Object



103
104
105
106
107
# File 'lib/ruby_lsp/requests/semantic_highlighting.rb', line 103

def visit_def(node)
  add_token(node.name.location, :method, [:declaration])
  visit(node.params)
  visit(node.bodystmt)
end

#visit_def_endless(node) ⇒ Object



110
111
112
113
114
115
# File 'lib/ruby_lsp/requests/semantic_highlighting.rb', line 110

def visit_def_endless(node)
  add_token(node.name.location, :method, [:declaration])
  visit(node.paren)
  visit(node.operator)
  visit(node.statement)
end

#visit_defs(node) ⇒ Object



118
119
120
121
122
123
124
# File 'lib/ruby_lsp/requests/semantic_highlighting.rb', line 118

def visit_defs(node)
  visit(node.target)
  visit(node.operator)
  add_token(node.name.location, :method, [:declaration])
  visit(node.params)
  visit(node.bodystmt)
end

#visit_fcall(node) ⇒ Object



127
128
129
130
# File 'lib/ruby_lsp/requests/semantic_highlighting.rb', line 127

def visit_fcall(node)
  add_token(node.value.location, :method)
  visit(node.arguments)
end

#visit_kw(node) ⇒ Object



133
134
135
136
137
138
# File 'lib/ruby_lsp/requests/semantic_highlighting.rb', line 133

def visit_kw(node)
  case node.value
  when "self"
    add_token(node.location, :variable, [:default_library])
  end
end

#visit_m_assign(node) ⇒ Object



141
142
143
144
145
# File 'lib/ruby_lsp/requests/semantic_highlighting.rb', line 141

def visit_m_assign(node)
  node.target.parts.each do |var_ref|
    add_token(var_ref.value.location, :variable)
  end
end

#visit_var_field(node) ⇒ Object



148
149
150
151
152
153
154
155
# File 'lib/ruby_lsp/requests/semantic_highlighting.rb', line 148

def visit_var_field(node)
  case node.value
  when SyntaxTree::Ident
    add_token(node.value.location, :variable)
  else
    visit(node.value)
  end
end

#visit_var_ref(node) ⇒ Object



158
159
160
161
162
163
164
165
# File 'lib/ruby_lsp/requests/semantic_highlighting.rb', line 158

def visit_var_ref(node)
  case node.value
  when SyntaxTree::Ident
    add_token(node.value.location, :variable)
  else
    visit(node.value)
  end
end

#visit_vcall(node) ⇒ Object



168
169
170
# File 'lib/ruby_lsp/requests/semantic_highlighting.rb', line 168

def visit_vcall(node)
  add_token(node.value.location, :method)
end