ruby-lsp 0.3.8 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -23,25 +23,55 @@ module RubyLsp
23
23
  params(
24
24
  uri: String,
25
25
  document: Document,
26
- range: T::Range[Integer],
26
+ range: Document::RangeShape,
27
+ context: T::Hash[Symbol, T.untyped],
27
28
  ).void
28
29
  end
29
- def initialize(uri, document, range)
30
+ def initialize(uri, document, range, context)
30
31
  super(document)
31
32
 
32
33
  @uri = uri
33
34
  @range = range
35
+ @context = context
34
36
  end
35
37
 
36
- sig { override.returns(T.all(T::Array[LanguageServer::Protocol::Interface::CodeAction], Object)) }
38
+ sig { override.returns(T.nilable(T.all(T::Array[Interface::CodeAction], Object))) }
37
39
  def run
38
- diagnostics = @document.cache_fetch(:diagnostics) { Diagnostics.new(@uri, @document).run }
39
- corrections = diagnostics.select do |diagnostic|
40
- diagnostic.correctable? && T.cast(diagnostic, Support::RuboCopDiagnostic).in_range?(@range)
40
+ diagnostics = @context[:diagnostics]
41
+
42
+ code_actions = diagnostics.filter_map do |diagnostic|
43
+ code_action = diagnostic.dig(:data, :code_action)
44
+ next if code_action.nil?
45
+
46
+ # We want to return only code actions that are within range or that do not have any edits, such as refactor
47
+ # code actions
48
+ range = code_action.dig(:edit, :documentChanges, 0, :edits, 0, :range)
49
+ code_action if diagnostic.dig(:data, :correctable) && cover?(range)
41
50
  end
42
- return [] if corrections.empty?
43
51
 
44
- T.cast(corrections, T::Array[Support::RuboCopDiagnostic]).map!(&:to_lsp_code_action)
52
+ code_actions << refactor_code_action(@range, @uri)
53
+ end
54
+
55
+ private
56
+
57
+ sig { params(range: T.nilable(Document::RangeShape)).returns(T::Boolean) }
58
+ def cover?(range)
59
+ range.nil? ||
60
+ ((@range.dig(:start, :line))..(@range.dig(:end, :line))).cover?(
61
+ (range.dig(:start, :line))..(range.dig(:end, :line)),
62
+ )
63
+ end
64
+
65
+ sig { params(range: Document::RangeShape, uri: String).returns(Interface::CodeAction) }
66
+ def refactor_code_action(range, uri)
67
+ Interface::CodeAction.new(
68
+ title: "Refactor: Extract Variable",
69
+ kind: Constant::CodeActionKind::REFACTOR_EXTRACT,
70
+ data: {
71
+ range: range,
72
+ uri: uri,
73
+ },
74
+ )
45
75
  end
46
76
  end
47
77
  end
@@ -15,7 +15,7 @@ module RubyLsp
15
15
  #
16
16
  # ```ruby
17
17
  # def say_hello
18
- # puts "Hello" # --> diagnostics: incorrect indentantion
18
+ # puts "Hello" # --> diagnostics: incorrect indentation
19
19
  # end
20
20
  # ```
21
21
  class Diagnostics < BaseRequest
@@ -28,17 +28,13 @@ module RubyLsp
28
28
  @uri = uri
29
29
  end
30
30
 
31
- sig do
32
- override.returns(
33
- T.any(
34
- T.all(T::Array[Support::RuboCopDiagnostic], Object),
35
- T.all(T::Array[Support::SyntaxErrorDiagnostic], Object),
36
- ),
37
- )
38
- end
31
+ sig { override.returns(T.nilable(T.all(T::Array[Support::RuboCopDiagnostic], Object))) }
39
32
  def run
40
- return [] if @document.syntax_error?
41
- return [] unless defined?(Support::RuboCopDiagnosticsRunner)
33
+ return if @document.syntax_error?
34
+ return unless defined?(Support::RuboCopDiagnosticsRunner)
35
+
36
+ # Don't try to run RuboCop diagnostics for files outside the current working directory
37
+ return unless @uri.sub("file://", "").start_with?(Dir.pwd)
42
38
 
43
39
  Support::RuboCopDiagnosticsRunner.instance.run(@uri, @document)
44
40
  end
@@ -32,8 +32,13 @@ module RubyLsp
32
32
  @uri = uri
33
33
  end
34
34
 
35
- sig { override.returns(T.nilable(T.all(T::Array[LanguageServer::Protocol::Interface::TextEdit], Object))) }
35
+ sig { override.returns(T.nilable(T.all(T::Array[Interface::TextEdit], Object))) }
36
36
  def run
37
+ # Don't try to format files outside the current working directory
38
+ return unless @uri.sub("file://", "").start_with?(Dir.pwd)
39
+
40
+ return if @document.syntax_error?
41
+
37
42
  formatted_text = formatted_file
38
43
  return unless formatted_text
39
44
 
@@ -41,10 +46,10 @@ module RubyLsp
41
46
  return if formatted_text.size == size && formatted_text == @document.source
42
47
 
43
48
  [
44
- LanguageServer::Protocol::Interface::TextEdit.new(
45
- range: LanguageServer::Protocol::Interface::Range.new(
46
- start: LanguageServer::Protocol::Interface::Position.new(line: 0, character: 0),
47
- end: LanguageServer::Protocol::Interface::Position.new(line: size, character: size),
49
+ Interface::TextEdit.new(
50
+ range: Interface::Range.new(
51
+ start: Interface::Position.new(line: 0, character: 0),
52
+ end: Interface::Position.new(line: size, character: size),
48
53
  ),
49
54
  new_text: formatted_text,
50
55
  ),
@@ -32,8 +32,8 @@ module RubyLsp
32
32
 
33
33
  scanner = document.create_scanner
34
34
  line_begin = position[:line] == 0 ? 0 : scanner.find_char_position({ line: position[:line] - 1, character: 0 })
35
- line_end = scanner.find_char_position(position)
36
- line = T.must(@document.source[line_begin..line_end])
35
+ @line_end = T.let(scanner.find_char_position(position), Integer)
36
+ line = T.must(@document.source[line_begin..@line_end])
37
37
 
38
38
  @indentation = T.let(find_indentation(line), Integer)
39
39
  @previous_line = T.let(line.strip.chomp, String)
@@ -42,7 +42,7 @@ module RubyLsp
42
42
  @trigger_character = trigger_character
43
43
  end
44
44
 
45
- sig { override.returns(T.nilable(T.all(T::Array[Interface::TextEdit], Object))) }
45
+ sig { override.returns(T.all(T::Array[Interface::TextEdit], Object)) }
46
46
  def run
47
47
  case @trigger_character
48
48
  when "{"
@@ -84,8 +84,30 @@ module RubyLsp
84
84
 
85
85
  indents = " " * @indentation
86
86
 
87
- add_edit_with_text(" \n#{indents}end")
88
- move_cursor_to(@position[:line], @indentation + 2)
87
+ if @previous_line.include?("\n")
88
+ # If the previous line has a line break, then it means there's content after the line break that triggered
89
+ # this completion. For these cases, we want to add the `end` after the content and move the cursor back to the
90
+ # keyword that triggered the completion
91
+
92
+ line = @position[:line]
93
+
94
+ # If there are enough lines in the document, we want to add the `end` token on the line below the extra
95
+ # content. Otherwise, we want to insert and extra line break ourselves
96
+ correction = if T.must(@document.source[@line_end..-1]).count("\n") >= 2
97
+ line -= 1
98
+ "#{indents}end"
99
+ else
100
+ "#{indents}\nend"
101
+ end
102
+
103
+ add_edit_with_text(correction, { line: @position[:line] + 1, character: @position[:character] })
104
+ move_cursor_to(line, @indentation + 3)
105
+ else
106
+ # If there's nothing after the new line break that triggered the completion, then we want to add the `end` and
107
+ # move the cursor to the body of the statement
108
+ add_edit_with_text(" \n#{indents}end")
109
+ move_cursor_to(@position[:line], @indentation + 2)
110
+ end
89
111
  end
90
112
 
91
113
  sig { params(spaces: String).void }
@@ -94,18 +116,15 @@ module RubyLsp
94
116
  move_cursor_to(@position[:line], @indentation + spaces.size + 1)
95
117
  end
96
118
 
97
- sig { params(text: String).void }
98
- def add_edit_with_text(text)
99
- position = Interface::Position.new(
100
- line: @position[:line],
101
- character: @position[:character],
119
+ sig { params(text: String, position: Document::PositionShape).void }
120
+ def add_edit_with_text(text, position = @position)
121
+ pos = Interface::Position.new(
122
+ line: position[:line],
123
+ character: position[:character],
102
124
  )
103
125
 
104
126
  @edits << Interface::TextEdit.new(
105
- range: Interface::Range.new(
106
- start: position,
107
- end: position,
108
- ),
127
+ range: Interface::Range.new(start: pos, end: pos),
109
128
  new_text: text,
110
129
  )
111
130
  end
@@ -0,0 +1,95 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RubyLsp
5
+ module Requests
6
+ # ![Path completion demo](../../misc/path_completion.gif)
7
+ #
8
+ # The [completion](https://microsoft.github.io/language-server-protocol/specification#textDocument_completion)
9
+ # request looks up Ruby files in the $LOAD_PATH to suggest path completion inside `require` statements.
10
+ #
11
+ # # Example
12
+ #
13
+ # ```ruby
14
+ # require "ruby_lsp/requests" # --> completion: suggests `base_request`, `code_actions`, ...
15
+ # ```
16
+ class PathCompletion < BaseRequest
17
+ extend T::Sig
18
+
19
+ sig { params(document: Document, position: Document::PositionShape).void }
20
+ def initialize(document, position)
21
+ super(document)
22
+
23
+ @tree = T.let(Support::PrefixTree.new(collect_load_path_files), Support::PrefixTree)
24
+ @position = position
25
+ end
26
+
27
+ sig { override.returns(T.all(T::Array[Interface::CompletionItem], Object)) }
28
+ def run
29
+ # We can't verify if we're inside a require when there are syntax errors
30
+ return [] if @document.syntax_error?
31
+
32
+ char_position = @document.create_scanner.find_char_position(@position)
33
+ target = T.let(find(char_position), T.nilable(SyntaxTree::TStringContent))
34
+ # no target means the we are not inside a `require` call
35
+ return [] unless target
36
+
37
+ text = target.value
38
+ @tree.search(text).sort.map! do |path|
39
+ build_completion(path, path.delete_prefix(text))
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ sig { returns(T::Array[String]) }
46
+ def collect_load_path_files
47
+ $LOAD_PATH.flat_map do |p|
48
+ Dir.glob("**/*.rb", base: p)
49
+ end.map! do |result|
50
+ result.delete_suffix!(".rb")
51
+ end
52
+ end
53
+
54
+ sig { params(position: Integer).returns(T.nilable(SyntaxTree::TStringContent)) }
55
+ def find(position)
56
+ matched, parent = locate(
57
+ T.must(@document.tree),
58
+ position,
59
+ node_types: [SyntaxTree::Command, SyntaxTree::CommandCall, SyntaxTree::CallNode],
60
+ )
61
+
62
+ return unless matched && parent
63
+
64
+ case matched
65
+ when SyntaxTree::Command, SyntaxTree::CallNode, SyntaxTree::CommandCall
66
+ return unless matched.message.value == "require"
67
+
68
+ args = matched.arguments
69
+ args = args.arguments if args.is_a?(SyntaxTree::ArgParen)
70
+
71
+ path_node = args.parts.first.parts.first
72
+ return unless path_node
73
+ return unless (path_node.location.start_char..path_node.location.end_char).cover?(position)
74
+
75
+ path_node
76
+ end
77
+ end
78
+
79
+ sig { params(label: String, insert_text: String).returns(Interface::CompletionItem) }
80
+ def build_completion(label, insert_text)
81
+ Interface::CompletionItem.new(
82
+ label: label,
83
+ text_edit: Interface::TextEdit.new(
84
+ range: Interface::Range.new(
85
+ start: @position,
86
+ end: @position,
87
+ ),
88
+ new_text: insert_text,
89
+ ),
90
+ kind: Constant::CompletionItemKind::REFERENCE,
91
+ )
92
+ end
93
+ end
94
+ end
95
+ end
@@ -20,7 +20,7 @@ module RubyLsp
20
20
  # ```
21
21
  class SemanticHighlighting < BaseRequest
22
22
  extend T::Sig
23
- include SyntaxTree::WithEnvironment
23
+ include SyntaxTree::WithScope
24
24
 
25
25
  TOKEN_TYPES = T.let(
26
26
  {
@@ -78,11 +78,28 @@ module RubyLsp
78
78
  T::Array[String],
79
79
  )
80
80
 
81
- class SemanticToken < T::Struct
82
- const :location, SyntaxTree::Location
83
- const :length, Integer
84
- const :type, Integer
85
- const :modifier, T::Array[Integer]
81
+ class SemanticToken
82
+ extend T::Sig
83
+
84
+ sig { returns(SyntaxTree::Location) }
85
+ attr_reader :location
86
+
87
+ sig { returns(Integer) }
88
+ attr_reader :length
89
+
90
+ sig { returns(Integer) }
91
+ attr_reader :type
92
+
93
+ sig { returns(T::Array[Integer]) }
94
+ attr_reader :modifier
95
+
96
+ sig { params(location: SyntaxTree::Location, length: Integer, type: Integer, modifier: T::Array[Integer]).void }
97
+ def initialize(location:, length:, type:, modifier:)
98
+ @location = location
99
+ @length = length
100
+ @type = type
101
+ @modifier = modifier
102
+ end
86
103
  end
87
104
 
88
105
  sig do
@@ -126,8 +143,10 @@ module RubyLsp
126
143
  visit(node.receiver)
127
144
 
128
145
  message = node.message
129
- unless message == :call || special_method?(message.value)
130
- add_token(message.location, :method)
146
+ if message != :call && !special_method?(message.value)
147
+ type = Support::Sorbet.annotation?(node) ? :type : :method
148
+
149
+ add_token(message.location, type)
131
150
  end
132
151
 
133
152
  visit(node.arguments)
@@ -137,7 +156,9 @@ module RubyLsp
137
156
  def visit_command(node)
138
157
  return super unless visible?(node, @range)
139
158
 
140
- add_token(node.message.location, :method) unless special_method?(node.message.value)
159
+ unless special_method?(node.message.value)
160
+ add_token(node.message.location, :method)
161
+ end
141
162
  visit(node.arguments)
142
163
  end
143
164
 
@@ -243,7 +264,10 @@ module RubyLsp
243
264
  def visit_vcall(node)
244
265
  return super unless visible?(node, @range)
245
266
 
246
- add_token(node.value.location, :method) unless special_method?(node.value.value)
267
+ return if special_method?(node.value.value)
268
+
269
+ type = Support::Sorbet.annotation?(node) ? :type : :method
270
+ add_token(node.value.location, type)
247
271
  end
248
272
 
249
273
  sig { override.params(node: SyntaxTree::ClassDeclaration).void }
@@ -305,7 +329,7 @@ module RubyLsp
305
329
 
306
330
  sig { params(value: SyntaxTree::Ident).returns(Symbol) }
307
331
  def type_for_local(value)
308
- local = current_environment.find_local(value.value)
332
+ local = current_scope.find_local(value.value)
309
333
 
310
334
  if local.nil? || local.type == :variable
311
335
  :variable
@@ -0,0 +1,46 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RubyLsp
5
+ module Requests
6
+ module Support
7
+ class Annotation
8
+ extend T::Sig
9
+ sig do
10
+ params(
11
+ arity: T.any(Integer, T::Range[Integer]),
12
+ receiver: T::Boolean,
13
+ ).void
14
+ end
15
+ def initialize(arity:, receiver: false)
16
+ @arity = arity
17
+ @receiver = receiver
18
+ end
19
+
20
+ sig { returns(T.any(Integer, T::Range[Integer])) }
21
+ attr_reader :arity
22
+
23
+ sig { returns(T::Boolean) }
24
+ attr_reader :receiver
25
+
26
+ sig { params(arity: T.any(T::Range[Integer], Integer)).returns(T::Boolean) }
27
+ def supports_arity?(arity)
28
+ if @arity.is_a?(Integer)
29
+ @arity == arity
30
+ elsif @arity.is_a?(Range)
31
+ @arity.cover?(arity)
32
+ else
33
+ T.absurd(@arity)
34
+ end
35
+ end
36
+
37
+ sig { params(receiver: T.nilable(String)).returns(T::Boolean) }
38
+ def supports_receiver?(receiver)
39
+ return receiver.nil? || receiver.empty? if @receiver == false
40
+
41
+ receiver == "T"
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -10,9 +10,20 @@ module RubyLsp
10
10
  READ = LanguageServer::Protocol::Constant::DocumentHighlightKind::READ
11
11
  WRITE = LanguageServer::Protocol::Constant::DocumentHighlightKind::WRITE
12
12
 
13
- class HighlightMatch < T::Struct
14
- const :type, Integer
15
- const :node, SyntaxTree::Node
13
+ class HighlightMatch
14
+ extend T::Sig
15
+
16
+ sig { returns(Integer) }
17
+ attr_reader :type
18
+
19
+ sig { returns(SyntaxTree::Node) }
20
+ attr_reader :node
21
+
22
+ sig { params(type: Integer, node: SyntaxTree::Node).void }
23
+ def initialize(type:, node:)
24
+ @type = type
25
+ @node = node
26
+ end
16
27
  end
17
28
 
18
29
  sig { params(node: SyntaxTree::Node).void }
@@ -0,0 +1,80 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RubyLsp
5
+ module Requests
6
+ module Support
7
+ class PrefixTree
8
+ extend T::Sig
9
+
10
+ sig { params(items: T::Array[String]).void }
11
+ def initialize(items)
12
+ @root = T.let(Node.new(""), Node)
13
+
14
+ items.each do |item|
15
+ insert(item)
16
+ end
17
+ end
18
+
19
+ sig { params(prefix: String).returns(T::Array[String]) }
20
+ def search(prefix)
21
+ node = T.let(@root, Node)
22
+
23
+ prefix.each_char do |char|
24
+ snode = node.children[char]
25
+ return [] unless snode
26
+
27
+ node = snode
28
+ end
29
+
30
+ node.collect
31
+ end
32
+
33
+ private
34
+
35
+ sig { params(item: String).void }
36
+ def insert(item)
37
+ node = T.let(@root, Node)
38
+
39
+ item.each_char do |char|
40
+ node = node.children[char] ||= Node.new(node.value + char)
41
+ end
42
+
43
+ node.leaf = true
44
+ end
45
+
46
+ class Node
47
+ extend T::Sig
48
+
49
+ sig { returns(T::Hash[String, Node]) }
50
+ attr_reader :children
51
+
52
+ sig { returns(String) }
53
+ attr_reader :value
54
+
55
+ sig { returns(T::Boolean) }
56
+ attr_accessor :leaf
57
+
58
+ sig { params(value: String).void }
59
+ def initialize(value)
60
+ @children = T.let({}, T::Hash[String, Node])
61
+ @value = T.let(value, String)
62
+ @leaf = T.let(false, T::Boolean)
63
+ end
64
+
65
+ sig { returns(T::Array[String]) }
66
+ def collect
67
+ result = T.let([], T::Array[String])
68
+ result << value if leaf
69
+
70
+ children.each_value do |node|
71
+ result.concat(node.collect)
72
+ end
73
+
74
+ result
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -9,52 +9,35 @@ module RubyLsp
9
9
 
10
10
  RUBOCOP_TO_LSP_SEVERITY = T.let(
11
11
  {
12
- convention: LanguageServer::Protocol::Constant::DiagnosticSeverity::INFORMATION,
13
- info: LanguageServer::Protocol::Constant::DiagnosticSeverity::INFORMATION,
14
- refactor: LanguageServer::Protocol::Constant::DiagnosticSeverity::INFORMATION,
15
- warning: LanguageServer::Protocol::Constant::DiagnosticSeverity::WARNING,
16
- error: LanguageServer::Protocol::Constant::DiagnosticSeverity::ERROR,
17
- fatal: LanguageServer::Protocol::Constant::DiagnosticSeverity::ERROR,
12
+ convention: Constant::DiagnosticSeverity::INFORMATION,
13
+ info: Constant::DiagnosticSeverity::INFORMATION,
14
+ refactor: Constant::DiagnosticSeverity::INFORMATION,
15
+ warning: Constant::DiagnosticSeverity::WARNING,
16
+ error: Constant::DiagnosticSeverity::ERROR,
17
+ fatal: Constant::DiagnosticSeverity::ERROR,
18
18
  }.freeze,
19
19
  T::Hash[Symbol, Integer],
20
20
  )
21
21
 
22
- sig { returns(T::Array[LanguageServer::Protocol::Interface::TextEdit]) }
23
- attr_reader :replacements
24
-
25
22
  sig { params(offense: RuboCop::Cop::Offense, uri: String).void }
26
23
  def initialize(offense, uri)
27
24
  @offense = offense
28
25
  @uri = uri
29
- @replacements = T.let(
30
- offense.correctable? ? offense_replacements : [],
31
- T::Array[LanguageServer::Protocol::Interface::TextEdit],
32
- )
33
- end
34
-
35
- sig { returns(T::Boolean) }
36
- def correctable?
37
- @offense.correctable?
38
26
  end
39
27
 
40
- sig { params(range: T::Range[Integer]).returns(T::Boolean) }
41
- def in_range?(range)
42
- range.cover?(@offense.line - 1)
43
- end
44
-
45
- sig { returns(LanguageServer::Protocol::Interface::CodeAction) }
28
+ sig { returns(Interface::CodeAction) }
46
29
  def to_lsp_code_action
47
- LanguageServer::Protocol::Interface::CodeAction.new(
30
+ Interface::CodeAction.new(
48
31
  title: "Autocorrect #{@offense.cop_name}",
49
- kind: LanguageServer::Protocol::Constant::CodeActionKind::QUICK_FIX,
50
- edit: LanguageServer::Protocol::Interface::WorkspaceEdit.new(
32
+ kind: Constant::CodeActionKind::QUICK_FIX,
33
+ edit: Interface::WorkspaceEdit.new(
51
34
  document_changes: [
52
- LanguageServer::Protocol::Interface::TextDocumentEdit.new(
53
- text_document: LanguageServer::Protocol::Interface::OptionalVersionedTextDocumentIdentifier.new(
35
+ Interface::TextDocumentEdit.new(
36
+ text_document: Interface::OptionalVersionedTextDocumentIdentifier.new(
54
37
  uri: @uri,
55
38
  version: nil,
56
39
  ),
57
- edits: @replacements,
40
+ edits: @offense.correctable? ? offense_replacements : [],
58
41
  ),
59
42
  ],
60
43
  ),
@@ -62,45 +45,47 @@ module RubyLsp
62
45
  )
63
46
  end
64
47
 
65
- sig { returns(LanguageServer::Protocol::Interface::Diagnostic) }
48
+ sig { returns(Interface::Diagnostic) }
66
49
  def to_lsp_diagnostic
67
50
  if @offense.correctable?
68
51
  severity = RUBOCOP_TO_LSP_SEVERITY[@offense.severity.name]
69
52
  message = @offense.message
70
53
  else
71
- severity = LanguageServer::Protocol::Constant::DiagnosticSeverity::WARNING
54
+ severity = Constant::DiagnosticSeverity::WARNING
72
55
  message = "#{@offense.message}\n\nThis offense is not auto-correctable.\n"
73
56
  end
74
- LanguageServer::Protocol::Interface::Diagnostic.new(
57
+
58
+ Interface::Diagnostic.new(
75
59
  message: message,
76
60
  source: "RuboCop",
77
61
  code: @offense.cop_name,
78
62
  severity: severity,
79
- range: LanguageServer::Protocol::Interface::Range.new(
80
- start: LanguageServer::Protocol::Interface::Position.new(
63
+ range: Interface::Range.new(
64
+ start: Interface::Position.new(
81
65
  line: @offense.line - 1,
82
66
  character: @offense.column,
83
67
  ),
84
- end: LanguageServer::Protocol::Interface::Position.new(
68
+ end: Interface::Position.new(
85
69
  line: @offense.last_line - 1,
86
70
  character: @offense.last_column,
87
71
  ),
88
72
  ),
73
+ data: {
74
+ correctable: @offense.correctable?,
75
+ code_action: to_lsp_code_action,
76
+ },
89
77
  )
90
78
  end
91
79
 
92
80
  private
93
81
 
94
- sig { returns(T::Array[LanguageServer::Protocol::Interface::TextEdit]) }
82
+ sig { returns(T::Array[Interface::TextEdit]) }
95
83
  def offense_replacements
96
84
  @offense.corrector.as_replacements.map do |range, replacement|
97
- LanguageServer::Protocol::Interface::TextEdit.new(
98
- range: LanguageServer::Protocol::Interface::Range.new(
99
- start: LanguageServer::Protocol::Interface::Position.new(line: range.line - 1, character: range.column),
100
- end: LanguageServer::Protocol::Interface::Position.new(
101
- line: range.last_line - 1,
102
- character: range.last_column,
103
- ),
85
+ Interface::TextEdit.new(
86
+ range: Interface::Range.new(
87
+ start: Interface::Position.new(line: range.line - 1, character: range.column),
88
+ end: Interface::Position.new(line: range.last_line - 1, character: range.last_column),
104
89
  ),
105
90
  new_text: replacement,
106
91
  )
@@ -21,7 +21,7 @@ module RubyLsp
21
21
  @runner = T.let(RuboCopRunner.new("-a"), RuboCopRunner)
22
22
  end
23
23
 
24
- sig { params(uri: String, document: Document).returns(T.nilable(String)) }
24
+ sig { params(uri: String, document: Document).returns(String) }
25
25
  def run(uri, document)
26
26
  filename = CGI.unescape(URI.parse(uri).path)
27
27