solargraph 0.56.0 → 0.58.2

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.
Files changed (191) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +2 -0
  3. data/.github/workflows/linting.yml +127 -0
  4. data/.github/workflows/plugins.yml +183 -7
  5. data/.github/workflows/rspec.yml +55 -5
  6. data/.github/workflows/typecheck.yml +6 -3
  7. data/.gitignore +6 -0
  8. data/.overcommit.yml +72 -0
  9. data/.rspec +1 -0
  10. data/.rubocop.yml +66 -0
  11. data/.rubocop_todo.yml +1279 -0
  12. data/.yardopts +1 -0
  13. data/CHANGELOG.md +92 -1
  14. data/README.md +8 -4
  15. data/Rakefile +125 -13
  16. data/bin/solargraph +3 -0
  17. data/lib/solargraph/api_map/cache.rb +110 -109
  18. data/lib/solargraph/api_map/constants.rb +279 -0
  19. data/lib/solargraph/api_map/index.rb +193 -175
  20. data/lib/solargraph/api_map/source_to_yard.rb +97 -88
  21. data/lib/solargraph/api_map/store.rb +384 -266
  22. data/lib/solargraph/api_map.rb +945 -973
  23. data/lib/solargraph/bench.rb +1 -0
  24. data/lib/solargraph/complex_type/type_methods.rb +228 -222
  25. data/lib/solargraph/complex_type/unique_type.rb +482 -475
  26. data/lib/solargraph/complex_type.rb +444 -423
  27. data/lib/solargraph/convention/active_support_concern.rb +111 -0
  28. data/lib/solargraph/convention/base.rb +17 -0
  29. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -0
  30. data/lib/solargraph/convention/data_definition/data_definition_node.rb +91 -0
  31. data/lib/solargraph/convention/data_definition.rb +105 -0
  32. data/lib/solargraph/convention/gemspec.rb +3 -2
  33. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +61 -60
  34. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +102 -100
  35. data/lib/solargraph/convention/struct_definition.rb +164 -101
  36. data/lib/solargraph/convention.rb +32 -2
  37. data/lib/solargraph/diagnostics/require_not_found.rb +53 -53
  38. data/lib/solargraph/diagnostics/rubocop.rb +118 -113
  39. data/lib/solargraph/diagnostics/rubocop_helpers.rb +68 -66
  40. data/lib/solargraph/diagnostics/type_check.rb +55 -55
  41. data/lib/solargraph/doc_map.rb +439 -405
  42. data/lib/solargraph/environ.rb +9 -2
  43. data/lib/solargraph/equality.rb +34 -33
  44. data/lib/solargraph/gem_pins.rb +98 -88
  45. data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
  46. data/lib/solargraph/language_server/host/dispatch.rb +130 -128
  47. data/lib/solargraph/language_server/host/message_worker.rb +112 -109
  48. data/lib/solargraph/language_server/host/sources.rb +99 -99
  49. data/lib/solargraph/language_server/host.rb +878 -871
  50. data/lib/solargraph/language_server/message/base.rb +2 -1
  51. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +114 -114
  52. data/lib/solargraph/language_server/message/extended/document.rb +23 -23
  53. data/lib/solargraph/language_server/message/text_document/completion.rb +56 -56
  54. data/lib/solargraph/language_server/message/text_document/definition.rb +40 -38
  55. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +26 -26
  56. data/lib/solargraph/language_server/message/text_document/formatting.rb +148 -131
  57. data/lib/solargraph/language_server/message/text_document/hover.rb +58 -58
  58. data/lib/solargraph/language_server/message/text_document/signature_help.rb +24 -24
  59. data/lib/solargraph/language_server/message/text_document/type_definition.rb +25 -24
  60. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +2 -0
  61. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +23 -23
  62. data/lib/solargraph/language_server/progress.rb +8 -0
  63. data/lib/solargraph/language_server/request.rb +4 -1
  64. data/lib/solargraph/library.rb +683 -666
  65. data/lib/solargraph/location.rb +82 -79
  66. data/lib/solargraph/logging.rb +37 -28
  67. data/lib/solargraph/page.rb +3 -0
  68. data/lib/solargraph/parser/comment_ripper.rb +69 -62
  69. data/lib/solargraph/parser/flow_sensitive_typing.rb +255 -227
  70. data/lib/solargraph/parser/node_processor/base.rb +92 -87
  71. data/lib/solargraph/parser/node_processor.rb +62 -46
  72. data/lib/solargraph/parser/parser_gem/class_methods.rb +149 -159
  73. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -0
  74. data/lib/solargraph/parser/parser_gem/node_chainer.rb +166 -164
  75. data/lib/solargraph/parser/parser_gem/node_methods.rb +486 -497
  76. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +22 -21
  77. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +59 -59
  78. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +15 -15
  79. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +46 -45
  80. data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +1 -21
  81. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +53 -53
  82. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +23 -21
  83. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +40 -40
  84. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +29 -29
  85. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +59 -53
  86. data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +0 -22
  87. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +98 -41
  88. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +17 -16
  89. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +38 -37
  90. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +52 -43
  91. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +291 -271
  92. data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +1 -0
  93. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +29 -29
  94. data/lib/solargraph/parser/parser_gem/node_processors.rb +70 -66
  95. data/lib/solargraph/parser/region.rb +69 -66
  96. data/lib/solargraph/parser/snippet.rb +17 -15
  97. data/lib/solargraph/pin/base.rb +729 -651
  98. data/lib/solargraph/pin/base_variable.rb +126 -125
  99. data/lib/solargraph/pin/block.rb +104 -103
  100. data/lib/solargraph/pin/breakable.rb +9 -9
  101. data/lib/solargraph/pin/callable.rb +231 -218
  102. data/lib/solargraph/pin/closure.rb +72 -74
  103. data/lib/solargraph/pin/common.rb +79 -75
  104. data/lib/solargraph/pin/constant.rb +2 -0
  105. data/lib/solargraph/pin/conversions.rb +123 -123
  106. data/lib/solargraph/pin/delegated_method.rb +120 -120
  107. data/lib/solargraph/pin/documenting.rb +114 -114
  108. data/lib/solargraph/pin/instance_variable.rb +34 -34
  109. data/lib/solargraph/pin/keyword.rb +20 -20
  110. data/lib/solargraph/pin/local_variable.rb +75 -76
  111. data/lib/solargraph/pin/method.rb +672 -651
  112. data/lib/solargraph/pin/method_alias.rb +34 -31
  113. data/lib/solargraph/pin/namespace.rb +115 -115
  114. data/lib/solargraph/pin/parameter.rb +275 -261
  115. data/lib/solargraph/pin/proxy_type.rb +39 -35
  116. data/lib/solargraph/pin/reference/override.rb +47 -33
  117. data/lib/solargraph/pin/reference/superclass.rb +15 -10
  118. data/lib/solargraph/pin/reference.rb +39 -22
  119. data/lib/solargraph/pin/search.rb +61 -56
  120. data/lib/solargraph/pin/signature.rb +61 -59
  121. data/lib/solargraph/pin/symbol.rb +53 -48
  122. data/lib/solargraph/pin/until.rb +18 -18
  123. data/lib/solargraph/pin/while.rb +18 -18
  124. data/lib/solargraph/pin.rb +44 -44
  125. data/lib/solargraph/pin_cache.rb +245 -185
  126. data/lib/solargraph/position.rb +132 -116
  127. data/lib/solargraph/range.rb +112 -107
  128. data/lib/solargraph/rbs_map/conversions.rb +823 -773
  129. data/lib/solargraph/rbs_map/core_fills.rb +18 -0
  130. data/lib/solargraph/rbs_map/core_map.rb +58 -51
  131. data/lib/solargraph/rbs_map/stdlib_map.rb +43 -43
  132. data/lib/solargraph/rbs_map.rb +163 -150
  133. data/lib/solargraph/shell.rb +352 -268
  134. data/lib/solargraph/source/chain/call.rb +337 -333
  135. data/lib/solargraph/source/chain/constant.rb +26 -89
  136. data/lib/solargraph/source/chain/hash.rb +34 -34
  137. data/lib/solargraph/source/chain/if.rb +28 -28
  138. data/lib/solargraph/source/chain/instance_variable.rb +13 -13
  139. data/lib/solargraph/source/chain/link.rb +11 -2
  140. data/lib/solargraph/source/chain/literal.rb +48 -48
  141. data/lib/solargraph/source/chain/or.rb +23 -23
  142. data/lib/solargraph/source/chain.rb +291 -282
  143. data/lib/solargraph/source/change.rb +82 -82
  144. data/lib/solargraph/source/cursor.rb +166 -167
  145. data/lib/solargraph/source/encoding_fixes.rb +23 -23
  146. data/lib/solargraph/source/source_chainer.rb +194 -194
  147. data/lib/solargraph/source/updater.rb +55 -55
  148. data/lib/solargraph/source.rb +498 -495
  149. data/lib/solargraph/source_map/clip.rb +226 -234
  150. data/lib/solargraph/source_map/data.rb +34 -30
  151. data/lib/solargraph/source_map/mapper.rb +259 -259
  152. data/lib/solargraph/source_map.rb +212 -200
  153. data/lib/solargraph/type_checker/checks.rb +124 -124
  154. data/lib/solargraph/type_checker/param_def.rb +37 -35
  155. data/lib/solargraph/type_checker/problem.rb +32 -32
  156. data/lib/solargraph/type_checker/rules.rb +84 -62
  157. data/lib/solargraph/type_checker.rb +814 -699
  158. data/lib/solargraph/version.rb +5 -5
  159. data/lib/solargraph/workspace/config.rb +255 -239
  160. data/lib/solargraph/workspace/require_paths.rb +97 -0
  161. data/lib/solargraph/workspace.rb +220 -249
  162. data/lib/solargraph/yard_map/helpers.rb +44 -16
  163. data/lib/solargraph/yard_map/mapper/to_constant.rb +5 -5
  164. data/lib/solargraph/yard_map/mapper/to_method.rb +130 -134
  165. data/lib/solargraph/yard_map/mapper/to_namespace.rb +31 -30
  166. data/lib/solargraph/yard_map/mapper.rb +79 -79
  167. data/lib/solargraph/yard_map/to_method.rb +89 -88
  168. data/lib/solargraph/yardoc.rb +87 -49
  169. data/lib/solargraph.rb +105 -90
  170. data/rbs/fills/bundler/0/bundler.rbs +4271 -0
  171. data/rbs/fills/open3/0/open3.rbs +172 -0
  172. data/rbs/fills/rubygems/0/basic_specification.rbs +326 -0
  173. data/rbs/fills/rubygems/0/errors.rbs +364 -0
  174. data/rbs/fills/rubygems/0/spec_fetcher.rbs +107 -0
  175. data/rbs/fills/rubygems/0/specification.rbs +1753 -0
  176. data/rbs/fills/{tuple.rbs → tuple/tuple.rbs} +2 -3
  177. data/rbs/shims/ast/0/node.rbs +5 -0
  178. data/rbs/shims/ast/2.4/.rbs_meta.yaml +9 -0
  179. data/rbs/shims/ast/2.4/ast.rbs +73 -0
  180. data/rbs/shims/parser/3.2.0.1/builders/default.rbs +195 -0
  181. data/rbs/shims/parser/3.2.0.1/manifest.yaml +7 -0
  182. data/rbs/shims/parser/3.2.0.1/parser.rbs +201 -0
  183. data/rbs/shims/parser/3.2.0.1/polyfill.rbs +4 -0
  184. data/rbs/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
  185. data/rbs/shims/thor/1.2.0.1/manifest.yaml +7 -0
  186. data/rbs/shims/thor/1.2.0.1/thor.rbs +17 -0
  187. data/rbs_collection.yaml +4 -4
  188. data/solargraph.gemspec +26 -5
  189. metadata +187 -15
  190. data/lib/.rubocop.yml +0 -22
  191. data/lib/solargraph/parser/node_methods.rb +0 -97
@@ -1,128 +1,130 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- module LanguageServer
5
- class Host
6
- # Methods for associating sources with libraries via URIs.
7
- #
8
- module Dispatch
9
- # @abstract
10
- # @return [Host::Diagnoser]
11
- def diagnoser
12
- raise NotImplementedError, 'Host::Dispatch requires a diagnoser method'
13
- end
14
-
15
- # @return [Sources]
16
- def sources
17
- @sources ||= begin
18
- src = Sources.new
19
- src.add_observer self, :update_libraries
20
- src
21
- end
22
- end
23
-
24
- # @return [::Array<Library>]
25
- def libraries
26
- @libraries ||= []
27
- end
28
-
29
- # The Sources observer callback that merges a source into the host's
30
- # libraries when it gets updated.
31
- #
32
- # @param uri [String]
33
- # @return [void]
34
- def update_libraries uri
35
- src = sources.find(uri)
36
- using = libraries.select { |lib| lib.contain?(src.filename) }
37
- using.push library_for(uri) if using.empty?
38
- using.each { |lib| lib.merge src }
39
- diagnoser.schedule uri
40
- end
41
-
42
- # Find the best libary match for the given URI.
43
- #
44
- # @param uri [String]
45
- # @return [Library]
46
- def library_for uri
47
- result = explicit_library_for(uri) ||
48
- implicit_library_for(uri) ||
49
- generic_library_for(uri)
50
- # previous library for already call attach. avoid call twice
51
- # result.attach sources.find(uri) if sources.include?(uri)
52
- result
53
- end
54
-
55
- # Find an explicit library match for the given URI. An explicit match
56
- # means the libary's workspace includes the file.
57
- #
58
- # If a matching library is found, the source corresponding to the URI
59
- # gets attached to it.
60
- #
61
- # @raise [FileNotFoundError] if the source could not be attached.
62
- #
63
- # @param uri [String]
64
- # @return [Library, nil]
65
- def explicit_library_for uri
66
- filename = UriHelpers.uri_to_file(uri)
67
- libraries.each do |lib|
68
- if lib.contain?(filename)
69
- lib.attach sources.find(uri) if sources.include?(uri)
70
- return lib
71
- end
72
- end
73
- nil
74
- end
75
-
76
- # Find an implicit library match for the given URI. An implicit match
77
- # means the file is located inside the library's workspace directory,
78
- # regardless of whether the workspace is configured to include it.
79
- #
80
- # If a matching library is found, the source corresponding to the URI
81
- # gets attached to it.
82
- #
83
- # @raise [FileNotFoundError] if the source could not be attached.
84
- #
85
- # @param uri [String]
86
- # @return [Library, nil]
87
- def implicit_library_for uri
88
- filename = UriHelpers.uri_to_file(uri)
89
- libraries.each do |lib|
90
- if filename.start_with?(lib.workspace.directory)
91
- lib.attach sources.find(uri)
92
- return lib
93
- end
94
- end
95
- nil
96
- end
97
-
98
- def options
99
- @options ||= {}.freeze
100
- end
101
-
102
- # Get a generic library for the given URI and attach the corresponding
103
- # source.
104
- #
105
- # @raise [FileNotFoundError] if the source could not be attached.
106
- #
107
- # @param uri [String]
108
- # @return [Library]
109
- def generic_library_for uri
110
- generic_library.attach sources.find(uri)
111
- generic_library
112
- end
113
-
114
- # @return [Library]
115
- def generic_library
116
- @generic_library ||= Solargraph::Library.new(Solargraph::Workspace.new('', nil, options), nil)
117
- .tap { |lib| lib.add_observer self }
118
- end
119
-
120
- # @param library [Solargraph::Library]
121
- # @return [void]
122
- def update progress
123
- progress&.send(self)
124
- end
125
- end
126
- end
127
- end
128
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module LanguageServer
5
+ class Host
6
+ # Methods for associating sources with libraries via URIs.
7
+ #
8
+ module Dispatch
9
+ # @abstract
10
+ # @return [Host::Diagnoser]
11
+ def diagnoser
12
+ raise NotImplementedError, 'Host::Dispatch requires a diagnoser method'
13
+ end
14
+
15
+ # @return [Sources]
16
+ def sources
17
+ @sources ||= begin
18
+ src = Sources.new
19
+ src.add_observer self, :update_libraries
20
+ src
21
+ end
22
+ end
23
+
24
+ # @return [::Array<Library>]
25
+ def libraries
26
+ @libraries ||= []
27
+ end
28
+
29
+ # The Sources observer callback that merges a source into the host's
30
+ # libraries when it gets updated.
31
+ #
32
+ # @param uri [String]
33
+ # @return [void]
34
+ def update_libraries uri
35
+ src = sources.find(uri)
36
+ using = libraries.select { |lib| lib.contain?(src.filename) }
37
+ using.push library_for(uri) if using.empty?
38
+ using.each { |lib| lib.merge src }
39
+ diagnoser.schedule uri
40
+ end
41
+
42
+ # Find the best libary match for the given URI.
43
+ #
44
+ # @param uri [String]
45
+ # @return [Library]
46
+ def library_for uri
47
+ result = explicit_library_for(uri) ||
48
+ implicit_library_for(uri) ||
49
+ generic_library_for(uri)
50
+ # previous library for already call attach. avoid call twice
51
+ # result.attach sources.find(uri) if sources.include?(uri)
52
+ result
53
+ end
54
+
55
+ # Find an explicit library match for the given URI. An explicit match
56
+ # means the libary's workspace includes the file.
57
+ #
58
+ # If a matching library is found, the source corresponding to the URI
59
+ # gets attached to it.
60
+ #
61
+ # @raise [FileNotFoundError] if the source could not be attached.
62
+ #
63
+ # @param uri [String]
64
+ # @return [Library, nil]
65
+ def explicit_library_for uri
66
+ filename = UriHelpers.uri_to_file(uri)
67
+ libraries.each do |lib|
68
+ if lib.contain?(filename)
69
+ lib.attach sources.find(uri) if sources.include?(uri)
70
+ return lib
71
+ end
72
+ end
73
+ nil
74
+ end
75
+
76
+ # Find an implicit library match for the given URI. An implicit match
77
+ # means the file is located inside the library's workspace directory,
78
+ # regardless of whether the workspace is configured to include it.
79
+ #
80
+ # If a matching library is found, the source corresponding to the URI
81
+ # gets attached to it.
82
+ #
83
+ # @raise [FileNotFoundError] if the source could not be attached.
84
+ #
85
+ # @param uri [String]
86
+ # @return [Library, nil]
87
+ def implicit_library_for uri
88
+ filename = UriHelpers.uri_to_file(uri)
89
+ libraries.each do |lib|
90
+ if filename.start_with?(lib.workspace.directory)
91
+ lib.attach sources.find(uri)
92
+ return lib
93
+ end
94
+ end
95
+ nil
96
+ end
97
+
98
+ # @return [Hash{String => undefined}]
99
+ def options
100
+ @options ||= {}.freeze
101
+ end
102
+
103
+ # Get a generic library for the given URI and attach the corresponding
104
+ # source.
105
+ #
106
+ # @raise [FileNotFoundError] if the source could not be attached.
107
+ #
108
+ # @param uri [String]
109
+ # @return [Library]
110
+ def generic_library_for uri
111
+ generic_library.attach sources.find(uri)
112
+ generic_library
113
+ end
114
+
115
+ # @return [Library]
116
+ def generic_library
117
+ @generic_library ||= Solargraph::Library.new(Solargraph::Workspace.new('', nil, options), nil)
118
+ .tap { |lib| lib.add_observer self }
119
+ end
120
+
121
+ # @param library [Solargraph::Library]
122
+ # @param progress [Solargraph::LanguageServer::Progress, nil]
123
+ # @return [void]
124
+ def update progress
125
+ progress&.send(self)
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -1,109 +1,112 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- module LanguageServer
5
- class Host
6
- # A serial worker Thread to handle incoming messages.
7
- #
8
- class MessageWorker
9
- UPDATE_METHODS = [
10
- 'textDocument/didChange',
11
- 'textDocument/didClose',
12
- 'textDocument/didOpen',
13
- 'textDocument/didSave',
14
- 'workspace/didChangeConfiguration',
15
- 'workspace/didChangeWatchedFiles',
16
- 'workspace/didCreateFiles',
17
- 'workspace/didChangeWorkspaceFolders',
18
- 'workspace/didDeleteFiles',
19
- 'workspace/didRenameFiles'
20
- ].freeze
21
-
22
- # @param host [Host]
23
- def initialize(host)
24
- @host = host
25
- @mutex = Mutex.new
26
- @resource = ConditionVariable.new
27
- @stopped = true
28
- end
29
-
30
- # pending handle messages
31
- # @return [Array<Hash>]
32
- def messages
33
- @messages ||= []
34
- end
35
-
36
- def stopped?
37
- @stopped
38
- end
39
-
40
- # @return [void]
41
- def stop
42
- @stopped = true
43
- end
44
-
45
- # @param message [Hash] The message to handle. Will be forwarded to Host#receive
46
- # @return [void]
47
- def queue(message)
48
- @mutex.synchronize do
49
- messages.push(message)
50
- @resource.signal
51
- end
52
- end
53
-
54
- # @return [void]
55
- def start
56
- return unless @stopped
57
- @stopped = false
58
- Thread.new do
59
- tick until stopped?
60
- end
61
- end
62
-
63
- # @return [void]
64
- def tick
65
- message = @mutex.synchronize do
66
- @resource.wait(@mutex) if messages.empty?
67
- next_message
68
- end
69
- handler = @host.receive(message)
70
- handler&.send_response
71
- end
72
-
73
- private
74
-
75
- def next_message
76
- cancel_message || next_priority
77
- end
78
-
79
- def cancel_message
80
- # Handle cancellations first
81
- idx = messages.find_index { |msg| msg['method'] == '$/cancelRequest' }
82
- return unless idx
83
-
84
- msg = messages[idx]
85
- messages.delete_at idx
86
- msg
87
- end
88
-
89
- def next_priority
90
- # Prioritize updates and version-dependent messages for performance
91
- idx = messages.find_index do |msg|
92
- UPDATE_METHODS.include?(msg['method']) || version_dependent?(msg)
93
- end
94
- idx ? messages.delete_at(idx) : messages.shift
95
- end
96
-
97
- # True if the message requires a previous update to have executed in
98
- # order to work correctly.
99
- #
100
- # @param msg [Hash{String => Object}]
101
- # @todo need boolish type from RBS
102
- # @return [Object]
103
- def version_dependent? msg
104
- msg['textDocument'] && msg['position']
105
- end
106
- end
107
- end
108
- end
109
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module LanguageServer
5
+ class Host
6
+ # A serial worker Thread to handle incoming messages.
7
+ #
8
+ class MessageWorker
9
+ UPDATE_METHODS = [
10
+ 'textDocument/didChange',
11
+ 'textDocument/didClose',
12
+ 'textDocument/didOpen',
13
+ 'textDocument/didSave',
14
+ 'workspace/didChangeConfiguration',
15
+ 'workspace/didChangeWatchedFiles',
16
+ 'workspace/didCreateFiles',
17
+ 'workspace/didChangeWorkspaceFolders',
18
+ 'workspace/didDeleteFiles',
19
+ 'workspace/didRenameFiles'
20
+ ].freeze
21
+
22
+ # @param host [Host]
23
+ def initialize(host)
24
+ @host = host
25
+ @mutex = Mutex.new
26
+ @resource = ConditionVariable.new
27
+ @stopped = true
28
+ end
29
+
30
+ # pending handle messages
31
+ # @return [Array<Hash>]
32
+ def messages
33
+ @messages ||= []
34
+ end
35
+
36
+ def stopped?
37
+ @stopped
38
+ end
39
+
40
+ # @return [void]
41
+ def stop
42
+ @stopped = true
43
+ end
44
+
45
+ # @param message [Hash] The message to handle. Will be forwarded to Host#receive
46
+ # @return [void]
47
+ def queue(message)
48
+ @mutex.synchronize do
49
+ messages.push(message)
50
+ @resource.signal
51
+ end
52
+ end
53
+
54
+ # @return [void]
55
+ def start
56
+ return unless @stopped
57
+ @stopped = false
58
+ Thread.new do
59
+ tick until stopped?
60
+ end
61
+ end
62
+
63
+ # @return [void]
64
+ def tick
65
+ message = @mutex.synchronize do
66
+ @resource.wait(@mutex) if messages.empty?
67
+ next_message
68
+ end
69
+ handler = @host.receive(message)
70
+ handler&.send_response
71
+ end
72
+
73
+ private
74
+
75
+ # @return [Hash, nil]
76
+ def next_message
77
+ cancel_message || next_priority
78
+ end
79
+
80
+ # @return [Hash, nil]
81
+ def cancel_message
82
+ # Handle cancellations first
83
+ idx = messages.find_index { |msg| msg['method'] == '$/cancelRequest' }
84
+ return unless idx
85
+
86
+ msg = messages[idx]
87
+ messages.delete_at idx
88
+ msg
89
+ end
90
+
91
+ # @return [Hash, nil]
92
+ def next_priority
93
+ # Prioritize updates and version-dependent messages for performance
94
+ idx = messages.find_index do |msg|
95
+ UPDATE_METHODS.include?(msg['method']) || version_dependent?(msg)
96
+ end
97
+ idx ? messages.delete_at(idx) : messages.shift
98
+ end
99
+
100
+ # True if the message requires a previous update to have executed in
101
+ # order to work correctly.
102
+ #
103
+ # @param msg [Hash{String => Object}]
104
+ # @todo need boolish type from RBS
105
+ # @return [Object]
106
+ def version_dependent? msg
107
+ msg['textDocument'] && msg['position']
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
@@ -1,99 +1,99 @@
1
- # frozen_string_literal: true
2
-
3
- require 'observer'
4
-
5
- module Solargraph
6
- module LanguageServer
7
- class Host
8
- # A Host class for managing sources.
9
- #
10
- class Sources
11
- include Observable
12
- include UriHelpers
13
-
14
- # @param uri [String]
15
- # @return [void]
16
- def add_uri(uri)
17
- queue.push(uri)
18
- end
19
-
20
- # Open a source.
21
- #
22
- # @param uri [String]
23
- # @param text [String]
24
- # @param version [Integer]
25
- # @return [Source]
26
- def open uri, text, version
27
- filename = uri_to_file(uri)
28
- source = Solargraph::Source.new(text, filename, version)
29
- open_source_hash[uri] = source
30
- end
31
-
32
- # @param uri [String]
33
- # @return [void]
34
- def open_from_disk uri
35
- source = Solargraph::Source.load(UriHelpers.uri_to_file(uri))
36
- open_source_hash[uri] = source
37
- end
38
-
39
- # Update an existing source.
40
- #
41
- # @raise [FileNotFoundError] if the URI does not match an open source.
42
- #
43
- # @param uri [String]
44
- # @param updater [Source::Updater]
45
- # @return [void]
46
- def update uri, updater
47
- src = find(uri)
48
- open_source_hash[uri] = src.synchronize(updater)
49
- changed
50
- notify_observers uri
51
- end
52
-
53
- # Find the source with the given URI.
54
- #
55
- # @raise [FileNotFoundError] if the URI does not match an open source.
56
- #
57
- # @param uri [String]
58
- # @return [Solargraph::Source]
59
- def find uri
60
- open_source_hash[uri] || raise(Solargraph::FileNotFoundError, "Host could not find #{uri}")
61
- end
62
-
63
- # Close the source with the given URI.
64
- #
65
- # @param uri [String]
66
- # @return [void]
67
- def close uri
68
- open_source_hash.delete uri
69
- end
70
-
71
- # True if a source with given URI is currently open.
72
- # @param uri [String]
73
- # @return [Boolean]
74
- def include? uri
75
- open_source_hash.key? uri
76
- end
77
-
78
- # @return [void]
79
- def clear
80
- open_source_hash.clear
81
- end
82
-
83
- private
84
-
85
- # @return [Hash{String => Solargraph::Source}]
86
- def open_source_hash
87
- @open_source_hash ||= {}
88
- end
89
-
90
- # An array of source URIs that are waiting to finish synchronizing.
91
- #
92
- # @return [::Array<String>]
93
- def queue
94
- @queue ||= []
95
- end
96
- end
97
- end
98
- end
99
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'observer'
4
+
5
+ module Solargraph
6
+ module LanguageServer
7
+ class Host
8
+ # A Host class for managing sources.
9
+ #
10
+ class Sources
11
+ include Observable
12
+ include UriHelpers
13
+
14
+ # @param uri [String]
15
+ # @return [void]
16
+ def add_uri(uri)
17
+ queue.push(uri)
18
+ end
19
+
20
+ # Open a source.
21
+ #
22
+ # @param uri [String]
23
+ # @param text [String]
24
+ # @param version [Integer]
25
+ # @return [Source]
26
+ def open uri, text, version
27
+ filename = uri_to_file(uri)
28
+ source = Solargraph::Source.new(text, filename, version)
29
+ open_source_hash[uri] = source
30
+ end
31
+
32
+ # @param uri [String]
33
+ # @return [void]
34
+ def open_from_disk uri
35
+ source = Solargraph::Source.load(UriHelpers.uri_to_file(uri))
36
+ open_source_hash[uri] = source
37
+ end
38
+
39
+ # Update an existing source.
40
+ #
41
+ # @raise [FileNotFoundError] if the URI does not match an open source.
42
+ #
43
+ # @param uri [String]
44
+ # @param updater [Source::Updater]
45
+ # @return [void]
46
+ def update uri, updater
47
+ src = find(uri)
48
+ open_source_hash[uri] = src.synchronize(updater)
49
+ changed
50
+ notify_observers uri
51
+ end
52
+
53
+ # Find the source with the given URI.
54
+ #
55
+ # @raise [FileNotFoundError] if the URI does not match an open source.
56
+ #
57
+ # @param uri [String]
58
+ # @return [Solargraph::Source]
59
+ def find uri
60
+ open_source_hash[uri] || raise(Solargraph::FileNotFoundError, "Host could not find #{uri}")
61
+ end
62
+
63
+ # Close the source with the given URI.
64
+ #
65
+ # @param uri [String]
66
+ # @return [void]
67
+ def close uri
68
+ open_source_hash.delete uri
69
+ end
70
+
71
+ # True if a source with given URI is currently open.
72
+ # @param uri [String]
73
+ # @return [Boolean]
74
+ def include? uri
75
+ open_source_hash.key? uri
76
+ end
77
+
78
+ # @return [void]
79
+ def clear
80
+ open_source_hash.clear
81
+ end
82
+
83
+ private
84
+
85
+ # @return [Hash{String => Solargraph::Source}]
86
+ def open_source_hash
87
+ @open_source_hash ||= {}
88
+ end
89
+
90
+ # An array of source URIs that are waiting to finish synchronizing.
91
+ #
92
+ # @return [::Array<String>]
93
+ def queue
94
+ @queue ||= []
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end