solargraph 0.50.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 (264) 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 +218 -0
  5. data/.github/workflows/rspec.yml +58 -12
  6. data/.github/workflows/typecheck.yml +39 -0
  7. data/.gitignore +8 -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 +3 -2
  13. data/CHANGELOG.md +306 -3
  14. data/README.md +29 -18
  15. data/Rakefile +125 -13
  16. data/SPONSORS.md +2 -9
  17. data/bin/solargraph +3 -0
  18. data/lib/solargraph/api_map/cache.rb +110 -70
  19. data/lib/solargraph/api_map/constants.rb +279 -0
  20. data/lib/solargraph/api_map/index.rb +193 -0
  21. data/lib/solargraph/api_map/source_to_yard.rb +97 -81
  22. data/lib/solargraph/api_map/store.rb +384 -268
  23. data/lib/solargraph/api_map.rb +945 -704
  24. data/lib/solargraph/bench.rb +21 -3
  25. data/lib/solargraph/complex_type/type_methods.rb +228 -134
  26. data/lib/solargraph/complex_type/unique_type.rb +482 -132
  27. data/lib/solargraph/complex_type.rb +444 -254
  28. data/lib/solargraph/convention/active_support_concern.rb +111 -0
  29. data/lib/solargraph/convention/base.rb +20 -3
  30. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -0
  31. data/lib/solargraph/convention/data_definition/data_definition_node.rb +91 -0
  32. data/lib/solargraph/convention/data_definition.rb +105 -0
  33. data/lib/solargraph/convention/gemspec.rb +3 -2
  34. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +61 -0
  35. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +102 -0
  36. data/lib/solargraph/convention/struct_definition.rb +164 -0
  37. data/lib/solargraph/convention.rb +36 -7
  38. data/lib/solargraph/converters/dd.rb +5 -0
  39. data/lib/solargraph/converters/dl.rb +3 -0
  40. data/lib/solargraph/converters/dt.rb +3 -0
  41. data/lib/solargraph/diagnostics/require_not_found.rb +53 -53
  42. data/lib/solargraph/diagnostics/rubocop.rb +118 -112
  43. data/lib/solargraph/diagnostics/rubocop_helpers.rb +68 -65
  44. data/lib/solargraph/diagnostics/type_check.rb +55 -54
  45. data/lib/solargraph/diagnostics.rb +2 -2
  46. data/lib/solargraph/doc_map.rb +439 -0
  47. data/lib/solargraph/environ.rb +9 -2
  48. data/lib/solargraph/equality.rb +34 -0
  49. data/lib/solargraph/gem_pins.rb +98 -0
  50. data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
  51. data/lib/solargraph/language_server/host/dispatch.rb +130 -111
  52. data/lib/solargraph/language_server/host/message_worker.rb +112 -59
  53. data/lib/solargraph/language_server/host/sources.rb +99 -156
  54. data/lib/solargraph/language_server/host.rb +878 -869
  55. data/lib/solargraph/language_server/message/base.rb +20 -12
  56. data/lib/solargraph/language_server/message/completion_item/resolve.rb +3 -1
  57. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +114 -100
  58. data/lib/solargraph/language_server/message/extended/document.rb +23 -20
  59. data/lib/solargraph/language_server/message/extended/document_gems.rb +3 -3
  60. data/lib/solargraph/language_server/message/initialize.rb +28 -1
  61. data/lib/solargraph/language_server/message/initialized.rb +1 -0
  62. data/lib/solargraph/language_server/message/text_document/completion.rb +56 -59
  63. data/lib/solargraph/language_server/message/text_document/definition.rb +40 -38
  64. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +26 -23
  65. data/lib/solargraph/language_server/message/text_document/formatting.rb +148 -126
  66. data/lib/solargraph/language_server/message/text_document/hover.rb +58 -56
  67. data/lib/solargraph/language_server/message/text_document/signature_help.rb +24 -24
  68. data/lib/solargraph/language_server/message/text_document/type_definition.rb +25 -0
  69. data/lib/solargraph/language_server/message/text_document.rb +1 -1
  70. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +5 -0
  71. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +2 -0
  72. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +23 -23
  73. data/lib/solargraph/language_server/message.rb +1 -0
  74. data/lib/solargraph/language_server/progress.rb +143 -0
  75. data/lib/solargraph/language_server/request.rb +4 -1
  76. data/lib/solargraph/language_server/transport/adapter.rb +16 -1
  77. data/lib/solargraph/language_server/transport/data_reader.rb +2 -0
  78. data/lib/solargraph/language_server.rb +1 -0
  79. data/lib/solargraph/library.rb +683 -551
  80. data/lib/solargraph/location.rb +82 -37
  81. data/lib/solargraph/logging.rb +37 -27
  82. data/lib/solargraph/page.rb +9 -0
  83. data/lib/solargraph/parser/comment_ripper.rb +69 -52
  84. data/lib/solargraph/parser/flow_sensitive_typing.rb +255 -0
  85. data/lib/solargraph/parser/node_processor/base.rb +92 -77
  86. data/lib/solargraph/parser/node_processor.rb +62 -43
  87. data/lib/solargraph/parser/{legacy → parser_gem}/class_methods.rb +149 -135
  88. data/lib/solargraph/parser/{legacy → parser_gem}/flawed_builder.rb +4 -1
  89. data/lib/solargraph/parser/{legacy → parser_gem}/node_chainer.rb +166 -148
  90. data/lib/solargraph/parser/{legacy → parser_gem}/node_methods.rb +486 -325
  91. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/alias_node.rb +3 -2
  92. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +22 -0
  93. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +59 -0
  94. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/begin_node.rb +15 -15
  95. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/block_node.rb +46 -42
  96. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/casgn_node.rb +4 -3
  97. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/cvasgn_node.rb +3 -2
  98. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/def_node.rb +53 -63
  99. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/defs_node.rb +4 -3
  100. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/gvasgn_node.rb +3 -2
  101. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +23 -0
  102. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/ivasgn_node.rb +40 -38
  103. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/lvasgn_node.rb +29 -28
  104. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +59 -0
  105. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/namespace_node.rb +10 -9
  106. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +98 -0
  107. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/orasgn_node.rb +17 -16
  108. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/resbody_node.rb +38 -36
  109. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/sclass_node.rb +52 -42
  110. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/send_node.rb +291 -257
  111. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/sym_node.rb +4 -2
  112. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -0
  113. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +29 -0
  114. data/lib/solargraph/parser/parser_gem/node_processors.rb +70 -0
  115. data/lib/solargraph/parser/parser_gem.rb +12 -0
  116. data/lib/solargraph/parser/region.rb +69 -66
  117. data/lib/solargraph/parser/snippet.rb +17 -13
  118. data/lib/solargraph/parser.rb +9 -12
  119. data/lib/solargraph/pin/base.rb +729 -299
  120. data/lib/solargraph/pin/base_variable.rb +126 -84
  121. data/lib/solargraph/pin/block.rb +104 -73
  122. data/lib/solargraph/pin/breakable.rb +9 -0
  123. data/lib/solargraph/pin/callable.rb +231 -0
  124. data/lib/solargraph/pin/closure.rb +72 -37
  125. data/lib/solargraph/pin/common.rb +79 -70
  126. data/lib/solargraph/pin/constant.rb +2 -0
  127. data/lib/solargraph/pin/conversions.rb +123 -92
  128. data/lib/solargraph/pin/delegated_method.rb +120 -0
  129. data/lib/solargraph/pin/documenting.rb +114 -105
  130. data/lib/solargraph/pin/instance_variable.rb +34 -30
  131. data/lib/solargraph/pin/keyword.rb +20 -15
  132. data/lib/solargraph/pin/local_variable.rb +75 -55
  133. data/lib/solargraph/pin/method.rb +672 -335
  134. data/lib/solargraph/pin/method_alias.rb +34 -31
  135. data/lib/solargraph/pin/namespace.rb +115 -94
  136. data/lib/solargraph/pin/parameter.rb +275 -206
  137. data/lib/solargraph/pin/proxy_type.rb +39 -29
  138. data/lib/solargraph/pin/reference/override.rb +47 -29
  139. data/lib/solargraph/pin/reference/require.rb +2 -2
  140. data/lib/solargraph/pin/reference/superclass.rb +15 -10
  141. data/lib/solargraph/pin/reference.rb +39 -14
  142. data/lib/solargraph/pin/search.rb +61 -56
  143. data/lib/solargraph/pin/signature.rb +61 -23
  144. data/lib/solargraph/pin/singleton.rb +1 -1
  145. data/lib/solargraph/pin/symbol.rb +53 -47
  146. data/lib/solargraph/pin/until.rb +18 -0
  147. data/lib/solargraph/pin/while.rb +18 -0
  148. data/lib/solargraph/pin.rb +44 -38
  149. data/lib/solargraph/pin_cache.rb +245 -0
  150. data/lib/solargraph/position.rb +132 -100
  151. data/lib/solargraph/range.rb +112 -95
  152. data/lib/solargraph/rbs_map/conversions.rb +823 -394
  153. data/lib/solargraph/rbs_map/core_fills.rb +53 -30
  154. data/lib/solargraph/rbs_map/core_map.rb +58 -38
  155. data/lib/solargraph/rbs_map/stdlib_map.rb +43 -36
  156. data/lib/solargraph/rbs_map.rb +163 -73
  157. data/lib/solargraph/shell.rb +352 -244
  158. data/lib/solargraph/source/chain/array.rb +37 -0
  159. data/lib/solargraph/source/chain/block_symbol.rb +13 -0
  160. data/lib/solargraph/source/chain/block_variable.rb +1 -1
  161. data/lib/solargraph/source/chain/call.rb +337 -215
  162. data/lib/solargraph/source/chain/constant.rb +26 -75
  163. data/lib/solargraph/source/chain/hash.rb +34 -28
  164. data/lib/solargraph/source/chain/head.rb +1 -1
  165. data/lib/solargraph/source/chain/if.rb +28 -0
  166. data/lib/solargraph/source/chain/instance_variable.rb +13 -13
  167. data/lib/solargraph/source/chain/link.rb +44 -6
  168. data/lib/solargraph/source/chain/literal.rb +48 -23
  169. data/lib/solargraph/source/chain/or.rb +23 -23
  170. data/lib/solargraph/source/chain/z_super.rb +4 -4
  171. data/lib/solargraph/source/chain.rb +291 -179
  172. data/lib/solargraph/source/change.rb +82 -79
  173. data/lib/solargraph/source/cursor.rb +166 -164
  174. data/lib/solargraph/source/encoding_fixes.rb +23 -23
  175. data/lib/solargraph/source/source_chainer.rb +194 -191
  176. data/lib/solargraph/source/updater.rb +55 -54
  177. data/lib/solargraph/source.rb +498 -522
  178. data/lib/solargraph/source_map/clip.rb +226 -229
  179. data/lib/solargraph/source_map/data.rb +34 -0
  180. data/lib/solargraph/source_map/mapper.rb +259 -243
  181. data/lib/solargraph/source_map.rb +212 -180
  182. data/lib/solargraph/type_checker/checks.rb +124 -112
  183. data/lib/solargraph/type_checker/param_def.rb +37 -35
  184. data/lib/solargraph/type_checker/problem.rb +32 -32
  185. data/lib/solargraph/type_checker/rules.rb +84 -57
  186. data/lib/solargraph/type_checker.rb +814 -549
  187. data/lib/solargraph/version.rb +5 -5
  188. data/lib/solargraph/views/_method.erb +10 -10
  189. data/lib/solargraph/views/_namespace.erb +3 -3
  190. data/lib/solargraph/views/document.erb +10 -10
  191. data/lib/solargraph/views/environment.erb +3 -5
  192. data/lib/solargraph/workspace/config.rb +255 -231
  193. data/lib/solargraph/workspace/require_paths.rb +97 -0
  194. data/lib/solargraph/workspace.rb +220 -212
  195. data/lib/solargraph/yard_map/cache.rb +6 -0
  196. data/lib/solargraph/yard_map/helpers.rb +44 -16
  197. data/lib/solargraph/yard_map/mapper/to_constant.rb +8 -5
  198. data/lib/solargraph/yard_map/mapper/to_method.rb +130 -81
  199. data/lib/solargraph/yard_map/mapper/to_namespace.rb +31 -27
  200. data/lib/solargraph/yard_map/mapper.rb +79 -77
  201. data/lib/solargraph/yard_map/to_method.rb +89 -79
  202. data/lib/solargraph/yard_map.rb +1 -284
  203. data/lib/solargraph/yard_tags.rb +20 -0
  204. data/lib/solargraph/yardoc.rb +87 -0
  205. data/lib/solargraph.rb +105 -69
  206. data/rbs/fills/bundler/0/bundler.rbs +4271 -0
  207. data/rbs/fills/open3/0/open3.rbs +172 -0
  208. data/rbs/fills/rubygems/0/basic_specification.rbs +326 -0
  209. data/rbs/fills/rubygems/0/errors.rbs +364 -0
  210. data/rbs/fills/rubygems/0/spec_fetcher.rbs +107 -0
  211. data/rbs/fills/rubygems/0/specification.rbs +1753 -0
  212. data/rbs/fills/tuple/tuple.rbs +149 -0
  213. data/rbs/shims/ast/0/node.rbs +5 -0
  214. data/rbs/shims/ast/2.4/.rbs_meta.yaml +9 -0
  215. data/rbs/shims/ast/2.4/ast.rbs +73 -0
  216. data/rbs/shims/parser/3.2.0.1/builders/default.rbs +195 -0
  217. data/rbs/shims/parser/3.2.0.1/manifest.yaml +7 -0
  218. data/rbs/shims/parser/3.2.0.1/parser.rbs +201 -0
  219. data/rbs/shims/parser/3.2.0.1/polyfill.rbs +4 -0
  220. data/rbs/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
  221. data/rbs/shims/thor/1.2.0.1/manifest.yaml +7 -0
  222. data/rbs/shims/thor/1.2.0.1/thor.rbs +17 -0
  223. data/rbs_collection.yaml +19 -0
  224. data/solargraph.gemspec +39 -11
  225. metadata +354 -97
  226. data/lib/.rubocop.yml +0 -22
  227. data/lib/solargraph/api_map/bundler_methods.rb +0 -22
  228. data/lib/solargraph/cache.rb +0 -53
  229. data/lib/solargraph/convention/rspec.rb +0 -30
  230. data/lib/solargraph/documentor.rb +0 -76
  231. data/lib/solargraph/language_server/host/cataloger.rb +0 -56
  232. data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +0 -23
  233. data/lib/solargraph/parser/legacy/node_processors/args_node.rb +0 -35
  234. data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +0 -15
  235. data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +0 -18
  236. data/lib/solargraph/parser/legacy/node_processors.rb +0 -54
  237. data/lib/solargraph/parser/legacy.rb +0 -12
  238. data/lib/solargraph/parser/node_methods.rb +0 -43
  239. data/lib/solargraph/parser/rubyvm/class_methods.rb +0 -149
  240. data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -160
  241. data/lib/solargraph/parser/rubyvm/node_methods.rb +0 -315
  242. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +0 -85
  243. data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +0 -42
  244. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +0 -33
  245. data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +0 -23
  246. data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +0 -75
  247. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +0 -68
  248. data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +0 -23
  249. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +0 -38
  250. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +0 -39
  251. data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +0 -20
  252. data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +0 -27
  253. data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +0 -39
  254. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +0 -26
  255. data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +0 -15
  256. data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +0 -45
  257. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +0 -32
  258. data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +0 -15
  259. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +0 -279
  260. data/lib/solargraph/parser/rubyvm/node_processors.rb +0 -63
  261. data/lib/solargraph/parser/rubyvm/node_wrapper.rb +0 -47
  262. data/lib/solargraph/parser/rubyvm.rb +0 -40
  263. data/lib/solargraph/rbs_map/core_signs.rb +0 -33
  264. data/lib/yard-solargraph.rb +0 -33
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'open3'
4
+
5
+ module Solargraph
6
+ # A workspace consists of the files in a project's directory and the
7
+ # project's configuration. It provides a Source for each file to be used
8
+ # in an associated Library or ApiMap.
9
+ #
10
+ class Workspace
11
+ # Manages determining which gemspecs are available in a workspace
12
+ class RequirePaths
13
+ attr_reader :directory, :config
14
+
15
+ # @param directory [String, nil]
16
+ # @param config [Config, nil]
17
+ def initialize directory, config
18
+ @directory = directory
19
+ @config = config
20
+ end
21
+
22
+ # Generate require paths from gemspecs if they exist or assume the default
23
+ # lib directory.
24
+ #
25
+ # @return [Array<String>]
26
+ def generate
27
+ result = require_paths_from_gemspec_files
28
+ return configured_require_paths if result.empty?
29
+ result.concat(config.require_paths.map { |p| File.join(directory, p) }) if config
30
+ result
31
+ end
32
+
33
+ private
34
+
35
+ # @return [Array<String>]
36
+ def require_paths_from_gemspec_files
37
+ results = []
38
+ gemspec_file_paths.each do |gemspec_file_path|
39
+ results.concat require_path_from_gemspec_file(gemspec_file_path)
40
+ end
41
+ results
42
+ end
43
+
44
+ # Get an array of all gemspec files in the workspace.
45
+ #
46
+ # @return [Array<String>]
47
+ def gemspec_file_paths
48
+ return [] if directory.nil?
49
+ @gemspec_file_paths ||= Dir[File.join(directory, '**/*.gemspec')].select do |gs|
50
+ config.nil? || config.allow?(gs)
51
+ end
52
+ end
53
+
54
+ # Get additional require paths defined in the configuration.
55
+ #
56
+ # @return [Array<String>]
57
+ def configured_require_paths
58
+ return ['lib'] unless directory
59
+ return [File.join(directory, 'lib')] if !config || config.require_paths.empty?
60
+ config.require_paths.map { |p| File.join(directory, p) }
61
+ end
62
+
63
+ # Generate require paths from gemspecs if they exist or assume the default
64
+ # lib directory.
65
+ #
66
+ # @param gemspec_file_path [String]
67
+ # @return [Array<String>]
68
+ def require_path_from_gemspec_file gemspec_file_path
69
+ base = File.dirname(gemspec_file_path)
70
+ # HACK: Evaluating gemspec files violates the goal of not running
71
+ # workspace code, but this is how Gem::Specification.load does it
72
+ # anyway.
73
+ cmd = ['ruby', '-e',
74
+ "require 'rubygems'; " \
75
+ "require 'json'; " \
76
+ "spec = eval(File.read('#{gemspec_file_path}'), TOPLEVEL_BINDING, '#{gemspec_file_path}'); " \
77
+ 'return unless Gem::Specification === spec; ' \
78
+ 'puts({name: spec.name, paths: spec.require_paths}.to_json)']
79
+ o, e, s = Open3.capture3(*cmd)
80
+ if s.success?
81
+ begin
82
+ hash = o && !o.empty? ? JSON.parse(o.split("\n").last) : {}
83
+ return [] if hash.empty?
84
+ hash['paths'].map { |path| File.join(base, path) }
85
+ rescue StandardError => e
86
+ Solargraph.logger.warn "Error reading #{gemspec_file_path}: [#{e.class}] #{e.message}"
87
+ []
88
+ end
89
+ else
90
+ Solargraph.logger.warn "Error reading #{gemspec_file_path}"
91
+ Solargraph.logger.warn e
92
+ []
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -1,212 +1,220 @@
1
- # frozen_string_literal: true
2
-
3
- require 'open3'
4
- require 'rubygems'
5
- require 'json'
6
-
7
- module Solargraph
8
- # A workspace consists of the files in a project's directory and the
9
- # project's configuration. It provides a Source for each file to be used
10
- # in an associated Library or ApiMap.
11
- #
12
- class Workspace
13
- autoload :Config, 'solargraph/workspace/config'
14
-
15
- # @return [String]
16
- attr_reader :directory
17
-
18
- # The require paths associated with the workspace.
19
- #
20
- # @return [Array<String>]
21
- attr_reader :require_paths
22
-
23
- # @return [Array<String>]
24
- attr_reader :gemnames
25
- alias source_gems gemnames
26
-
27
- # @param directory [String]
28
- # @param config [Config, nil]
29
- def initialize directory = '', config = nil
30
- @directory = directory
31
- @config = config
32
- load_sources
33
- @gemnames = []
34
- @require_paths = generate_require_paths
35
- require_plugins
36
- end
37
-
38
- # @return [Solargraph::Workspace::Config]
39
- def config
40
- @config ||= Solargraph::Workspace::Config.new(directory)
41
- end
42
-
43
- # Merge the source. A merge will update the existing source for the file
44
- # or add it to the sources if the workspace is configured to include it.
45
- # The source is ignored if the configuration excludes it.
46
- #
47
- # @param source [Solargraph::Source]
48
- # @return [Boolean] True if the source was added to the workspace
49
- def merge *sources
50
- unless directory == '*' || sources.all? { |source| source_hash.key?(source.filename) }
51
- # Reload the config to determine if a new source should be included
52
- @config = Solargraph::Workspace::Config.new(directory)
53
- end
54
-
55
- includes_any = false
56
- sources.each do |source|
57
- if directory == "*" || config.calculated.include?(source.filename)
58
- source_hash[source.filename] = source
59
- includes_any = true
60
- end
61
- end
62
-
63
- includes_any
64
- end
65
-
66
- # Remove a source from the workspace. The source will not be removed if
67
- # its file exists and the workspace is configured to include it.
68
- #
69
- # @param filename [String]
70
- # @return [Boolean] True if the source was removed from the workspace
71
- def remove filename
72
- return false unless source_hash.key?(filename)
73
- source_hash.delete filename
74
- true
75
- end
76
-
77
- # @return [Array<String>]
78
- def filenames
79
- source_hash.keys
80
- end
81
-
82
- # @return [Array<Solargraph::Source>]
83
- def sources
84
- source_hash.values
85
- end
86
-
87
- # @param filename [String]
88
- # @return [Boolean]
89
- def has_file? filename
90
- source_hash.key?(filename)
91
- end
92
-
93
- # Get a source by its filename.
94
- #
95
- # @param filename [String]
96
- # @return [Solargraph::Source]
97
- def source filename
98
- source_hash[filename]
99
- end
100
-
101
- # True if the path resolves to a file in the workspace's require paths.
102
- #
103
- # @param path [String]
104
- # @return [Boolean]
105
- def would_require? path
106
- require_paths.each do |rp|
107
- return true if File.exist?(File.join(rp, "#{path}.rb"))
108
- end
109
- false
110
- end
111
-
112
- # True if the workspace contains at least one gemspec file.
113
- #
114
- # @return [Boolean]
115
- def gemspec?
116
- !gemspecs.empty?
117
- end
118
-
119
- # Get an array of all gemspec files in the workspace.
120
- #
121
- # @return [Array<String>]
122
- def gemspecs
123
- return [] if directory.empty? || directory == '*'
124
- @gemspecs ||= Dir[File.join(directory, '**/*.gemspec')].select do |gs|
125
- config.allow? gs
126
- end
127
- end
128
-
129
- # Synchronize the workspace from the provided updater.
130
- #
131
- # @param updater [Source::Updater]
132
- # @return [void]
133
- def synchronize! updater
134
- source_hash[updater.filename] = source_hash[updater.filename].synchronize(updater)
135
- end
136
-
137
- private
138
-
139
- # @return [Hash{String => Solargraph::Source}]
140
- def source_hash
141
- @source_hash ||= {}
142
- end
143
-
144
- # @return [void]
145
- def load_sources
146
- source_hash.clear
147
- unless directory.empty? || directory == '*'
148
- size = config.calculated.length
149
- raise WorkspaceTooLargeError, "The workspace is too large to index (#{size} files, #{config.max_files} max)" if config.max_files > 0 and size > config.max_files
150
- config.calculated.each do |filename|
151
- begin
152
- source_hash[filename] = Solargraph::Source.load(filename)
153
- rescue Errno::ENOENT => e
154
- Solargraph.logger.warn("Error loading #{filename}: [#{e.class}] #{e.message}")
155
- end
156
- end
157
- end
158
- end
159
-
160
- # Generate require paths from gemspecs if they exist or assume the default
161
- # lib directory.
162
- #
163
- # @return [Array<String>]
164
- def generate_require_paths
165
- return configured_require_paths unless gemspec?
166
- result = []
167
- gemspecs.each do |file|
168
- base = File.dirname(file)
169
- # HACK: Evaluating gemspec files violates the goal of not running
170
- # workspace code, but this is how Gem::Specification.load does it
171
- # anyway.
172
- cmd = ['ruby', '-e', "require 'rubygems'; require 'json'; spec = eval(File.read('#{file}'), TOPLEVEL_BINDING, '#{file}'); return unless Gem::Specification === spec; puts({name: spec.name, paths: spec.require_paths}.to_json)"]
173
- o, e, s = Open3.capture3(*cmd)
174
- if s.success?
175
- begin
176
- hash = o && !o.empty? ? JSON.parse(o.split("\n").last) : {}
177
- next if hash.empty?
178
- @gemnames.push hash['name']
179
- result.concat(hash['paths'].map { |path| File.join(base, path) })
180
- rescue StandardError => e
181
- Solargraph.logger.warn "Error reading #{file}: [#{e.class}] #{e.message}"
182
- end
183
- else
184
- Solargraph.logger.warn "Error reading #{file}"
185
- Solargraph.logger.warn e
186
- end
187
- end
188
- result.concat(config.require_paths.map { |p| File.join(directory, p) })
189
- result.push File.join(directory, 'lib') if result.empty?
190
- result
191
- end
192
-
193
- # Get additional require paths defined in the configuration.
194
- #
195
- # @return [Array<String>]
196
- def configured_require_paths
197
- return ['lib'] if directory.empty?
198
- return [File.join(directory, 'lib')] if config.require_paths.empty?
199
- config.require_paths.map{|p| File.join(directory, p)}
200
- end
201
-
202
- def require_plugins
203
- config.plugins.each do |plugin|
204
- begin
205
- require plugin
206
- rescue LoadError
207
- Solargraph.logger.warn "Failed to load plugin '#{plugin}'"
208
- end
209
- end
210
- end
211
- end
212
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'open3'
4
+ require 'json'
5
+
6
+ module Solargraph
7
+ # A workspace consists of the files in a project's directory and the
8
+ # project's configuration. It provides a Source for each file to be used
9
+ # in an associated Library or ApiMap.
10
+ #
11
+ class Workspace
12
+ autoload :Config, 'solargraph/workspace/config'
13
+ autoload :RequirePaths, 'solargraph/workspace/require_paths'
14
+
15
+ # @return [String]
16
+ attr_reader :directory
17
+
18
+ # @return [Array<String>]
19
+ attr_reader :gemnames
20
+ alias source_gems gemnames
21
+
22
+ # @param directory [String] TODO: Remove '' and '*' special cases
23
+ # @param config [Config, nil]
24
+ # @param server [Hash]
25
+ def initialize directory = '', config = nil, server = {}
26
+ raise ArgumentError, 'directory must be a String' unless directory.is_a?(String)
27
+
28
+ @directory = if ['*', ''].include?(directory)
29
+ directory
30
+ else
31
+ File.absolute_path(directory)
32
+ end
33
+ @config = config
34
+ @server = server
35
+ load_sources
36
+ @gemnames = []
37
+ require_plugins
38
+ end
39
+
40
+ # The require paths associated with the workspace.
41
+ #
42
+ # @return [Array<String>]
43
+ def require_paths
44
+ # @todo are the semantics of '*' the same as '', meaning 'don't send back any require paths'?
45
+ @require_paths ||= RequirePaths.new(directory_or_nil, config).generate
46
+ end
47
+
48
+ # @return [Solargraph::Workspace::Config]
49
+ def config
50
+ @config ||= Solargraph::Workspace::Config.new(directory)
51
+ end
52
+
53
+ # @param level [Symbol]
54
+ # @return [TypeChecker::Rules]
55
+ def rules(level)
56
+ @rules ||= TypeChecker::Rules.new(level, config.type_checker_rules)
57
+ end
58
+
59
+ # Merge the source. A merge will update the existing source for the file
60
+ # or add it to the sources if the workspace is configured to include it.
61
+ # The source is ignored if the configuration excludes it.
62
+ #
63
+ # @param sources [Array<Solargraph::Source>]
64
+ # @return [Boolean] True if the source was added to the workspace
65
+ def merge *sources
66
+ unless directory == '*' || sources.all? { |source| source_hash.key?(source.filename) }
67
+ # Reload the config to determine if a new source should be included
68
+ @config = Solargraph::Workspace::Config.new(directory)
69
+ end
70
+
71
+ includes_any = false
72
+ sources.each do |source|
73
+ if directory == "*" || config.calculated.include?(source.filename)
74
+ source_hash[source.filename] = source
75
+ includes_any = true
76
+ end
77
+ end
78
+
79
+ includes_any
80
+ end
81
+
82
+ # Remove a source from the workspace. The source will not be removed if
83
+ # its file exists and the workspace is configured to include it.
84
+ #
85
+ # @param filename [String]
86
+ # @return [Boolean] True if the source was removed from the workspace
87
+ def remove filename
88
+ return false unless source_hash.key?(filename)
89
+ source_hash.delete filename
90
+ true
91
+ end
92
+
93
+ # @return [Array<String>]
94
+ def filenames
95
+ source_hash.keys
96
+ end
97
+
98
+ # @return [Array<Solargraph::Source>]
99
+ def sources
100
+ source_hash.values
101
+ end
102
+
103
+ # @param filename [String]
104
+ # @return [Boolean]
105
+ def has_file? filename
106
+ source_hash.key?(filename)
107
+ end
108
+
109
+ # Get a source by its filename.
110
+ #
111
+ # @param filename [String]
112
+ # @return [Solargraph::Source]
113
+ def source filename
114
+ source_hash[filename]
115
+ end
116
+
117
+ # True if the path resolves to a file in the workspace's require paths.
118
+ #
119
+ # @param path [String]
120
+ # @return [Boolean]
121
+ def would_require? path
122
+ require_paths.each do |rp|
123
+ full = File.join rp, path
124
+ return true if File.file?(full) || File.file?(full << ".rb")
125
+ end
126
+ false
127
+ end
128
+
129
+ # @return [String, nil]
130
+ def rbs_collection_path
131
+ @gem_rbs_collection ||= read_rbs_collection_path
132
+ end
133
+
134
+ # @return [String, nil]
135
+ def rbs_collection_config_path
136
+ @rbs_collection_config_path ||= begin
137
+ unless directory.empty? || directory == '*'
138
+ yaml_file = File.join(directory, 'rbs_collection.yaml')
139
+ yaml_file if File.file?(yaml_file)
140
+ end
141
+ end
142
+ end
143
+
144
+ # Synchronize the workspace from the provided updater.
145
+ #
146
+ # @param updater [Source::Updater]
147
+ # @return [void]
148
+ def synchronize! updater
149
+ source_hash[updater.filename] = source_hash[updater.filename].synchronize(updater)
150
+ end
151
+
152
+ # @return [String]
153
+ def command_path
154
+ server['commandPath'] || 'solargraph'
155
+ end
156
+
157
+ # @return [String, nil]
158
+ def directory_or_nil
159
+ return nil if directory.empty? || directory == '*'
160
+ directory
161
+ end
162
+
163
+ # True if the workspace has a root Gemfile.
164
+ #
165
+ # @todo Handle projects with custom Bundler/Gemfile setups (see DocMap#gemspecs_required_from_bundler)
166
+ #
167
+ def gemfile?
168
+ directory && File.file?(File.join(directory, 'Gemfile'))
169
+ end
170
+
171
+ private
172
+
173
+ # The language server configuration (or an empty hash if the workspace was
174
+ # not initialized from a server).
175
+ #
176
+ # @return [Hash]
177
+ attr_reader :server
178
+
179
+ # @return [Hash{String => Solargraph::Source}]
180
+ def source_hash
181
+ @source_hash ||= {}
182
+ end
183
+
184
+ # @return [void]
185
+ def load_sources
186
+ source_hash.clear
187
+ unless directory.empty? || directory == '*'
188
+ size = config.calculated.length
189
+ raise WorkspaceTooLargeError, "The workspace is too large to index (#{size} files, #{config.max_files} max)" if config.max_files > 0 and size > config.max_files
190
+ config.calculated.each do |filename|
191
+ begin
192
+ source_hash[filename] = Solargraph::Source.load(filename)
193
+ rescue Errno::ENOENT => e
194
+ Solargraph.logger.warn("Error loading #{filename}: [#{e.class}] #{e.message}")
195
+ end
196
+ end
197
+ end
198
+ end
199
+
200
+ # @return [void]
201
+ def require_plugins
202
+ config.plugins.each do |plugin|
203
+ begin
204
+ require plugin
205
+ rescue LoadError
206
+ Solargraph.logger.warn "Failed to load plugin '#{plugin}'"
207
+ end
208
+ end
209
+ end
210
+
211
+ # @return [String, nil]
212
+ def read_rbs_collection_path
213
+ return unless rbs_collection_config_path
214
+
215
+ path = YAML.load_file(rbs_collection_config_path)&.fetch('path')
216
+ # make fully qualified
217
+ File.expand_path(path, directory)
218
+ end
219
+ end
220
+ end
@@ -4,13 +4,19 @@ module Solargraph
4
4
  class YardMap
5
5
  class Cache
6
6
  def initialize
7
+ # @type [Hash{String => Array<Solargraph::Pin::Base>}]
7
8
  @path_pins = {}
8
9
  end
9
10
 
11
+ # @param path [String]
12
+ # @param pins [Array<Solargraph::Pin::Base>]
13
+ # @return [Array<Solargraph::Pin::Base>]
10
14
  def set_path_pins path, pins
11
15
  @path_pins[path] = pins
12
16
  end
13
17
 
18
+ # @param path [String]
19
+ # @return [Array<Solargraph::Pin::Base>]
14
20
  def get_path_pins path
15
21
  @path_pins[path]
16
22
  end
@@ -1,16 +1,44 @@
1
- module Solargraph
2
- class YardMap
3
- module Helpers
4
- module_function
5
-
6
- # @param code_object [YARD::CodeObjects::Base]
7
- # @param spec [Gem::Specification]
8
- # @return [Solargraph::Location, nil]
9
- def object_location code_object, spec
10
- return nil if spec.nil? || code_object.nil? || code_object.file.nil? || code_object.line.nil?
11
- file = File.join(spec.full_gem_path, code_object.file)
12
- Solargraph::Location.new(file, Solargraph::Range.from_to(code_object.line - 1, 0, code_object.line - 1, 0))
13
- end
14
- end
15
- end
16
- end
1
+ module Solargraph
2
+ class YardMap
3
+ module Helpers
4
+ module_function
5
+
6
+ # @param code_object [YARD::CodeObjects::Base]
7
+ # @param spec [Gem::Specification, nil]
8
+ # @return [Solargraph::Location, nil]
9
+ def object_location code_object, spec
10
+ if spec.nil? || code_object.nil? || code_object.file.nil? || code_object.line.nil?
11
+ if code_object.namespace.is_a?(YARD::CodeObjects::NamespaceObject)
12
+ # If the code object is a namespace, use the namespace's location
13
+ return object_location(code_object.namespace, spec)
14
+ end
15
+ return Solargraph::Location.new(__FILE__, Solargraph::Range.from_to(__LINE__ - 1, 0, __LINE__ - 1, 0))
16
+ end
17
+ file = File.join(spec.full_gem_path, code_object.file)
18
+ Solargraph::Location.new(file, Solargraph::Range.from_to(code_object.line - 1, 0, code_object.line - 1, 0))
19
+ end
20
+
21
+ # @param code_object [YARD::CodeObjects::Base]
22
+ # @param spec [Gem::Specification, nil]
23
+ # @return [Solargraph::Pin::Namespace]
24
+ def create_closure_namespace_for(code_object, spec)
25
+ code_object_for_location = code_object
26
+ # code_object.namespace is sometimes a YARD proxy object pointing to a method path ("Object#new")
27
+ code_object_for_location = code_object.namespace if code_object.namespace.is_a?(YARD::CodeObjects::NamespaceObject)
28
+ namespace_location = object_location(code_object_for_location, spec)
29
+ ns_name = code_object.namespace.to_s
30
+ if ns_name.empty?
31
+ Solargraph::Pin::ROOT_PIN
32
+ else
33
+ Solargraph::Pin::Namespace.new(
34
+ name: ns_name,
35
+ closure: Pin::ROOT_PIN,
36
+ gates: [code_object.namespace.to_s],
37
+ source: :yardoc,
38
+ location: namespace_location
39
+ )
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -6,17 +6,20 @@ module Solargraph
6
6
  module ToConstant
7
7
  extend YardMap::Helpers
8
8
 
9
+ # @param code_object [YARD::CodeObjects::Base]
10
+ # @param closure [Pin::Closure, nil]
11
+ # @param spec [Gem::Specification, nil]
12
+ # @return [Pin::Constant]
9
13
  def self.make code_object, closure = nil, spec = nil
10
- closure ||= Solargraph::Pin::Namespace.new(
11
- name: code_object.namespace.to_s,
12
- gates: [code_object.namespace.to_s]
13
- )
14
+ closure ||= create_closure_namespace_for(code_object, spec)
15
+
14
16
  Pin::Constant.new(
15
17
  location: object_location(code_object, spec),
16
18
  closure: closure,
17
19
  name: code_object.name.to_s,
18
20
  comments: code_object.docstring ? code_object.docstring.all.to_s : '',
19
- visibility: code_object.visibility
21
+ visibility: code_object.visibility,
22
+ source: :yardoc
20
23
  )
21
24
  end
22
25
  end