standard 1.23.0 → 1.24.1

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: 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: []