standard 1.23.0 → 1.24.0

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: c0671d43dc2bb8c9d1337a61ea48651fa7bf9d47f3e9c427e27603d5eed9d462
4
+ data.tar.gz: b98d3235ec3a617dfe3c6dbb57d827c6f4aff4670c53c5e4dccf92a003b79206
5
5
  SHA512:
6
- metadata.gz: 3da9df5fa960b922f29da77dfa2f8379180726bed9d0021916a08dae0d7c082056985c1c22ff7c855db050d7006d0b02370b58b2adeb9c5591f7a3fb42122ed9
7
- data.tar.gz: 549557b4f5bf4ad6a9e7d63b4414ddac999bd0088992e28580158b68a43100677bc066ebebbe29a382a9efb431bbb1c32bca60e5c333ac443730229763b42f05
6
+ metadata.gz: 465bf72a4d1585c54e93d290358a13e2a5b4e4890c428f41f08918bec2d6365367f41f8b7b3614765d4eb6a7557c9ef13823a845e86ce3f54f39e043027a93cf
7
+ data.tar.gz: b9c98f70f328bdad82f563f8fa572f5ea18389bdebeb81b830b54c23197cedfb9918ee29d7a1dfe79b83b0e2ee7aa41798fd25bdeb68eb85ca28460cd2376fc3
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.24.0
4
+
5
+ * Improve `--lsp` server to better support the commands used by VS Code
6
+
3
7
  ## 1.23.0
4
8
 
5
9
  * 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,8 @@ gem "minitest", "~> 5.0"
7
7
  gem "pry"
8
8
  gem "rake", "~> 13.0"
9
9
  gem "gimme"
10
+ gem "m"
11
+
10
12
 
11
13
  if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.5")
12
14
  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.0)
5
5
  language_server-protocol (~> 3.17.0.2)
6
6
  rubocop (= 1.44.1)
7
7
  rubocop-performance (= 1.15.2)
@@ -15,6 +15,9 @@ 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)
@@ -25,7 +28,7 @@ GEM
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,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,155 @@
1
+ module Standard
2
+ module Lsp
3
+ class Routes
4
+ def initialize(writer, logger, standardizer)
5
+ @writer = writer
6
+ @logger = logger
7
+ @standardizer = standardizer
8
+
9
+ @text_cache = {}
10
+ end
11
+
12
+ def self.handle(name, &block)
13
+ define_method("handle_#{name}", &block)
14
+ end
15
+
16
+ def for(name)
17
+ name = "handle_#{name}"
18
+ if respond_to?(name)
19
+ method(name)
20
+ end
21
+ end
22
+
23
+ handle "initialize" do |request|
24
+ @writer.write(id: request[:id], result: Proto::Interface::InitializeResult.new(
25
+ capabilities: Proto::Interface::ServerCapabilities.new(
26
+ document_formatting_provider: true,
27
+ diagnostic_provider: true,
28
+ text_document_sync: Proto::Interface::TextDocumentSyncOptions.new(
29
+ change: Proto::Constant::TextDocumentSyncKind::FULL
30
+ )
31
+ )
32
+ ))
33
+ end
34
+
35
+ handle "initialized" do |request|
36
+ @logger.puts "Standard Ruby v#{Standard::VERSION} LSP server initialized, pid #{Process.pid}"
37
+ end
38
+
39
+ handle "shutdown" do |request|
40
+ @logger.puts "Client asked to shutdown Standard LSP server. Exiting..."
41
+ at_exit {
42
+ @writer.write(id: request[:id], result: nil)
43
+ }
44
+ exit 0
45
+ end
46
+
47
+ handle "textDocument/diagnostic" do |request|
48
+ doc = request[:params][:textDocument]
49
+ result = diagnostic(doc[:uri], doc[:text])
50
+ @writer.write(result)
51
+ end
52
+
53
+ handle "textDocument/didChange" do |request|
54
+ params = request[:params]
55
+ result = diagnostic(params[:textDocument][:uri], params[:contentChanges][0][:text])
56
+ @writer.write(result)
57
+ end
58
+
59
+ handle "textDocument/didOpen" do |request|
60
+ doc = request[:params][:textDocument]
61
+ result = diagnostic(doc[:uri], doc[:text])
62
+ @writer.write(result)
63
+ end
64
+
65
+ handle "textDocument/didClose" do |request|
66
+ @text_cache.delete(request.dig(:params, :textDocument, :uri))
67
+ end
68
+
69
+ handle "textDocument/formatting" do |request|
70
+ uri = request[:params][:textDocument][:uri]
71
+ @writer.write({id: request[:id], result: format_file(uri)})
72
+ end
73
+
74
+ handle "textDocument/didSave" do |_request|
75
+ # No-op
76
+ end
77
+
78
+ handle "$/cancelRequest" do |_request|
79
+ # No-op
80
+ end
81
+
82
+ handle "$/setTrace" do |_request|
83
+ # No-op
84
+ end
85
+
86
+ private
87
+
88
+ def format_file(file_uri)
89
+ text = @text_cache[file_uri]
90
+ if text.nil?
91
+ @logger.puts "Format request arrived before text synchonized; skipping: `#{file_uri}'"
92
+ []
93
+ else
94
+ new_text = @standardizer.format(text)
95
+ if new_text == text
96
+ []
97
+ else
98
+ [{
99
+ newText: new_text,
100
+ range: {
101
+ start: {line: 0, character: 0},
102
+ end: {line: text.count("\n") + 1, character: 0}
103
+ }
104
+ }]
105
+ end
106
+ end
107
+ end
108
+
109
+ def diagnostic(file_uri, text)
110
+ @text_cache[file_uri] = text
111
+ offenses = @standardizer.offenses(text)
112
+
113
+ lsp_diagnostics = offenses.map { |o|
114
+ code = o[:cop_name]
115
+
116
+ msg = o[:message].delete_prefix(code)
117
+ loc = o[:location]
118
+
119
+ severity = case o[:severity]
120
+ when "error", "fatal"
121
+ SEV::ERROR
122
+ when "warning"
123
+ SEV::WARNING
124
+ when "convention"
125
+ SEV::INFORMATION
126
+ when "refactor", "info"
127
+ SEV::HINT
128
+ else # the above cases fully cover what RuboCop sends at this time
129
+ logger.puts "Unknown severity: #{severity.inspect}"
130
+ SEV::HINT
131
+ end
132
+
133
+ {
134
+ code: code,
135
+ message: msg,
136
+ range: {
137
+ start: {character: loc[:start_column] - 1, line: loc[:start_line] - 1},
138
+ end: {character: loc[:last_column] - 1, line: loc[:last_line] - 1}
139
+ },
140
+ severity: severity,
141
+ source: "standard"
142
+ }
143
+ }
144
+
145
+ {
146
+ method: "textDocument/publishDiagnostics",
147
+ params: {
148
+ uri: file_uri,
149
+ diagnostics: lsp_diagnostics
150
+ }
151
+ }
152
+ end
153
+ end
154
+ end
155
+ end
@@ -1,144 +1,43 @@
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|
69
26
  method = request[:method]
70
- if (subscriber = subscribers[method])
71
- subscriber.call(request)
27
+ if (route = @routes.for(method))
28
+ route.call(request)
72
29
  else
73
- logger.puts "unknown method: #{method}"
30
+ @writer.write({id: request[:id], error: Proto::Interface::ResponseError.new(
31
+ code: Proto::Constant::ErrorCodes::METHOD_NOT_FOUND,
32
+ message: "Unsupported Method: #{method}"
33
+ )})
34
+ @logger.puts "Unsupported Method: #{method}"
74
35
  end
75
36
  rescue => e
76
- logger.puts "error #{e.class} #{e.message[0..100]}"
77
- logger.puts e.backtrace.inspect
37
+ @logger.puts "Error #{e.class} #{e.message[0..100]}"
38
+ @logger.puts e.backtrace.inspect
78
39
  end
79
40
  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
41
  end
143
42
  end
144
43
  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.0")
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.0
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-09 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,8 @@ 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/logger.rb
106
+ - lib/standard/lsp/routes.rb
105
107
  - lib/standard/lsp/server.rb
106
108
  - lib/standard/lsp/standardizer.rb
107
109
  - lib/standard/merges_settings.rb
@@ -120,7 +122,7 @@ files:
120
122
  homepage: https://github.com/testdouble/standard
121
123
  licenses: []
122
124
  metadata: {}
123
- post_install_message:
125
+ post_install_message:
124
126
  rdoc_options: []
125
127
  require_paths:
126
128
  - lib
@@ -135,8 +137,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
137
  - !ruby/object:Gem::Version
136
138
  version: '0'
137
139
  requirements: []
138
- rubygems_version: 3.1.6
139
- signing_key:
140
+ rubygems_version: 3.3.26
141
+ signing_key:
140
142
  specification_version: 4
141
143
  summary: Ruby Style Guide, with linter & automatic code fixer
142
144
  test_files: []