rubocop-lsp 0.1.1 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3c17a7ea5c41b994245f6f8d3231d64bd14debc7d694383f2e847f0ccef92d82
4
- data.tar.gz: c1b2f65bfd943cc815ac35196660296f11e89bdfd6945f605014c813c7244489
3
+ metadata.gz: 764e9fc1c28866c816e63128566630c67a64de01806866564321f79d24f8b6a0
4
+ data.tar.gz: 6fe1eec7178a026983f631c66e82c764994d86f4c4eb9336d6df947808547c31
5
5
  SHA512:
6
- metadata.gz: ffacb6a3e97dd4d3d70e8c36daf9a6d3864b1a732ea09fa5bb6f92cba96ea7cb4ac15d8e384fd82b839dea513af5de15da072289cbad99e90d80f9bb81298a3f
7
- data.tar.gz: 6d37b9ee07feda017345dd717c26c158d8cafe154d2b3c61b89d460d1edcc092cebfeb7fe68d1167e7036d097de9a41347b3208e19a438c355327037739ef4ca
6
+ metadata.gz: d2f731dae661bd512c8531918d8f69e977b2acc992f683678761fa1cb9d88b5454cae9b7e3abdbb5d273b42c0a36f8842084369ccfd6e1a0143760d26bf52cf7
7
+ data.tar.gz: b824829e84e030748ef6808e3acd7b84744d7127baf6afa23e7904825cd7d0d4ade4f89ce34f5f9f91d1e053b8635f4a109e0a7e3150913556828415450d2b85
@@ -1,3 +1,4 @@
1
1
  {
2
- "rubocop-lsp.trace.server": "verbose"
2
+ // "rubocop-lsp.trace.server": "verbose",
3
+ "editor.formatOnSave": true
3
4
  }
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rubocop-lsp (0.1.1)
4
+ rubocop-lsp (0.1.5)
5
5
  language_server-protocol (>= 3.16)
6
6
  rubocop (>= 1.0)
7
7
 
@@ -9,64 +9,66 @@ require "rubocop/lsp/handler"
9
9
  module Rubocop
10
10
  module Lsp
11
11
  module Cli
12
- Interface = LanguageServer::Protocol::Interface
13
- Constant = LanguageServer::Protocol::Constant
14
-
15
12
  def self.start(_argv)
16
13
  handler = Handler.new
17
14
 
18
15
  handler.config do
19
16
  on("initialize") do
20
- DiagnosticStore.clear_diagnostics
21
- Interface::InitializeResult.new(
22
- capabilities: Interface::ServerCapabilities.new(
23
- text_document_sync: Interface::TextDocumentSyncOptions.new(
24
- change: Constant::TextDocumentSyncKind::FULL,
25
- open_close: true
26
- ),
27
- code_action_provider: true
28
- ),
29
- )
17
+ store.clear
18
+
19
+ respond_with_capabilities
30
20
  end
31
21
 
32
22
  on("shutdown") do
33
- DiagnosticStore.clear_diagnostics
23
+ store.clear
24
+
34
25
  nil
35
26
  end
36
27
 
37
28
  on("textDocument/didChange") do |request|
38
- uri = request[:params][:textDocument][:uri]
39
- text = request[:params][:contentChanges][0][:text]
29
+ uri = request.dig(:params, :textDocument, :uri)
30
+ text = request.dig(:params, :contentChanges, 0, :text)
40
31
 
41
- send_diagnostics(uri: uri, text: text)
32
+ collector = collect_diagnostics(uri: uri, text: text)
33
+ send_diagnostics(collector)
42
34
 
43
35
  nil
44
36
  end
45
37
 
46
38
  on("textDocument/didOpen") do |request|
47
- uri = request[:params][:textDocument][:uri]
48
- text = request[:params][:textDocument][:text]
39
+ uri = request.dig(:params, :textDocument, :uri)
40
+ text = request.dig(:params, :textDocument, :text)
49
41
 
50
- send_diagnostics(uri: uri, text: text)
42
+ collector = collect_diagnostics(uri: uri, text: text)
43
+ send_diagnostics(collector)
51
44
 
52
45
  nil
53
46
  end
54
47
 
55
48
  on("textDocument/didClose") do |request|
56
- uri = request[:params][:textDocument][:uri]
57
-
58
- DiagnosticStore.remove_diagnostics_for(uri)
49
+ uri = request.dig(:params, :textDocument, :uri)
59
50
 
60
- send_diagnostics(uri: uri, diagnostics: [])
51
+ clear_diagnostics(uri: uri)
61
52
 
62
53
  nil
63
54
  end
64
55
 
56
+ on("textDocument/formatting") do |request|
57
+ uri = request.dig(:params, :textDocument, :uri)
58
+
59
+ collector = collect_diagnostics(uri: uri, text: store.text_for(uri))
60
+ send_text_edits(collector)
61
+ end
62
+
65
63
  on("textDocument/codeAction") do |request|
66
- uri = request[:params][:textDocument][:uri]
67
- range = request[:params][:range]
64
+ uri = request.dig(:params, :textDocument, :uri)
65
+ range = request.dig(:params, :range)
66
+ start_line = range.dig(:start, :line)
67
+ end_line = range.dig(:end, :line)
68
+
69
+ line_range = Range.new(start_line, end_line)
68
70
 
69
- DiagnosticStore.code_actions_for(uri, range)
71
+ send_code_actions(uri, line_range)
70
72
  end
71
73
  end
72
74
 
@@ -1,64 +1,44 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class DiagnosticCollector < RuboCop::Formatter::BaseFormatter
4
- Interface = LanguageServer::Protocol::Interface
5
- Constant = LanguageServer::Protocol::Constant
6
-
7
- attr_reader :diagnostics
8
-
9
- def initialize
10
- super({}, nil)
11
- end
12
-
13
- def run(file:, text:)
14
- config_store = ::RuboCop::ConfigStore.new
15
- options, paths = ::RuboCop::Options.new.parse(["--stderr"])
16
- # config_store.options_config = options[:config] if options[:config]
17
- options[:stdin] = text
18
- paths << file
19
- runner = ::RuboCop::Runner.new(options, config_store)
20
- runner.send(:formatter_set).clear.push(self)
21
- runner.run(paths)
22
- end
23
-
24
- def file_finished(_file, offenses)
25
- @diagnostics = offenses.map do |offense|
26
- diagnostic_from_offense(offense)
27
- end
28
- end
29
-
30
- private
31
-
32
- def diagnostic_from_offense(offense)
33
- Interface::Diagnostic.new(
34
- message: offense.message,
35
- severity: Constant::DiagnosticSeverity::INFORMATION,
36
- range: Interface::Range.new(
37
- start: Interface::Position.new(line: offense.line - 1, character: offense.column),
38
- end: Interface::Position.new(line: offense.last_line - 1, character: offense.last_column)
39
- ),
40
- data: {
41
- cop_name: offense.cop_name,
42
- edits: replacements_from_offense(offense),
43
- }
3
+ require "rubocop/lsp/model/diagnostic_collection"
4
+
5
+ class DiagnosticCollector < RuboCop::Runner
6
+ RUBOCOP_FLAGS = [
7
+ "--stderr", # Print any output to stderr so that our stdout does not get polluted
8
+ "--format",
9
+ "quiet", # Supress any progress output by setting the formatter to `quiet`
10
+ "--auto-correct", # Apply the autocorrects on the supplied buffer
11
+ ]
12
+
13
+ attr_reader :uri, :file, :text, :formatted_text, :diagnostics
14
+
15
+ def initialize(uri:, text:)
16
+ @uri = uri
17
+ @file = CGI.unescape(URI.parse(uri).path)
18
+ @text = text
19
+ @formatted_text = nil
20
+
21
+ super(
22
+ ::RuboCop::Options.new.parse(RUBOCOP_FLAGS).first,
23
+ ::RuboCop::ConfigStore.new
44
24
  )
45
25
  end
46
26
 
47
- def replacements_from_offense(offense)
48
- return unless offense.correctable?
27
+ def run
28
+ # Send text via "stdin".
29
+ # RuboCop reads all of stdin into the "stdin" option, when `--stdin`
30
+ # flag is supplied
31
+ @options[:stdin] = text
49
32
 
50
- offense.corrector.as_replacements.map do |range, replacement|
51
- edit_from_replacement(range, replacement)
52
- end
33
+ # Invoke the actual run method with just this file in `paths`
34
+ super([file])
35
+
36
+ # RuboCop applies autocorrections to the "stdin" option,
37
+ # so read that into the formatted text attribute
38
+ @formatted_text = @options[:stdin]
53
39
  end
54
40
 
55
- def edit_from_replacement(range, replacement)
56
- Interface::TextEdit.new(
57
- range: Interface::Range.new(
58
- start: Interface::Position.new(line: range.line - 1, character: range.column),
59
- end: Interface::Position.new(line: range.last_line - 1, character: range.last_column)
60
- ),
61
- new_text: replacement
62
- )
41
+ def file_finished(_file, offenses)
42
+ @diagnostics = Model::DiagnosticCollection.new(uri, offenses)
63
43
  end
64
44
  end
@@ -1,18 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "rubocop/lsp/diagnostic_store"
3
+ require "rubocop/lsp/state_store"
4
4
  require "rubocop/lsp/diagnostic_collector"
5
5
 
6
6
  class Handler
7
7
  Interface = LanguageServer::Protocol::Interface
8
8
  Constant = LanguageServer::Protocol::Constant
9
9
 
10
- attr_reader :writer, :reader
11
-
12
10
  def initialize
13
11
  @writer = LanguageServer::Protocol::Transport::Stdio::Writer.new
14
12
  @reader = LanguageServer::Protocol::Transport::Stdio::Reader.new
15
13
  @handlers = {}
14
+ @store = StateStore.new
16
15
  end
17
16
 
18
17
  def config(&blk)
@@ -27,6 +26,8 @@ class Handler
27
26
 
28
27
  private
29
28
 
29
+ attr_reader :writer, :reader, :store
30
+
30
31
  def on(message, &blk)
31
32
  @handlers[message.to_s] = blk
32
33
  end
@@ -51,22 +52,69 @@ class Handler
51
52
  writer.write(method: method, params: params)
52
53
  end
53
54
 
54
- def send_diagnostics(uri:, text: nil, diagnostics: [])
55
- diagnostics = collect_diagnostics(uri: uri, text: text) if text
55
+ def respond_with_capabilities
56
+ Interface::InitializeResult.new(
57
+ capabilities: Interface::ServerCapabilities.new(
58
+ text_document_sync: Interface::TextDocumentSyncOptions.new(
59
+ change: Constant::TextDocumentSyncKind::FULL,
60
+ open_close: true,
61
+ ),
62
+ document_formatting_provider: true,
63
+ code_action_provider: true
64
+ ),
65
+ )
66
+ end
56
67
 
68
+ def notify_diagnostics(uri:, diagnostics_response:)
57
69
  notify(
58
70
  method: "textDocument/publishDiagnostics",
59
71
  params: Interface::PublishDiagnosticsParams.new(
60
72
  uri: uri,
61
- diagnostics: diagnostics
73
+ diagnostics: diagnostics_response
62
74
  )
63
75
  )
64
76
  end
65
77
 
78
+ def clear_diagnostics(uri:)
79
+ store.delete(uri)
80
+
81
+ notify_diagnostics(uri: uri, diagnostics_response: [])
82
+ end
83
+
84
+ def send_diagnostics(collector)
85
+ notify_diagnostics(
86
+ uri: collector.uri,
87
+ diagnostics_response: collector.diagnostics.response
88
+ )
89
+ end
90
+
91
+ def send_code_actions(uri, line_range)
92
+ store.code_actions_for(uri, line_range)
93
+ end
94
+
95
+ def send_text_edits(collector)
96
+ return unless collector.formatted_text
97
+
98
+ [
99
+ Interface::TextEdit.new(
100
+ range: Interface::Range.new(
101
+ start: Interface::Position.new(line: 0, character: 0),
102
+ end: Interface::Position.new(
103
+ line: collector.text.size,
104
+ character: collector.text.size
105
+ )
106
+ ),
107
+ new_text: collector.formatted_text
108
+ ),
109
+ ]
110
+ end
111
+
66
112
  def collect_diagnostics(uri:, text:)
67
- file = CGI.unescape(URI.parse(uri).path)
68
- collector = DiagnosticCollector.new
69
- collector.run(file: file, text: text)
70
- DiagnosticStore.set_diagnostics_for(uri, collector.diagnostics)
113
+ collector = DiagnosticCollector.new(uri: uri, text: text)
114
+ collector.run
115
+
116
+ store.set(uri: collector.uri, text: collector.text, diagnostics: collector.diagnostics)
117
+
118
+ collector
71
119
  end
72
120
  end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Model
4
+ class Diagnostic
5
+ attr_reader :badge, :message, :start, :end, :replacements
6
+
7
+ DOCS_URLS = {
8
+ "Bundler": "https://docs.rubocop.org/rubocop/cops_bundler.html#%{anchor}",
9
+ "Gemspec": "https://docs.rubocop.org/rubocop/cops_gemspec.html#%{anchor}",
10
+ "Layout": "https://docs.rubocop.org/rubocop/cops_layout.html#%{anchor}",
11
+ "Lint": "https://docs.rubocop.org/rubocop/cops_lint.html#%{anchor}",
12
+ "Metrics": "https://docs.rubocop.org/rubocop/cops_metrics.html#%{anchor}",
13
+ "Migration": "https://docs.rubocop.org/rubocop/cops_migration.html#%{anchor}",
14
+ "Naming": "https://docs.rubocop.org/rubocop/cops_naming.html#%{anchor}",
15
+ "Security": "https://docs.rubocop.org/rubocop/cops_security.html#%{anchor}",
16
+ "Style": "https://docs.rubocop.org/rubocop/cops_style.html#%{anchor}",
17
+ "Minitest": "https://docs.rubocop.org/rubocop-minitest/cops_minitest.html#%{anchor}",
18
+ "Performance": "https://docs.rubocop.org/rubocop-performance/cops_performance.html#%{anchor}",
19
+ "Rails": "https://docs.rubocop.org/rubocop-rails/cops_rails.html#%{anchor}",
20
+ "RSpec": "https://docs.rubocop.org/rubocop-rspec/cops_rspec.html#%{anchor}",
21
+ "RSpec/Capybara": "https://docs.rubocop.org/rubocop-rspec/cops_rspec/capybara.html#%{anchor}",
22
+ "RSpec/FactoryBot": "https://docs.rubocop.org/rubocop-rspec/cops_rspec/factorybot.html#%{anchor}",
23
+ "RSpec/Rails": "https://docs.rubocop.org/rubocop-rspec/cops_rspec/rails.html#%{anchor}",
24
+ "Sorbet": "https://github.com/Shopify/rubocop-sorbet/blob/master/manual/cops_sorbet.md#%{anchor}",
25
+ }
26
+
27
+ def initialize(offense)
28
+ @badge = RuboCop::Cop::Badge.parse(offense.cop_name)
29
+ @message = offense.message
30
+ @start = Interface::Position.new(line: offense.line - 1, character: offense.column)
31
+ @end = Interface::Position.new(line: offense.last_line - 1, character: offense.last_column)
32
+ @replacements = replacements_from_offense(offense)
33
+ end
34
+
35
+ def correctable?
36
+ !!@replacements
37
+ end
38
+
39
+ def cop_name
40
+ @cop_name ||= badge.to_s
41
+ end
42
+
43
+ def diagnostic_response
44
+ @diagnostic_response ||= Interface::Diagnostic.new(
45
+ message: message,
46
+ "source": "RuboCop",
47
+ code: cop_name,
48
+ code_description: Interface::CodeDescription.new(
49
+ href: doc_url
50
+ ),
51
+ severity: Constant::DiagnosticSeverity::INFORMATION,
52
+ range: Interface::Range.new(
53
+ start: start,
54
+ end: self.end
55
+ )
56
+ )
57
+ end
58
+
59
+ private
60
+
61
+ def doc_url
62
+ @doc_url ||= begin
63
+ anchor = cop_name.downcase.gsub(%r{/}, "")
64
+
65
+ format(DOCS_URLS[badge.department], anchor: anchor)
66
+ end
67
+ end
68
+
69
+ def replacements_from_offense(offense)
70
+ return unless offense.correctable?
71
+
72
+ offense.corrector.as_replacements.map do |range, replacement|
73
+ edit_from_replacement(range, replacement)
74
+ end
75
+ end
76
+
77
+ def edit_from_replacement(range, replacement)
78
+ Interface::TextEdit.new(
79
+ range: Interface::Range.new(
80
+ start: Interface::Position.new(line: range.line - 1, character: range.column),
81
+ end: Interface::Position.new(line: range.last_line - 1, character: range.last_column)
82
+ ),
83
+ new_text: replacement
84
+ )
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rubocop/lsp/model/diagnostic"
4
+
5
+ module Model
6
+ Interface = LanguageServer::Protocol::Interface
7
+ Constant = LanguageServer::Protocol::Constant
8
+
9
+ class DiagnosticCollection
10
+ attr_reader :uri, :diagnostics
11
+
12
+ def initialize(uri, offenses)
13
+ @uri = uri
14
+ @diagnostics = offenses.map do |offense|
15
+ Diagnostic.new(offense)
16
+ end
17
+ end
18
+
19
+ def response
20
+ diagnostics.map(&:diagnostic_response)
21
+ end
22
+
23
+ def correctable_diagnostics
24
+ @correctable_diagnostics ||= diagnostics.select(&:correctable?)
25
+ end
26
+
27
+ def code_actions(line_range)
28
+ line_diagnostics = correctable_diagnostics.select do |diagnostic|
29
+ line_range.include?(diagnostic.start.line)
30
+ end
31
+
32
+ actions = line_diagnostics.map do |diagnostic|
33
+ code_action_from(
34
+ diagnostic,
35
+ title: "Autocorrect `#{diagnostic.cop_name}`",
36
+ kind: Constant::CodeActionKind::QUICK_FIX
37
+ )
38
+ end
39
+
40
+ if actions.any?
41
+ actions << code_action_from(
42
+ line_diagnostics,
43
+ title: "Autocorrect all offenses on line",
44
+ kind: "rubocop.fix"
45
+ )
46
+ end
47
+
48
+ actions
49
+ end
50
+
51
+ private
52
+
53
+ def code_action_from(diagnostics, title:, kind:)
54
+ diagnostics = Array(diagnostics)
55
+
56
+ Interface::CodeAction.new(
57
+ title: title,
58
+ kind: kind,
59
+ edit: Interface::WorkspaceEdit.new(
60
+ document_changes: [
61
+ Interface::TextDocumentEdit.new(
62
+ text_document: Interface::OptionalVersionedTextDocumentIdentifier.new(
63
+ uri: uri,
64
+ version: nil
65
+ ),
66
+ edits: diagnostics.flat_map(&:replacements)
67
+ ),
68
+ ]
69
+ ),
70
+ is_preferred: true,
71
+ )
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class State
4
+ attr_reader :uri, :text, :diagnostics
5
+
6
+ def initialize(uri:, text:, diagnostics: [])
7
+ @uri = uri
8
+ @text = text
9
+ @diagnostics = diagnostics
10
+ end
11
+
12
+ def code_actions(line_range)
13
+ diagnostics.code_actions(line_range)
14
+ end
15
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rubocop/lsp/state"
4
+
5
+ class StateStore
6
+ def initialize
7
+ @state_map = {}
8
+ end
9
+
10
+ def clear
11
+ @state_map = {}
12
+ end
13
+
14
+ def delete(uri)
15
+ @state_map.delete(uri)
16
+ []
17
+ end
18
+
19
+ def set(uri:, text:, diagnostics: [])
20
+ @state_map[uri] = State.new(uri: uri, text: text, diagnostics: diagnostics || [])
21
+ end
22
+
23
+ def get(uri)
24
+ @state_map[uri]
25
+ end
26
+
27
+ def text_for(uri)
28
+ state = get(uri)
29
+
30
+ return state.text if state
31
+
32
+ file = CGI.unescape(URI.parse(uri).path)
33
+ File.binread(file)
34
+ end
35
+
36
+ def code_actions_for(uri, line_range)
37
+ state = get(uri)
38
+
39
+ return [] unless state
40
+
41
+ state.code_actions(line_range)
42
+ end
43
+
44
+ private
45
+
46
+ attr_reader :state_map
47
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Rubocop
4
4
  module Lsp
5
- VERSION = "0.1.1"
5
+ VERSION = "0.1.5"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-lsp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-07-22 00:00:00.000000000 Z
11
+ date: 2021-08-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop
@@ -60,8 +60,11 @@ files:
60
60
  - lib/rubocop/lsp.rb
61
61
  - lib/rubocop/lsp/cli.rb
62
62
  - lib/rubocop/lsp/diagnostic_collector.rb
63
- - lib/rubocop/lsp/diagnostic_store.rb
64
63
  - lib/rubocop/lsp/handler.rb
64
+ - lib/rubocop/lsp/model/diagnostic.rb
65
+ - lib/rubocop/lsp/model/diagnostic_collection.rb
66
+ - lib/rubocop/lsp/state.rb
67
+ - lib/rubocop/lsp/state_store.rb
65
68
  - lib/rubocop/lsp/version.rb
66
69
  - rubocop-lsp.gemspec
67
70
  homepage: https://github.com/Shopify/rubocop-lsp
@@ -1,85 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DiagnosticStore
4
- @diagnostic_map = {}
5
-
6
- def self.clear_diagnostics
7
- @diagnostic_map = {}
8
- end
9
-
10
- def self.remove_diagnostics_for(uri)
11
- @diagnostic_map.delete(uri)
12
- []
13
- end
14
-
15
- def self.set_diagnostics_for(uri, diagnostics)
16
- @diagnostic_map[uri] = diagnostics
17
- end
18
-
19
- def self.diagnostics_for(uri)
20
- @diagnostic_map[uri] || []
21
- end
22
-
23
- def self.correctable_diagnostics_for(uri)
24
- diagnostics_for(uri).reject do |diagnostic|
25
- diagnostic.data[:edits].nil?
26
- end
27
- end
28
-
29
- def self.code_actions_for(uri, range)
30
- line_range = Range.new(range[:start][:line], range[:end][:line])
31
-
32
- file_diagnostics = correctable_diagnostics_for(uri)
33
- line_diagnostics = file_diagnostics.select { |diagnostic| line_range.include?(diagnostic.range.start.line) }
34
- actions = line_diagnostics.map { |diagnostic| code_action_from(uri, diagnostic) }
35
-
36
- unless actions.empty?
37
- actions << code_action_from_diagnostics(uri, line_diagnostics, title: "Autocorrect all offenses on line")
38
- actions << code_action_from_diagnostics(uri, file_diagnostics, title: "Autocorrect all offenses in file")
39
- end
40
-
41
- actions
42
- end
43
-
44
- def self.code_action_from_diagnostics(uri, diagnostics, title:)
45
- diagnostics = diagnostics.sort_by do |diagnostic|
46
- [diagnostic.range.start.line, diagnostic.range.start.character]
47
- end
48
-
49
- LanguageServer::Protocol::Interface::CodeAction.new(
50
- title: title,
51
- kind: "rubocop.fix",
52
- edit: LanguageServer::Protocol::Interface::WorkspaceEdit.new(
53
- document_changes: [
54
- LanguageServer::Protocol::Interface::TextDocumentEdit.new(
55
- text_document: LanguageServer::Protocol::Interface::OptionalVersionedTextDocumentIdentifier.new(
56
- uri: uri,
57
- version: nil
58
- ),
59
- edits: diagnostics.flat_map { |d| d.data[:edits] }
60
- ),
61
- ]
62
- ),
63
- is_preferred: true,
64
- )
65
- end
66
-
67
- def self.code_action_from(uri, diagnostic)
68
- LanguageServer::Protocol::Interface::CodeAction.new(
69
- title: "Autocorrect `#{diagnostic.data[:cop_name]}`",
70
- kind: LanguageServer::Protocol::Constant::CodeActionKind::QUICK_FIX,
71
- edit: LanguageServer::Protocol::Interface::WorkspaceEdit.new(
72
- document_changes: [
73
- LanguageServer::Protocol::Interface::TextDocumentEdit.new(
74
- text_document: LanguageServer::Protocol::Interface::OptionalVersionedTextDocumentIdentifier.new(
75
- uri: uri,
76
- version: nil
77
- ),
78
- edits: diagnostic.data[:edits]
79
- ),
80
- ]
81
- ),
82
- is_preferred: true,
83
- )
84
- end
85
- end