rubocop-lsp 0.1.1 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
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