standard 1.23.0 → 1.24.1

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: ec668f31e8de1959e062f5dbb2cf5e35271df24c5852658594c6ad3e9b36369a
4
- data.tar.gz: 458b4c01b10be7f37ffa140575d3ccf90d8be56778a4b4752961c9cb0b6e8940
3
+ metadata.gz: 69342b56c2cb5d98f491d5c02cb7d787c667954fe4422654ddc434d0f34384b4
4
+ data.tar.gz: 7945846b4e2a92e4543752ccd7034a8ce5e441d126f5604d72333cd3b2ec1966
5
5
  SHA512:
6
- metadata.gz: 3da9df5fa960b922f29da77dfa2f8379180726bed9d0021916a08dae0d7c082056985c1c22ff7c855db050d7006d0b02370b58b2adeb9c5591f7a3fb42122ed9
7
- data.tar.gz: 549557b4f5bf4ad6a9e7d63b4414ddac999bd0088992e28580158b68a43100677bc066ebebbe29a382a9efb431bbb1c32bca60e5c333ac443730229763b42f05
6
+ metadata.gz: 49e59dc51822c205910db0f1dc318e26012875ae727c00d1f358779b7292799e1d6ce4df36d321fd4a1633471afc86a218697bfd9dc7b00b73e62efc2bdbe7c8
7
+ data.tar.gz: 29dfd9bb60acb15d038be99e338e6376894237e8fe1fac78915b9c8f76040a17e6b3fcd7f14a072b9c6e712f256e8ef51445099993604a57c3b14d9675bb4285
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.24.1
4
+
5
+ * _Further_ improve `--lsp` server to better support commands used by VS Code
6
+
7
+ ## 1.24.0
8
+
9
+ * Improve `--lsp` server to better support the commands used by VS Code
10
+
3
11
  ## 1.23.0
4
12
 
5
13
  * Update rubocop from 1.42.0 to [1.44.1](https://github.com/rubocop/rubocop/releases/tag/v1.44.1)
data/Gemfile CHANGED
@@ -7,6 +7,7 @@ gem "minitest", "~> 5.0"
7
7
  gem "pry"
8
8
  gem "rake", "~> 13.0"
9
9
  gem "gimme"
10
+ gem "m"
10
11
 
11
12
  if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.5")
12
13
  gem "simplecov"
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- standard (1.23.0)
4
+ standard (1.24.1)
5
5
  language_server-protocol (~> 3.17.0.2)
6
6
  rubocop (= 1.44.1)
7
7
  rubocop-performance (= 1.15.2)
@@ -15,17 +15,20 @@ GEM
15
15
  gimme (0.5.0)
16
16
  json (2.6.3)
17
17
  language_server-protocol (3.17.0.3)
18
+ m (1.6.1)
19
+ method_source (>= 0.6.7)
20
+ rake (>= 0.9.2.2)
18
21
  method_source (1.0.0)
19
22
  minitest (5.17.0)
20
23
  parallel (1.22.1)
21
- parser (3.2.0.0)
24
+ parser (3.2.1.0)
22
25
  ast (~> 2.4.1)
23
26
  pry (0.14.2)
24
27
  coderay (~> 1.1)
25
28
  method_source (~> 1.0)
26
29
  rainbow (3.1.1)
27
30
  rake (13.0.6)
28
- regexp_parser (2.6.2)
31
+ regexp_parser (2.7.0)
29
32
  rexml (3.2.5)
30
33
  rubocop (1.44.1)
31
34
  json (~> 2.3)
@@ -58,6 +61,7 @@ PLATFORMS
58
61
  DEPENDENCIES
59
62
  bundler
60
63
  gimme
64
+ m
61
65
  minitest (~> 5.0)
62
66
  pry
63
67
  rake (~> 13.0)
@@ -0,0 +1,10 @@
1
+ module Standard
2
+ module Lsp
3
+ class KillsServer
4
+ def call(&blk)
5
+ at_exit(&blk) unless blk.nil?
6
+ exit 0
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ module Standard
2
+ module Lsp
3
+ class Logger
4
+ def puts(message)
5
+ warn("[server] #{message}")
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,194 @@
1
+ require_relative "kills_server"
2
+
3
+ module Standard
4
+ module Lsp
5
+ class Routes
6
+ def initialize(writer, logger, standardizer)
7
+ @writer = writer
8
+ @logger = logger
9
+ @standardizer = standardizer
10
+
11
+ @text_cache = {}
12
+ @kills_server = KillsServer.new
13
+ end
14
+
15
+ def self.handle(name, &block)
16
+ define_method("handle_#{name}", &block)
17
+ end
18
+
19
+ def for(name)
20
+ name = "handle_#{name}"
21
+ if respond_to?(name)
22
+ method(name)
23
+ end
24
+ end
25
+
26
+ handle "initialize" do |request|
27
+ @writer.write(id: request[:id], result: Proto::Interface::InitializeResult.new(
28
+ capabilities: Proto::Interface::ServerCapabilities.new(
29
+ document_formatting_provider: true,
30
+ diagnostic_provider: true,
31
+ execute_command_provider: true,
32
+ text_document_sync: Proto::Interface::TextDocumentSyncOptions.new(
33
+ change: Proto::Constant::TextDocumentSyncKind::FULL
34
+ )
35
+ )
36
+ ))
37
+ end
38
+
39
+ handle "initialized" do |request|
40
+ @logger.puts "Standard Ruby v#{Standard::VERSION} LSP server initialized, pid #{Process.pid}"
41
+ end
42
+
43
+ handle "shutdown" do |request|
44
+ @logger.puts "Client asked to shutdown Standard LSP server."
45
+ @kills_server.call do
46
+ @writer.write(id: request[:id], result: nil)
47
+ @logger.puts "Exiting..."
48
+ end
49
+ end
50
+
51
+ handle "textDocument/diagnostic" do |request|
52
+ doc = request[:params][:textDocument]
53
+ result = diagnostic(doc[:uri], doc[:text])
54
+ @writer.write(result)
55
+ end
56
+
57
+ handle "textDocument/didChange" do |request|
58
+ params = request[:params]
59
+ result = diagnostic(params[:textDocument][:uri], params[:contentChanges][0][:text])
60
+ @writer.write(result)
61
+ end
62
+
63
+ handle "textDocument/didOpen" do |request|
64
+ doc = request[:params][:textDocument]
65
+ result = diagnostic(doc[:uri], doc[:text])
66
+ @writer.write(result)
67
+ end
68
+
69
+ handle "textDocument/didClose" do |request|
70
+ @text_cache.delete(request.dig(:params, :textDocument, :uri))
71
+ end
72
+
73
+ handle "textDocument/formatting" do |request|
74
+ uri = request[:params][:textDocument][:uri]
75
+ @writer.write({id: request[:id], result: format_file(uri)})
76
+ end
77
+
78
+ handle "workspace/didChangeWatchedFiles" do |request|
79
+ if request[:params][:changes].any? { |change| change[:uri].end_with?(".standard.yml") }
80
+ @logger.puts "Configuration file changed; restart required"
81
+ @kills_server.call
82
+ end
83
+ end
84
+
85
+ handle "workspace/executeCommand" do |request|
86
+ if request[:params][:command] == "standardRuby.formatAutoFixes"
87
+ uri = request[:params][:arguments][0][:uri]
88
+ @writer.write({
89
+ id: request[:id],
90
+ method: "workspace/applyEdit",
91
+ params: {
92
+ label: "Format with Standard Ruby auto-fixes",
93
+ edit: {
94
+ changes: {
95
+ uri => format_file(uri)
96
+ }
97
+ }
98
+ }
99
+ })
100
+ else
101
+ handle_unsupported_method(request, request[:params][:command])
102
+ end
103
+ end
104
+
105
+ handle "textDocument/didSave" do |_request|
106
+ # Nothing to do
107
+ end
108
+
109
+ handle "$/cancelRequest" do |_request|
110
+ # Can't cancel anything because single-threaded
111
+ end
112
+
113
+ handle "$/setTrace" do |_request|
114
+ # No-op, we log everything
115
+ end
116
+
117
+ def handle_unsupported_method(request, method = request[:method])
118
+ @writer.write({id: request[:id], error: Proto::Interface::ResponseError.new(
119
+ code: Proto::Constant::ErrorCodes::METHOD_NOT_FOUND,
120
+ message: "Unsupported Method: #{method}"
121
+ )})
122
+ @logger.puts "Unsupported Method: #{method}"
123
+ end
124
+
125
+ private
126
+
127
+ def format_file(file_uri)
128
+ text = @text_cache[file_uri]
129
+ if text.nil?
130
+ @logger.puts "Format request arrived before text synchonized; skipping: `#{file_uri}'"
131
+ []
132
+ else
133
+ new_text = @standardizer.format(text)
134
+ if new_text == text
135
+ []
136
+ else
137
+ [{
138
+ newText: new_text,
139
+ range: {
140
+ start: {line: 0, character: 0},
141
+ end: {line: text.count("\n") + 1, character: 0}
142
+ }
143
+ }]
144
+ end
145
+ end
146
+ end
147
+
148
+ def diagnostic(file_uri, text)
149
+ @text_cache[file_uri] = text
150
+ offenses = @standardizer.offenses(text)
151
+
152
+ lsp_diagnostics = offenses.map { |o|
153
+ code = o[:cop_name]
154
+
155
+ msg = o[:message].delete_prefix(code)
156
+ loc = o[:location]
157
+
158
+ severity = case o[:severity]
159
+ when "error", "fatal"
160
+ SEV::ERROR
161
+ when "warning"
162
+ SEV::WARNING
163
+ when "convention"
164
+ SEV::INFORMATION
165
+ when "refactor", "info"
166
+ SEV::HINT
167
+ else # the above cases fully cover what RuboCop sends at this time
168
+ logger.puts "Unknown severity: #{severity.inspect}"
169
+ SEV::HINT
170
+ end
171
+
172
+ {
173
+ code: code,
174
+ message: msg,
175
+ range: {
176
+ start: {character: loc[:start_column] - 1, line: loc[:start_line] - 1},
177
+ end: {character: loc[:last_column] - 1, line: loc[:last_line] - 1}
178
+ },
179
+ severity: severity,
180
+ source: "standard"
181
+ }
182
+ }
183
+
184
+ {
185
+ method: "textDocument/publishDiagnostics",
186
+ params: {
187
+ uri: file_uri,
188
+ diagnostics: lsp_diagnostics
189
+ }
190
+ }
191
+ end
192
+ end
193
+ end
194
+ end
@@ -1,144 +1,41 @@
1
1
  require "language_server-protocol"
2
2
  require_relative "standardizer"
3
+ require_relative "routes"
4
+ require_relative "logger"
3
5
 
4
6
  module Standard
5
- module LSP
6
- class Server
7
- Proto = LanguageServer::Protocol
8
- SEV = Proto::Constant::DiagnosticSeverity
7
+ module Lsp
8
+ Proto = LanguageServer::Protocol
9
+ SEV = Proto::Constant::DiagnosticSeverity
9
10
 
11
+ class Server
10
12
  def self.start(standardizer)
11
13
  new(standardizer).start
12
14
  end
13
15
 
14
- attr_accessor :standardizer, :writer, :reader, :logger, :text_cache, :subscribers
15
-
16
16
  def initialize(standardizer)
17
- self.standardizer = standardizer
18
- self.writer = Proto::Transport::Io::Writer.new($stdout)
19
- self.reader = Proto::Transport::Io::Reader.new($stdin)
20
- self.logger = $stderr
21
- self.text_cache = {}
22
-
23
- self.subscribers = {
24
- "initialize" => ->(request) {
25
- init_result = Proto::Interface::InitializeResult.new(
26
- capabilities: Proto::Interface::ServerCapabilities.new(
27
- document_formatting_provider: true,
28
- diagnostic_provider: true,
29
- text_document_sync: Proto::Constant::TextDocumentSyncKind::FULL
30
- )
31
- )
32
- writer.write(id: request[:id], result: init_result)
33
- },
34
-
35
- "initialized" => ->(request) { logger.puts "standard v#{Standard::VERSION} initialized, pid #{Process.pid}" },
36
-
37
- "shutdown" => ->(request) {
38
- logger.puts "asked to shutdown, exiting..."
39
- exit
40
- },
41
-
42
- "textDocument/didChange" => ->(request) {
43
- params = request[:params]
44
- result = diagnostic(params[:textDocument][:uri], params[:contentChanges][0][:text])
45
- writer.write(result)
46
- },
47
-
48
- "textDocument/didOpen" => ->(request) {
49
- td = request[:params][:textDocument]
50
- result = diagnostic(td[:uri], td[:text])
51
- writer.write(result)
52
- },
53
-
54
- "textDocument/didClose" => ->(request) {
55
- text_cache.delete(request.dig(:params, :textDocument, :uri))
56
- },
57
-
58
- "textDocument/formatting" => ->(request) {
59
- uri = request[:params][:textDocument][:uri]
60
- writer.write({id: request[:id], result: format_file(uri)})
61
- },
62
-
63
- "textDocument/didSave" => ->(request) {}
64
- }
17
+ @standardizer = standardizer
18
+ @writer = Proto::Transport::Io::Writer.new($stdout)
19
+ @reader = Proto::Transport::Io::Reader.new($stdin)
20
+ @logger = Logger.new
21
+ @routes = Routes.new(@writer, @logger, @standardizer)
65
22
  end
66
23
 
67
24
  def start
68
- reader.read do |request|
25
+ @reader.read do |request|
26
+ next unless request.key?(:method) # ignore responses without methods
27
+
69
28
  method = request[:method]
70
- if (subscriber = subscribers[method])
71
- subscriber.call(request)
29
+ if (route = @routes.for(method))
30
+ route.call(request)
72
31
  else
73
- logger.puts "unknown method: #{method}"
32
+ @routes.handle_unsupported_method(request)
74
33
  end
75
34
  rescue => e
76
- logger.puts "error #{e.class} #{e.message[0..100]}"
77
- logger.puts e.backtrace.inspect
35
+ @logger.puts "Error #{e.class} #{e.message[0..100]}"
36
+ @logger.puts e.backtrace.inspect
78
37
  end
79
38
  end
80
-
81
- def format_file(file_uri)
82
- text = text_cache[file_uri]
83
- new_text = standardizer.format(text)
84
-
85
- if new_text == text
86
- []
87
- else
88
- [{
89
- newText: new_text,
90
- range: {
91
- start: {line: 0, character: 0},
92
- end: {line: text.count("\n") + 1, character: 0}
93
- }
94
- }]
95
- end
96
- end
97
-
98
- def diagnostic(file_uri, text)
99
- text_cache[file_uri] = text
100
- offenses = standardizer.offenses(text)
101
-
102
- lsp_diagnostics = offenses.map { |o|
103
- code = o[:cop_name]
104
-
105
- msg = o[:message].delete_prefix(code)
106
- loc = o[:location]
107
-
108
- severity = case o[:severity]
109
- when "error", "fatal"
110
- SEV::ERROR
111
- when "warning"
112
- SEV::WARNING
113
- when "convention"
114
- SEV::INFORMATION
115
- when "refactor", "info"
116
- SEV::HINT
117
- else # the above cases fully cover what RuboCop sends at this time
118
- logger.puts "unknown severity: #{severity.inspect}"
119
- SEV::HINT
120
- end
121
-
122
- {
123
- code: code,
124
- message: msg,
125
- range: {
126
- start: {character: loc[:start_column] - 1, line: loc[:start_line] - 1},
127
- end: {character: loc[:last_column] - 1, line: loc[:last_line] - 1}
128
- },
129
- severity: severity,
130
- source: "standard"
131
- }
132
- }
133
-
134
- {
135
- method: "textDocument/publishDiagnostics",
136
- params: {
137
- diagnostics: lsp_diagnostics,
138
- uri: file_uri
139
- }
140
- }
141
- end
142
39
  end
143
40
  end
144
41
  end
@@ -2,7 +2,7 @@ require_relative "../runners/rubocop"
2
2
  require "tempfile"
3
3
 
4
4
  module Standard
5
- module LSP
5
+ module Lsp
6
6
  class Standardizer
7
7
  def initialize(config)
8
8
  @template_options = config
@@ -4,8 +4,8 @@ module Standard
4
4
  module Runners
5
5
  class Lsp
6
6
  def call(config)
7
- standardizer = Standard::LSP::Standardizer.new(config)
8
- Standard::LSP::Server.start(standardizer)
7
+ standardizer = Standard::Lsp::Standardizer.new(config)
8
+ Standard::Lsp::Server.start(standardizer)
9
9
  end
10
10
  end
11
11
  end
@@ -1,3 +1,3 @@
1
1
  module Standard
2
- VERSION = Gem::Version.new("1.23.0")
2
+ VERSION = Gem::Version.new("1.24.1")
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: standard
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.23.0
4
+ version: 1.24.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Searls
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-02-06 00:00:00.000000000 Z
11
+ date: 2023-02-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop
@@ -52,7 +52,7 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 3.17.0.2
55
- description:
55
+ description:
56
56
  email:
57
57
  - searls@gmail.com
58
58
  executables:
@@ -102,6 +102,9 @@ files:
102
102
  - lib/standard/formatter.rb
103
103
  - lib/standard/loads_runner.rb
104
104
  - lib/standard/loads_yaml_config.rb
105
+ - lib/standard/lsp/kills_server.rb
106
+ - lib/standard/lsp/logger.rb
107
+ - lib/standard/lsp/routes.rb
105
108
  - lib/standard/lsp/server.rb
106
109
  - lib/standard/lsp/standardizer.rb
107
110
  - lib/standard/merges_settings.rb
@@ -120,7 +123,7 @@ files:
120
123
  homepage: https://github.com/testdouble/standard
121
124
  licenses: []
122
125
  metadata: {}
123
- post_install_message:
126
+ post_install_message:
124
127
  rdoc_options: []
125
128
  require_paths:
126
129
  - lib
@@ -135,8 +138,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
138
  - !ruby/object:Gem::Version
136
139
  version: '0'
137
140
  requirements: []
138
- rubygems_version: 3.1.6
139
- signing_key:
141
+ rubygems_version: 3.3.26
142
+ signing_key:
140
143
  specification_version: 4
141
144
  summary: Ruby Style Guide, with linter & automatic code fixer
142
145
  test_files: []