lsp_router 0.1.4 → 0.2.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: a4434480350b472e4784e0bc3dcd003f5863eeb5ee25accbcc5491d07ecdac39
4
- data.tar.gz: ba46303f99aa22018ade578cf1534ccfb7149b356b43ca262ae65c5cb729eb64
3
+ metadata.gz: 8723d008f57ebcb4e223047e71c87a08c3584986f69400e251992e9c0a9e28b0
4
+ data.tar.gz: 881cb222d1b8d5008d761468eeaab85c7cca49d1a8fc522d16b5e690a6218e4b
5
5
  SHA512:
6
- metadata.gz: 4e5716f9fab94ec450991faf87af92d81544341df78a795c9506a94b7feee39add469211144762b7514f5d46b76128e4c68b21d8ef12f300dbae9c28f3bdd7e4
7
- data.tar.gz: 7795648666367d4bada69bfa336c7cdbcf41f3f4039f17e819c0c79a61acbfbd2a3381c44f1b2e222f889cb9df81b32e61bf83b0e34fbfb51862b8009798c069
6
+ metadata.gz: d4f91f2d6b1d9c495d90304b27c34e840345e7964256b0718b0320d4cc78ad950ea7785125a700ed3d74b6aef21d4ec57549e15d25a0628fdd1a0a2263bc2fb5
7
+ data.tar.gz: 93cb11230758e15910f9d81e03aa69e561fcaf0babee18d49808099a5fb3b3c5dbf8a2b4062c3ec02feed865ab2a04582ca4e6235173f0fe792461649d213d4c
data/.rubocop.yml CHANGED
@@ -1,5 +1,7 @@
1
1
  AllCops:
2
2
  NewCops: enable
3
+ TargetRubyVersion: 3.1
4
+ SuggestExtensions: false
3
5
 
4
6
  Bundler/OrderedGems:
5
7
  Enabled: false
@@ -10,9 +12,15 @@ Gemspec/DevelopmentDependencies:
10
12
  Layout/EmptyLineAfterGuardClause:
11
13
  Enabled: false
12
14
 
15
+ Layout/EndAlignment:
16
+ EnforcedStyleAlignWith: start_of_line
17
+
13
18
  Layout/ExtraSpacing:
14
19
  AllowBeforeTrailingComments: true
15
20
 
21
+ Layout/LeadingCommentSpace:
22
+ AllowRBSInlineAnnotation: true
23
+
16
24
  Layout/LineLength:
17
25
  Max: 130
18
26
 
@@ -45,11 +53,22 @@ Layout/SpaceInsideHashLiteralBraces:
45
53
  Layout/SpaceInsidePercentLiteralDelimiters:
46
54
  Enabled: false
47
55
 
56
+ Lint/AmbiguousBlockAssociation:
57
+ AllowedPatterns: ['Module.new']
58
+
59
+ Lint/HashCompareByIdentity:
60
+ Enabled: false
61
+
48
62
  Lint/SuppressedException:
49
63
  AllowComments: true
50
64
 
51
65
  Metrics/AbcSize:
52
- Max: 60
66
+ Enabled: false
67
+
68
+ Metrics/BlockLength:
69
+ Max: 50
70
+ Exclude:
71
+ - '**/*_spec.rb'
53
72
 
54
73
  Metrics/BlockNesting:
55
74
  Enabled: false
@@ -69,6 +88,9 @@ Naming/AccessorMethodName:
69
88
  Naming/BlockForwarding:
70
89
  Enabled: false
71
90
 
91
+ Naming/HeredocDelimiterNaming:
92
+ Enabled: false
93
+
72
94
  Naming/MethodParameterName:
73
95
  Enabled: false
74
96
 
@@ -78,33 +100,117 @@ Metrics/ParameterLists:
78
100
  Metrics/PerceivedComplexity:
79
101
  Max: 100
80
102
 
103
+ Style/AccessModifierDeclarations:
104
+ Enabled: false
105
+
106
+ Style/AccessorGrouping:
107
+ Enabled: false
108
+
109
+ Style/Alias:
110
+ Enabled: false
111
+
81
112
  Style/AndOr:
82
113
  Enabled: false
83
114
 
115
+ Style/ArgumentsForwarding:
116
+ Enabled: false
117
+
118
+ Style/ArrayCoercion:
119
+ Enabled: false
120
+
121
+ Style/ArrayFirstLast:
122
+ Enabled: false
123
+
124
+ Style/ArrayIntersect:
125
+ Enabled: false
126
+
127
+ Style/ArrayJoin:
128
+ Enabled: false
129
+
130
+ Style/AsciiComments:
131
+ Enabled: false
132
+
133
+ Style/Attr:
134
+ Enabled: true
135
+
136
+ Style/AutoResourceCleanup:
137
+ Enabled: false
138
+
139
+ Style/BarePercentLiterals:
140
+ Enabled: false
141
+
142
+ Style/BeginBlock:
143
+ Enabled: false
144
+
145
+ Style/BisectedAttrAccessor:
146
+ Enabled: true
147
+
148
+ Style/BlockComments:
149
+ Enabled: false
150
+
84
151
  Style/BlockDelimiters:
85
152
  Enabled: false
86
153
 
154
+ Style/CaseEquality:
155
+ Enabled: false
156
+
87
157
  Style/CaseLikeIf:
88
158
  Enabled: false
89
159
 
160
+ Style/CharacterLiteral:
161
+ Enabled: false
162
+
90
163
  Style/ClassAndModuleChildren:
91
164
  Enabled: false
92
165
 
93
166
  Style/ClassCheck:
94
167
  Enabled: false
95
168
 
169
+ Style/ClassEqualityComparison:
170
+ Enabled: false
171
+
96
172
  Style/ClassMethods:
97
173
  Enabled: false
98
174
 
175
+ Style/ClassMethodsDefinitions:
176
+ Enabled: false
177
+
178
+ Style/ClassVars:
179
+ Enabled: true
180
+
181
+ Style/CollectionCompact:
182
+ Enabled: false
183
+
184
+ Style/CollectionMethods:
185
+ Enabled: false
186
+
187
+ Style/ColonMethodCall:
188
+ Enabled: true
189
+
190
+ Style/ColonMethodDefinition:
191
+ Enabled: true
192
+
99
193
  Style/CommentedKeyword:
100
194
  Enabled: false
101
195
 
196
+ Style/ConditionalAssignment:
197
+ Enabled: false
198
+
199
+ Style/DocumentDynamicEvalDefinition:
200
+ Enabled: false
201
+
202
+ Style/EmptyElse:
203
+ EnforcedStyle: empty
204
+
102
205
  Style/FormatString:
103
206
  Enabled: false
104
207
 
105
208
  Style/FrozenStringLiteralComment:
106
209
  Enabled: false
107
210
 
211
+ Style/GlobalVars:
212
+ Enabled: false
213
+
108
214
  Style/GuardClause:
109
215
  Enabled: false
110
216
 
@@ -120,6 +226,9 @@ Style/Lambda:
120
226
  Style/MethodCallWithoutArgsParentheses:
121
227
  Enabled: false
122
228
 
229
+ Style/MultipleComparison:
230
+ Enabled: false
231
+
123
232
  Style/MutableConstant:
124
233
  Enabled: false
125
234
 
@@ -153,9 +262,15 @@ Style/PreferredHashMethods:
153
262
  Style/RedundantReturn:
154
263
  Enabled: false
155
264
 
265
+ Style/RedundantRegexpArgument:
266
+ Enabled: false
267
+
156
268
  Style/RedundantSelf:
157
269
  Enabled: false
158
270
 
271
+ Style/RegexpLiteral:
272
+ Enabled: false
273
+
159
274
  Style/RescueModifier:
160
275
  Enabled: false
161
276
 
@@ -174,6 +289,15 @@ Style/StringConcatenation:
174
289
  Style/StringLiterals:
175
290
  Enabled: false
176
291
 
292
+ Style/StringLiteralsInInterpolation:
293
+ Enabled: false
294
+
295
+ Style/SuperArguments:
296
+ Enabled: false
297
+
298
+ Style/SuperWithArgsParentheses:
299
+ Enabled: false
300
+
177
301
  Style/TrailingCommaInArrayLiteral:
178
302
  EnforcedStyleForMultiline: consistent_comma
179
303
 
@@ -183,5 +307,8 @@ Style/TrailingCommaInHashLiteral:
183
307
  Style/VariableInterpolation:
184
308
  Enabled: false
185
309
 
310
+ Style/WhileUntilModifier:
311
+ Enabled: false
312
+
186
313
  Style/WordArray:
187
314
  Enabled: false
data/README.md CHANGED
@@ -13,7 +13,7 @@ gem install lsp_router
13
13
  次のような config ファイルを作成して、`lsp_router config-file` のように実行する。
14
14
 
15
15
  ```ruby
16
- logfile '/tmp/lsp_router'
16
+ logfile '/tmp/lsp_router.log'
17
17
  loglevel :info
18
18
 
19
19
  server :rubocop do
@@ -21,13 +21,13 @@ server :rubocop do
21
21
  mode :stdio
22
22
  end
23
23
 
24
- server :solargraph do
25
- command 'solargraph stdio'
24
+ server :ruby_lsp do
25
+ command 'ruby-lsp'
26
26
  mode :stdio
27
27
  end
28
28
  ```
29
29
 
30
- この例では、`rubocop --lsp` と `solargraph stdio` を起動して、クライアントからの処理を振り分ける。
30
+ この例では、`rubocop --lsp` と `ruby-lsp` を起動して、クライアントからの処理を振り分ける。
31
31
  最初に各サーバーの capabilities を確認して、各サーバーにどの機能があるかを確認し、クライアントからの REQUEST は対応しているサーバーに渡す。複数のサーバーが同じ機能を持っていれば上に書いたサーバーが優先される。NOTIFICATION は全サーバーに渡す。
32
32
 
33
33
  ## Example
@@ -0,0 +1,132 @@
1
+ class LspRouter
2
+ CAPABILITY_REQUEST = {
3
+ textDocumentSync: [
4
+ 'textDocument/willSaveWaitUntil',
5
+ ],
6
+ notebookDocumentSync: [
7
+ # Notification only
8
+ ],
9
+ completionProvider: [
10
+ 'textDocument/completion',
11
+ 'completionItem/resolve',
12
+ ],
13
+ hoverProvider: [
14
+ 'textDocument/hover',
15
+ ],
16
+ signatureHelpProvider: [
17
+ 'textDocument/signatureHelp',
18
+ ],
19
+ declarationProvider: [
20
+ 'textDocument/declaration',
21
+ ],
22
+ definitionProvider: [
23
+ 'textDocument/definition',
24
+ ],
25
+ typeDefinitionProvider: [
26
+ 'textDocument/typeDefinition',
27
+ ],
28
+ implementationProvider: [
29
+ 'textDocument/implementation',
30
+ ],
31
+ referencesProvider: [
32
+ 'textDocument/references',
33
+ ],
34
+ documentHighlightProvider: [
35
+ 'textDocument/documentHighlight',
36
+ ],
37
+ documentSymbolProvider: [
38
+ 'textDocument/documentSymbol',
39
+ ],
40
+ codeActionProvider: [
41
+ 'textDocument/codeAction',
42
+ 'codeAction/resolve',
43
+ ],
44
+ codeLensProvider: [
45
+ 'textDocument/codeLens',
46
+ 'codeLens/resolve',
47
+ 'workspace/codeLens/refresh',
48
+ ],
49
+ documentLinkProvider: [
50
+ 'textDocument/documentLink',
51
+ 'documentLink/resolve',
52
+ ],
53
+ colorProvider: [
54
+ 'textDocument/documentColor',
55
+ 'textDocument/colorPresentation',
56
+ ],
57
+ documentFormattingProvider: [
58
+ 'textDocument/formatting',
59
+ ],
60
+ documentRangeFormattingProvider: [
61
+ 'textDocument/rangeFormatting',
62
+ ],
63
+ documentOnTypeFormattingProvider: [
64
+ 'textDocument/onTypeFormatting',
65
+ ],
66
+ renameProvider: [
67
+ 'textDocument/rename',
68
+ 'textDocument/prepareRename',
69
+ ],
70
+ foldingRangeProvider: [
71
+ 'textDocument/foldingRange',
72
+ ],
73
+ executeCommandProvider: [
74
+ 'textDocument/selectionRange',
75
+ 'workspace/executeCommand',
76
+ ],
77
+ selectionRangeProvider: [
78
+ ],
79
+ linkedEditingRangeProvider: [
80
+ 'textDocument/linkedEditingRange',
81
+ ],
82
+ callHierarchyProvider: [
83
+ 'textDocument/prepareCallHierarchy',
84
+ 'callHierarchy/incomingCalls',
85
+ 'callHierarchy/outgoingCalls',
86
+
87
+ ],
88
+ semanticTokensProvider: [
89
+ 'textDocument/semanticTokens',
90
+ 'textDocument/semanticTokens/full',
91
+ 'textDocument/semanticTokens/full/delta',
92
+ 'textDocument/semanticTokens/range',
93
+ 'workspace/semanticTokens/refresh',
94
+ ],
95
+ monikerProvider: [
96
+ 'textDocument/moniker',
97
+ ],
98
+ typeHierarchyProvider: [
99
+ 'textDocument/prepareTypeHierarchy',
100
+ 'typeHierarchy/supertypes',
101
+ 'typeHierarchy/subtypes',
102
+ ],
103
+ inlineValueProvider: [
104
+ 'textDocument/inlineValue',
105
+ 'workspace/inlineValue/refresh',
106
+ ],
107
+ inlayHintProvider: [
108
+ 'textDocument/inlayHint',
109
+ 'inlayHint/resolve',
110
+ 'workspace/inlayHint/refresh',
111
+ ],
112
+ diagnosticProvider: [
113
+ 'textDocument/diagnostic',
114
+ 'workspace/diagnostic',
115
+ 'workspace/diagnostic/refresh',
116
+ ],
117
+ workspaceSymbolProvider: [
118
+ 'workspace/symbol',
119
+ 'workspaceSymbol/resolve',
120
+ ],
121
+ workspace: {
122
+ workspaceFolders: [
123
+ 'workspace/workspaceFolders',
124
+ ],
125
+ fileOperations: [
126
+ 'workspace/willCreateFiles',
127
+ 'workspace/willRenameFiles',
128
+ 'workspace/willDeleteFiles',
129
+ ],
130
+ },
131
+ }
132
+ end
@@ -6,10 +6,11 @@ class LspRouter
6
6
  include Singleton
7
7
 
8
8
  attr_reader :servers
9
- attr_accessor :logfile, :loglevel
9
+ attr_accessor :logfile, :loglevel, :encoding
10
10
 
11
11
  def initialize
12
12
  @servers = []
13
+ @encoding = 'utf-16'
13
14
  end
14
15
 
15
16
  # @param name [String]
@@ -34,6 +35,11 @@ class LspRouter
34
35
  config.loglevel = level
35
36
  end
36
37
 
38
+ # @return [String]
39
+ def position_encoding(enc)
40
+ config.encoding = enc
41
+ end
42
+
37
43
  # @return [LspRouter::Config]
38
44
  def config
39
45
  Config.instance
@@ -1,12 +1,10 @@
1
- require 'open3'
2
-
3
1
  class LspRouter
4
2
  # server side
5
3
  class ServerSide
6
- # @return String
4
+ # @return [String]
7
5
  attr_reader :name
8
6
  # @return [Hash]
9
- attr_reader :capabilities
7
+ attr_reader :requests
10
8
 
11
9
  # @param server [LspRouter::Config::Server]
12
10
  # @param logger [Logger]
@@ -14,25 +12,42 @@ class LspRouter
14
12
  @logger = logger
15
13
  @name = server.attr[:name]
16
14
  @command = server.attr[:command]
17
- @stdin, @stdout, @stderr = Open3.popen3(@command)
18
- @capabilities = {}
15
+ r, @stdin = IO.pipe
16
+ @stdout, w = IO.pipe
17
+ spawn(@command, in: r, out: w, err: $stderr)
18
+ @requests = {}
19
19
  @terminated = false
20
20
  end
21
21
 
22
22
  # @param req [Hash]
23
+ # @return [Hash]
23
24
  def init(req)
24
25
  write(req)
25
26
  while (data = read)
26
27
  capa = data.dig('result', 'capabilities')
27
28
  next unless capa
28
- capa.keys.grep(/Provider/).each do |key|
29
- @capabilities[key.sub(/Provider\z/, '')] = true
30
- end
29
+ @requests = capa_to_req(capa, CAPABILITY_REQUEST)
31
30
  break
32
31
  end
32
+ @logger.debug "requests: #{name}: #{@requests.inspect}"
33
33
  data
34
34
  end
35
35
 
36
+ # @param capa [Hash]
37
+ # @param req [Hash, Array]
38
+ # @return [Array]
39
+ def capa_to_req(capa, req)
40
+ ret = []
41
+ capa.each_key do |key|
42
+ if req[key.intern].is_a? Array
43
+ ret.concat req[key.intern]
44
+ elsif req[key.intern].is_a? Hash
45
+ ret.concat capa_to_req(capa[key], req[key.intern])
46
+ end
47
+ end
48
+ ret
49
+ end
50
+
36
51
  # @param data [Hash]
37
52
  def write(data)
38
53
  return if @terminated
@@ -1,3 +1,3 @@
1
1
  class LspRouter
2
- VERSION = '0.1.4'
2
+ VERSION = '0.2.0'
3
3
  end
data/lib/lsp_router.rb CHANGED
@@ -2,6 +2,7 @@ require_relative 'lsp_router/version'
2
2
  require_relative 'lsp_router/config'
3
3
  require_relative 'lsp_router/server_side'
4
4
  require_relative 'lsp_router/client_side'
5
+ require_relative 'lsp_router/capability_request'
5
6
 
6
7
  require 'socket'
7
8
  require 'json'
@@ -45,7 +46,7 @@ class LspRouter
45
46
  @servers = @config.servers.map{LspRouter::ServerSide.new(_1, logger: @logger)}
46
47
  @primary = @servers.first
47
48
  @server_map = @servers.map.to_h{[_1.name.to_s, _1]}
48
- @capa_server = {}
49
+ @req_server = {}
49
50
 
50
51
  initial_packet
51
52
  threads = server_loop
@@ -55,6 +56,8 @@ class LspRouter
55
56
 
56
57
  def initial_packet
57
58
  req = @client.read
59
+ req['params']['capabilities']['general'] ||= {}
60
+ req['params']['capabilities']['general']['positionEncodings'] = @config.encoding
58
61
  res = nil
59
62
  @servers.each do |server|
60
63
  data = server.init(req)
@@ -63,10 +66,11 @@ class LspRouter
63
66
  else
64
67
  res = data
65
68
  end
66
- server.capabilities.each_key do |key|
67
- @capa_server[key] ||= server
69
+ server.requests.each do |req|
70
+ @req_server[req] ||= server
68
71
  end
69
72
  end
73
+ @logger.debug "req_server: #{@req_server.transform_values(&:name).inspect}"
70
74
  @client.write(res)
71
75
  end
72
76
 
@@ -82,9 +86,8 @@ class LspRouter
82
86
  next
83
87
  end
84
88
  if data['id'] # request or response
85
- method = data['method']&.split('/')&.last
86
89
  if data['method'] # request
87
- server = @capa_server[method] || @primary
90
+ server = @req_server[data['method']] || @primary
88
91
  else # response
89
92
  server_name, id = JSON.parse(data['id'])
90
93
  data['id'] = id
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lsp_router
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - TOMITA Masahiro
@@ -24,6 +24,7 @@ files:
24
24
  - config/example.conf
25
25
  - exe/lsp_router
26
26
  - lib/lsp_router.rb
27
+ - lib/lsp_router/capability_request.rb
27
28
  - lib/lsp_router/cli.rb
28
29
  - lib/lsp_router/client_side.rb
29
30
  - lib/lsp_router/config.rb