solargraph 0.47.2 → 0.54.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.
Files changed (191) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +1 -0
  3. data/.github/workflows/plugins.yml +40 -0
  4. data/.github/workflows/rspec.yml +4 -8
  5. data/.github/workflows/typecheck.yml +34 -0
  6. data/.yardopts +2 -2
  7. data/CHANGELOG.md +166 -3
  8. data/LICENSE +1 -1
  9. data/README.md +19 -16
  10. data/SPONSORS.md +2 -9
  11. data/lib/solargraph/api_map/cache.rb +50 -20
  12. data/lib/solargraph/api_map/source_to_yard.rb +17 -10
  13. data/lib/solargraph/api_map/store.rb +68 -15
  14. data/lib/solargraph/api_map.rb +238 -112
  15. data/lib/solargraph/bench.rb +3 -2
  16. data/lib/solargraph/cache.rb +77 -0
  17. data/lib/solargraph/complex_type/type_methods.rb +116 -35
  18. data/lib/solargraph/complex_type/unique_type.rb +261 -33
  19. data/lib/solargraph/complex_type.rb +149 -30
  20. data/lib/solargraph/convention/rakefile.rb +17 -0
  21. data/lib/solargraph/convention.rb +2 -3
  22. data/lib/solargraph/converters/dd.rb +5 -0
  23. data/lib/solargraph/converters/dl.rb +3 -0
  24. data/lib/solargraph/converters/dt.rb +3 -0
  25. data/lib/solargraph/diagnostics/rubocop.rb +23 -8
  26. data/lib/solargraph/diagnostics/rubocop_helpers.rb +4 -1
  27. data/lib/solargraph/diagnostics/type_check.rb +1 -0
  28. data/lib/solargraph/diagnostics.rb +2 -2
  29. data/lib/solargraph/doc_map.rb +187 -0
  30. data/lib/solargraph/gem_pins.rb +72 -0
  31. data/lib/solargraph/language_server/host/diagnoser.rb +2 -2
  32. data/lib/solargraph/language_server/host/dispatch.rb +22 -5
  33. data/lib/solargraph/language_server/host/message_worker.rb +4 -0
  34. data/lib/solargraph/language_server/host/sources.rb +8 -65
  35. data/lib/solargraph/language_server/host.rb +88 -93
  36. data/lib/solargraph/language_server/message/base.rb +1 -1
  37. data/lib/solargraph/language_server/message/completion_item/resolve.rb +3 -1
  38. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +13 -1
  39. data/lib/solargraph/language_server/message/extended/download_core.rb +1 -5
  40. data/lib/solargraph/language_server/message/initialize.rb +27 -0
  41. data/lib/solargraph/language_server/message/initialized.rb +1 -0
  42. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +4 -1
  43. data/lib/solargraph/language_server/message/text_document/formatting.rb +5 -4
  44. data/lib/solargraph/language_server/message/text_document/hover.rb +2 -0
  45. data/lib/solargraph/language_server/message/text_document/signature_help.rb +1 -6
  46. data/lib/solargraph/language_server/message/text_document/type_definition.rb +24 -0
  47. data/lib/solargraph/language_server/message/text_document.rb +1 -1
  48. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +5 -0
  49. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +10 -3
  50. data/lib/solargraph/language_server/message.rb +1 -0
  51. data/lib/solargraph/language_server/progress.rb +118 -0
  52. data/lib/solargraph/language_server/transport/adapter.rb +16 -1
  53. data/lib/solargraph/language_server/transport/data_reader.rb +2 -0
  54. data/lib/solargraph/language_server.rb +1 -0
  55. data/lib/solargraph/library.rb +231 -104
  56. data/lib/solargraph/location.rb +1 -0
  57. data/lib/solargraph/page.rb +6 -0
  58. data/lib/solargraph/parser/comment_ripper.rb +4 -0
  59. data/lib/solargraph/parser/node_methods.rb +47 -7
  60. data/lib/solargraph/parser/node_processor/base.rb +11 -1
  61. data/lib/solargraph/parser/node_processor.rb +1 -0
  62. data/lib/solargraph/parser/{legacy → parser_gem}/class_methods.rb +31 -9
  63. data/lib/solargraph/parser/{legacy → parser_gem}/flawed_builder.rb +3 -1
  64. data/lib/solargraph/parser/{legacy → parser_gem}/node_chainer.rb +57 -41
  65. data/lib/solargraph/parser/parser_gem/node_methods.rb +495 -0
  66. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/alias_node.rb +1 -1
  67. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +53 -0
  68. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/begin_node.rb +1 -1
  69. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/block_node.rb +3 -2
  70. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/casgn_node.rb +14 -4
  71. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/cvasgn_node.rb +1 -1
  72. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/def_node.rb +7 -20
  73. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/defs_node.rb +2 -2
  74. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/gvasgn_node.rb +1 -1
  75. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/ivasgn_node.rb +2 -2
  76. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/lvasgn_node.rb +2 -2
  77. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +47 -0
  78. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/namespace_node.rb +2 -2
  79. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/orasgn_node.rb +1 -1
  80. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/resbody_node.rb +3 -3
  81. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +42 -0
  82. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/send_node.rb +7 -5
  83. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/sym_node.rb +1 -1
  84. data/lib/solargraph/parser/parser_gem/node_processors.rb +56 -0
  85. data/lib/solargraph/parser/parser_gem.rb +12 -0
  86. data/lib/solargraph/parser/region.rb +1 -1
  87. data/lib/solargraph/parser/snippet.rb +2 -0
  88. data/lib/solargraph/parser.rb +9 -10
  89. data/lib/solargraph/pin/base.rb +69 -11
  90. data/lib/solargraph/pin/base_variable.rb +40 -7
  91. data/lib/solargraph/pin/block.rb +81 -33
  92. data/lib/solargraph/pin/closure.rb +17 -2
  93. data/lib/solargraph/pin/common.rb +7 -3
  94. data/lib/solargraph/pin/conversions.rb +34 -8
  95. data/lib/solargraph/pin/delegated_method.rb +101 -0
  96. data/lib/solargraph/pin/documenting.rb +25 -32
  97. data/lib/solargraph/pin/instance_variable.rb +4 -0
  98. data/lib/solargraph/pin/local_variable.rb +13 -1
  99. data/lib/solargraph/pin/method.rb +273 -17
  100. data/lib/solargraph/pin/namespace.rb +17 -1
  101. data/lib/solargraph/pin/parameter.rb +40 -28
  102. data/lib/solargraph/pin/reference/override.rb +2 -2
  103. data/lib/solargraph/pin/reference.rb +8 -0
  104. data/lib/solargraph/pin/search.rb +4 -4
  105. data/lib/solargraph/pin/signature.rb +143 -0
  106. data/lib/solargraph/pin.rb +2 -1
  107. data/lib/solargraph/range.rb +4 -6
  108. data/lib/solargraph/rbs_map/conversions.rb +607 -0
  109. data/lib/solargraph/rbs_map/core_fills.rb +50 -0
  110. data/lib/solargraph/rbs_map/core_map.rb +28 -0
  111. data/lib/solargraph/rbs_map/stdlib_map.rb +33 -0
  112. data/lib/solargraph/rbs_map.rb +92 -0
  113. data/lib/solargraph/shell.rb +85 -59
  114. data/lib/solargraph/source/chain/array.rb +32 -0
  115. data/lib/solargraph/source/chain/block_symbol.rb +13 -0
  116. data/lib/solargraph/source/chain/call.rb +125 -61
  117. data/lib/solargraph/source/chain/constant.rb +15 -1
  118. data/lib/solargraph/source/chain/if.rb +23 -0
  119. data/lib/solargraph/source/chain/link.rb +8 -2
  120. data/lib/solargraph/source/chain/or.rb +1 -1
  121. data/lib/solargraph/source/chain/z_super.rb +3 -3
  122. data/lib/solargraph/source/chain.rb +64 -14
  123. data/lib/solargraph/source/change.rb +3 -0
  124. data/lib/solargraph/source/cursor.rb +2 -0
  125. data/lib/solargraph/source/source_chainer.rb +8 -5
  126. data/lib/solargraph/source/updater.rb +1 -0
  127. data/lib/solargraph/source.rb +18 -63
  128. data/lib/solargraph/source_map/clip.rb +31 -23
  129. data/lib/solargraph/source_map/mapper.rb +23 -7
  130. data/lib/solargraph/source_map.rb +36 -11
  131. data/lib/solargraph/type_checker/checks.rb +10 -2
  132. data/lib/solargraph/type_checker.rb +229 -100
  133. data/lib/solargraph/version.rb +1 -1
  134. data/lib/solargraph/views/environment.erb +2 -2
  135. data/lib/solargraph/workspace/config.rb +15 -11
  136. data/lib/solargraph/workspace.rb +41 -17
  137. data/lib/solargraph/yard_map/cache.rb +6 -0
  138. data/lib/solargraph/yard_map/helpers.rb +1 -1
  139. data/lib/solargraph/yard_map/mapper/to_method.rb +23 -7
  140. data/lib/solargraph/yard_map/mapper.rb +1 -1
  141. data/lib/solargraph/yard_map/to_method.rb +11 -4
  142. data/lib/solargraph/yard_map.rb +1 -443
  143. data/lib/solargraph/yard_tags.rb +20 -0
  144. data/lib/solargraph/yardoc.rb +52 -0
  145. data/lib/solargraph.rb +8 -6
  146. data/solargraph.gemspec +19 -8
  147. metadata +164 -99
  148. data/.travis.yml +0 -19
  149. data/lib/solargraph/api_map/bundler_methods.rb +0 -22
  150. data/lib/solargraph/compat.rb +0 -37
  151. data/lib/solargraph/convention/rspec.rb +0 -30
  152. data/lib/solargraph/documentor.rb +0 -76
  153. data/lib/solargraph/language_server/host/cataloger.rb +0 -56
  154. data/lib/solargraph/parser/legacy/node_methods.rb +0 -325
  155. data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +0 -23
  156. data/lib/solargraph/parser/legacy/node_processors/args_node.rb +0 -35
  157. data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +0 -15
  158. data/lib/solargraph/parser/legacy/node_processors/cvasgn_node.rb +0 -23
  159. data/lib/solargraph/parser/legacy/node_processors/def_node.rb +0 -63
  160. data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +0 -21
  161. data/lib/solargraph/parser/legacy/node_processors.rb +0 -54
  162. data/lib/solargraph/parser/legacy.rb +0 -12
  163. data/lib/solargraph/parser/rubyvm/class_methods.rb +0 -144
  164. data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -160
  165. data/lib/solargraph/parser/rubyvm/node_methods.rb +0 -315
  166. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +0 -85
  167. data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +0 -42
  168. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +0 -22
  169. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +0 -57
  170. data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +0 -23
  171. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +0 -38
  172. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +0 -39
  173. data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +0 -20
  174. data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +0 -27
  175. data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +0 -39
  176. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +0 -26
  177. data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +0 -15
  178. data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +0 -45
  179. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +0 -21
  180. data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +0 -15
  181. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +0 -277
  182. data/lib/solargraph/parser/rubyvm/node_processors/sym_node.rb +0 -18
  183. data/lib/solargraph/parser/rubyvm/node_processors.rb +0 -63
  184. data/lib/solargraph/parser/rubyvm.rb +0 -40
  185. data/lib/solargraph/yard_map/core_docs.rb +0 -170
  186. data/lib/solargraph/yard_map/core_fills.rb +0 -208
  187. data/lib/solargraph/yard_map/core_gen.rb +0 -76
  188. data/lib/solargraph/yard_map/rdoc_to_yard.rb +0 -140
  189. data/lib/solargraph/yard_map/stdlib_fills.rb +0 -43
  190. data/lib/yard-solargraph.rb +0 -33
  191. data/yardoc/2.2.2.tar.gz +0 -0
@@ -0,0 +1,187 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ # A collection of pins generated from required gems.
5
+ #
6
+ class DocMap
7
+ # @return [Array<String>]
8
+ attr_reader :requires
9
+
10
+ # @return [Array<Gem::Specification>]
11
+ attr_reader :preferences
12
+
13
+ # @return [Array<Pin::Base>]
14
+ attr_reader :pins
15
+
16
+ # @return [Array<Gem::Specification>]
17
+ attr_reader :uncached_gemspecs
18
+
19
+ # @param requires [Array<String>]
20
+ # @param preferences [Array<Gem::Specification>]
21
+ # @param rbs_path [String, Pathname, nil]
22
+ def initialize(requires, preferences, rbs_path = nil)
23
+ @requires = requires.compact
24
+ @preferences = preferences.compact
25
+ @rbs_path = rbs_path
26
+ generate
27
+ end
28
+
29
+ # @return [Array<Gem::Specification>]
30
+ def gemspecs
31
+ @gemspecs ||= required_gem_map.values.compact
32
+ end
33
+
34
+ # @return [Array<String>]
35
+ def unresolved_requires
36
+ @unresolved_requires ||= required_gem_map.select { |_, gemspec| gemspec.nil? }.keys
37
+ end
38
+
39
+ # @return [Hash{Gem::Specification => Array[Pin::Base]}]
40
+ def self.gems_in_memory
41
+ @gems_in_memory ||= {}
42
+ end
43
+
44
+ # @return [Set<Gem::Specification>]
45
+ def dependencies
46
+ @dependencies ||= (gemspecs.flat_map { |spec| fetch_dependencies(spec) } - gemspecs).to_set
47
+ end
48
+
49
+ private
50
+
51
+ # @return [void]
52
+ def generate
53
+ @pins = []
54
+ @uncached_gemspecs = []
55
+ required_gem_map.each do |path, gemspec|
56
+ if gemspec
57
+ try_cache gemspec
58
+ else
59
+ try_stdlib_map path
60
+ end
61
+ end
62
+ dependencies.each { |dep| try_cache dep }
63
+ @uncached_gemspecs.uniq!
64
+ end
65
+
66
+ # @return [Hash{String => Gem::Specification, nil}]
67
+ def required_gem_map
68
+ @required_gem_map ||= requires.to_h { |path| [path, resolve_path_to_gemspec(path)] }
69
+ end
70
+
71
+ # @return [Hash{String => Gem::Specification}]
72
+ def preference_map
73
+ @preference_map ||= preferences.to_h { |gemspec| [gemspec.name, gemspec] }
74
+ end
75
+
76
+ # @param gemspec [Gem::Specification]
77
+ # @return [void]
78
+ def try_cache gemspec
79
+ return if try_gem_in_memory(gemspec)
80
+ cache_file = File.join('gems', "#{gemspec.name}-#{gemspec.version}.ser")
81
+ if Cache.exist?(cache_file)
82
+ cached = Cache.load(cache_file)
83
+ gempins = update_from_collection(gemspec, cached)
84
+ self.class.gems_in_memory[gemspec] = gempins
85
+ @pins.concat gempins
86
+ else
87
+ Solargraph.logger.debug "No pin cache for #{gemspec.name} #{gemspec.version}"
88
+ @uncached_gemspecs.push gemspec
89
+ end
90
+ end
91
+
92
+ # @param path [String] require path that might be in the RBS stdlib collection
93
+ # @return [void]
94
+ def try_stdlib_map path
95
+ map = RbsMap::StdlibMap.load(path)
96
+ if map.resolved?
97
+ Solargraph.logger.debug "Loading stdlib pins for #{path}"
98
+ @pins.concat map.pins
99
+ else
100
+ # @todo Temporarily ignoring unresolved `require 'set'`
101
+ Solargraph.logger.debug "Require path #{path} could not be resolved" unless path == 'set'
102
+ end
103
+ end
104
+
105
+ # @param gemspec [Gem::Specification]
106
+ # @return [Boolean]
107
+ def try_gem_in_memory gemspec
108
+ gempins = DocMap.gems_in_memory[gemspec]
109
+ return false unless gempins
110
+ Solargraph.logger.debug "Found #{gemspec.name} #{gemspec.version} in memory"
111
+ @pins.concat gempins
112
+ true
113
+ end
114
+
115
+ def update_from_collection gemspec, gempins
116
+ return gempins unless @rbs_path && File.directory?(@rbs_path)
117
+ return gempins if RbsMap.new(gemspec.name, gemspec.version).resolved?
118
+
119
+ rbs_map = RbsMap.new(gemspec.name, gemspec.version, directories: [@rbs_path])
120
+ return gempins unless rbs_map.resolved?
121
+
122
+ Solargraph.logger.info "Updating #{gemspec.name} #{gemspec.version} from collection"
123
+ GemPins.combine(gempins, rbs_map)
124
+ end
125
+
126
+ # @param path [String]
127
+ # @return [Gem::Specification, nil]
128
+ def resolve_path_to_gemspec path
129
+ return nil if path.empty?
130
+
131
+ gemspec = Gem::Specification.find_by_path(path)
132
+ if gemspec.nil?
133
+ gem_name_guess = path.split('/').first
134
+ begin
135
+ # this can happen when the gem is included via a local path in
136
+ # a Gemfile; Gem doesn't try to index the paths in that case.
137
+ #
138
+ # See if we can make a good guess:
139
+ potential_gemspec = Gem::Specification.find_by_name(gem_name_guess)
140
+ file = "lib/#{path}.rb"
141
+ gemspec = potential_gemspec if potential_gemspec.files.any? { |gemspec_file| file == gemspec_file }
142
+ rescue Gem::MissingSpecError
143
+ Solargraph.logger.debug "Require path #{path} could not be resolved to a gem via find_by_path or guess of #{gem_name_guess}"
144
+ nil
145
+ end
146
+ end
147
+ gemspec_or_preference gemspec
148
+ end
149
+
150
+ # @param gemspec [Gem::Specification, nil]
151
+ # @return [Gem::Specification, nil]
152
+ def gemspec_or_preference gemspec
153
+ return gemspec unless gemspec && preference_map.key?(gemspec.name)
154
+ return gemspec if gemspec.version == preference_map[gemspec.name].version
155
+
156
+ change_gemspec_version gemspec, preference_map[by_path.name].version
157
+ end
158
+
159
+ # @param gemspec [Gem::Specification]
160
+ # @param version [Gem::Version]
161
+ # @return [Gem::Specification]
162
+ def change_gemspec_version gemspec, version
163
+ Gem::Specification.find_by_name(gemspec.name, "= #{version}")
164
+ rescue Gem::MissingSpecError
165
+ Solargraph.logger.info "Gem #{gemspec.name} version #{version} not found. Using #{gemspec.version} instead"
166
+ gemspec
167
+ end
168
+
169
+ # @param gemspec [Gem::Specification]
170
+ # @return [Array<Gem::Specification>]
171
+ def fetch_dependencies gemspec
172
+ only_runtime_dependencies(gemspec).each_with_object(Set.new) do |spec, deps|
173
+ Solargraph.logger.info "Adding #{spec.name} dependency for #{gemspec.name}"
174
+ dep = Gem::Specification.find_by_name(spec.name, spec.requirement)
175
+ deps.merge fetch_dependencies(dep) if deps.add?(dep)
176
+ rescue Gem::MissingSpecError
177
+ Solargraph.logger.warn "Gem dependency #{spec.name} #{spec.requirements} for #{gemspec.name} not found."
178
+ end.to_a
179
+ end
180
+
181
+ # @param gemspec [Gem::Specification]
182
+ # @return [Array<Gem::Dependency>]
183
+ def only_runtime_dependencies gemspec
184
+ gemspec.dependencies - gemspec.development_dependencies
185
+ end
186
+ end
187
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rbs'
4
+
5
+ module Solargraph
6
+ # A utility for building gem pins from a combination of YARD and RBS
7
+ # documentation.
8
+ #
9
+ module GemPins
10
+ # Build an array of pins from a gem specification. The process starts with
11
+ # YARD, enhances the resulting pins with RBS definitions, and appends RBS
12
+ # pins that don't exist in the YARD mapping.
13
+ #
14
+ # @param gemspec [Gem::Specification]
15
+ # @return [Array<Pin::Base>]
16
+ def self.build(gemspec)
17
+ yard_pins = build_yard_pins(gemspec)
18
+ rbs_map = RbsMap.from_gemspec(gemspec)
19
+ combine yard_pins, rbs_map
20
+ end
21
+
22
+ # @param yard_pins [Array<Pin::Base>]
23
+ # @param rbs_map [RbsMap]
24
+ # @return [Array<Pin::Base>]
25
+ def self.combine(yard_pins, rbs_map)
26
+ in_yard = Set.new
27
+ combined = yard_pins.map do |yard|
28
+ in_yard.add yard.path
29
+ next yard unless yard.is_a?(Pin::Method)
30
+
31
+ rbs = rbs_map.path_pin(yard.path, Pin::Method)
32
+ next yard unless rbs
33
+
34
+ # @sg-ignore
35
+ yard.class.new(
36
+ location: yard.location,
37
+ closure: yard.closure,
38
+ name: yard.name,
39
+ comments: yard.comments,
40
+ scope: yard.scope,
41
+ parameters: rbs.parameters,
42
+ generics: rbs.generics,
43
+ node: yard.node,
44
+ signatures: yard.signatures,
45
+ return_type: best_return_type(rbs.return_type, yard.return_type)
46
+ )
47
+ end
48
+ in_rbs = rbs_map.pins.reject { |pin| in_yard.include?(pin.path) }
49
+ combined + in_rbs
50
+ end
51
+
52
+ class << self
53
+ private
54
+
55
+ # @param gemspec [Gem::Specification]
56
+ # @return [Array<Pin::Base>]
57
+ def build_yard_pins(gemspec)
58
+ Yardoc.cache(gemspec) unless Yardoc.cached?(gemspec)
59
+ yardoc = Yardoc.load!(gemspec)
60
+ YardMap::Mapper.new(yardoc, gemspec).map
61
+ end
62
+
63
+ # Select the first defined type.
64
+ #
65
+ # @param choices [Array<ComplexType>]
66
+ # @return [ComplexType]
67
+ def best_return_type *choices
68
+ choices.find { |pin| pin.defined? } || choices.first || ComplexType::UNDEFINED
69
+ end
70
+ end
71
+ end
72
+ end
@@ -38,7 +38,7 @@ module Solargraph
38
38
 
39
39
  # Start the diagnosis thread.
40
40
  #
41
- # @return [self]
41
+ # @return [self, nil]
42
42
  def start
43
43
  return unless @stopped
44
44
  @stopped = false
@@ -81,7 +81,7 @@ module Solargraph
81
81
  # @return [Mutex]
82
82
  attr_reader :mutex
83
83
 
84
- # @return [Array]
84
+ # @return [::Array]
85
85
  attr_reader :queue
86
86
  end
87
87
  end
@@ -6,6 +6,12 @@ module Solargraph
6
6
  # Methods for associating sources with libraries via URIs.
7
7
  #
8
8
  module Dispatch
9
+ # @abstract
10
+ # @return [Host::Diagnoser]
11
+ def diagnoser
12
+ raise NotImplementedError, 'Host::Dispatch requires a diagnoser method'
13
+ end
14
+
9
15
  # @return [Sources]
10
16
  def sources
11
17
  @sources ||= begin
@@ -15,7 +21,7 @@ module Solargraph
15
21
  end
16
22
  end
17
23
 
18
- # @return [Array<Library>]
24
+ # @return [::Array<Library>]
19
25
  def libraries
20
26
  @libraries ||= []
21
27
  end
@@ -27,9 +33,9 @@ module Solargraph
27
33
  # @return [void]
28
34
  def update_libraries uri
29
35
  src = sources.find(uri)
30
- libraries.each do |lib|
31
- lib.merge src if lib.contain?(src.filename)
32
- end
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 }
33
39
  diagnoser.schedule uri
34
40
  end
35
41
 
@@ -89,6 +95,10 @@ module Solargraph
89
95
  nil
90
96
  end
91
97
 
98
+ def options
99
+ @options ||= {}.freeze
100
+ end
101
+
92
102
  # Get a generic library for the given URI and attach the corresponding
93
103
  # source.
94
104
  #
@@ -103,7 +113,14 @@ module Solargraph
103
113
 
104
114
  # @return [Library]
105
115
  def generic_library
106
- @generic_library ||= Solargraph::Library.new
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)
107
124
  end
108
125
  end
109
126
  end
@@ -16,6 +16,7 @@ module Solargraph
16
16
  end
17
17
 
18
18
  # pending handle messages
19
+ # @return [Array<Hash>]
19
20
  def messages
20
21
  @messages ||= []
21
22
  end
@@ -24,6 +25,7 @@ module Solargraph
24
25
  @stopped
25
26
  end
26
27
 
28
+ # @return [void]
27
29
  def stop
28
30
  @stopped = true
29
31
  end
@@ -37,6 +39,7 @@ module Solargraph
37
39
  end
38
40
  end
39
41
 
42
+ # @return [void]
40
43
  def start
41
44
  return unless @stopped
42
45
  @stopped = false
@@ -45,6 +48,7 @@ module Solargraph
45
48
  end
46
49
  end
47
50
 
51
+ # @return [void]
48
52
  def tick
49
53
  message = @mutex.synchronize do
50
54
  @resource.wait(@mutex) if messages.empty?
@@ -11,53 +11,10 @@ module Solargraph
11
11
  include Observable
12
12
  include UriHelpers
13
13
 
14
- def initialize
15
- @mutex = Mutex.new
16
- @stopped = true
17
- @has_uri = ConditionVariable.new
18
- end
19
-
20
- def stopped?
21
- @stopped
22
- end
23
-
24
- # @return [void]
25
- def start
26
- return unless @stopped
27
- @stopped = false
28
- Thread.new do
29
- tick until stopped?
30
- end
31
- end
32
-
33
- # @return [void]
34
- def tick
35
- uri = mutex.synchronize { next_uri }
36
-
37
- return if queue.include?(uri)
38
- mutex.synchronize do
39
- nxt = open_source_hash[uri].finish_synchronize
40
- open_source_hash[uri] = nxt
41
- changed
42
- notify_observers uri
43
- end
44
- end
45
-
14
+ # @param uri [String]
46
15
  # @return [void]
47
16
  def add_uri(uri)
48
17
  queue.push(uri)
49
- @has_uri.signal
50
- end
51
-
52
- # @return [String]
53
- def next_uri
54
- @has_uri.wait(mutex) if queue.empty?
55
- queue.shift
56
- end
57
-
58
- # @return [void]
59
- def stop
60
- @stopped = true
61
18
  end
62
19
 
63
20
  # Open a source.
@@ -72,6 +29,8 @@ module Solargraph
72
29
  open_source_hash[uri] = source
73
30
  end
74
31
 
32
+ # @param uri [String]
33
+ # @return [void]
75
34
  def open_from_disk uri
76
35
  source = Solargraph::Source.load(UriHelpers.uri_to_file(uri))
77
36
  open_source_hash[uri] = source
@@ -81,25 +40,12 @@ module Solargraph
81
40
  #
82
41
  # @raise [FileNotFoundError] if the URI does not match an open source.
83
42
  #
84
- # @param uri [String]
85
- # @param updater [Source::Updater]
86
- # @return [Source]
87
- def update uri, updater
88
- src = find(uri)
89
- mutex.synchronize { open_source_hash[uri] = src.synchronize(updater) }
90
- changed
91
- notify_observers uri
92
- end
93
-
94
43
  # @param uri [String]
95
44
  # @param updater [Source::Updater]
96
45
  # @return [void]
97
- def async_update uri, updater
46
+ def update uri, updater
98
47
  src = find(uri)
99
- mutex.synchronize do
100
- open_source_hash[uri] = src.start_synchronize(updater)
101
- add_uri(uri)
102
- end
48
+ open_source_hash[uri] = src.synchronize(updater)
103
49
  changed
104
50
  notify_observers uri
105
51
  end
@@ -109,7 +55,7 @@ module Solargraph
109
55
  # @raise [FileNotFoundError] if the URI does not match an open source.
110
56
  #
111
57
  # @param uri [String]
112
- # @return [Source]
58
+ # @return [Solargraph::Source]
113
59
  def find uri
114
60
  open_source_hash[uri] || raise(Solargraph::FileNotFoundError, "Host could not find #{uri}")
115
61
  end
@@ -136,17 +82,14 @@ module Solargraph
136
82
 
137
83
  private
138
84
 
139
- # @return [Hash]
85
+ # @return [Hash{String => Solargraph::Source}]
140
86
  def open_source_hash
141
87
  @open_source_hash ||= {}
142
88
  end
143
89
 
144
- # @return [Mutex]
145
- attr_reader :mutex
146
-
147
90
  # An array of source URIs that are waiting to finish synchronizing.
148
91
  #
149
- # @return [Array<String>]
92
+ # @return [::Array<String>]
150
93
  def queue
151
94
  @queue ||= []
152
95
  end