standard 1.23.0 → 1.24.0

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