solargraph 0.44.2 → 0.46.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 (246) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rspec.yml +41 -0
  3. data/.gitignore +9 -9
  4. data/.rspec +2 -2
  5. data/.travis.yml +19 -19
  6. data/CHANGELOG.md +1115 -1088
  7. data/Gemfile +0 -0
  8. data/LICENSE +0 -0
  9. data/README.md +128 -120
  10. data/Rakefile +0 -0
  11. data/SPONSORS.md +18 -15
  12. data/bin/solargraph +0 -0
  13. data/lib/solargraph/api_map/bundler_methods.rb +22 -22
  14. data/lib/solargraph/api_map/cache.rb +70 -70
  15. data/lib/solargraph/api_map/source_to_yard.rb +81 -81
  16. data/lib/solargraph/api_map/store.rb +256 -256
  17. data/lib/solargraph/api_map.rb +686 -681
  18. data/lib/solargraph/bench.rb +27 -27
  19. data/lib/solargraph/compat.rb +37 -37
  20. data/lib/solargraph/complex_type/type_methods.rb +130 -130
  21. data/lib/solargraph/complex_type/unique_type.rb +75 -75
  22. data/lib/solargraph/complex_type.rb +221 -221
  23. data/lib/solargraph/convention/base.rb +33 -33
  24. data/lib/solargraph/convention/gemfile.rb +15 -15
  25. data/lib/solargraph/convention/gemspec.rb +22 -22
  26. data/lib/solargraph/convention/rspec.rb +30 -21
  27. data/lib/solargraph/convention.rb +47 -47
  28. data/lib/solargraph/converters/dd.rb +12 -12
  29. data/lib/solargraph/converters/dl.rb +12 -12
  30. data/lib/solargraph/converters/dt.rb +12 -12
  31. data/lib/solargraph/converters/misc.rb +1 -1
  32. data/lib/solargraph/diagnostics/base.rb +29 -29
  33. data/lib/solargraph/diagnostics/require_not_found.rb +53 -37
  34. data/lib/solargraph/diagnostics/rubocop.rb +98 -98
  35. data/lib/solargraph/diagnostics/rubocop_helpers.rb +63 -63
  36. data/lib/solargraph/diagnostics/severities.rb +15 -15
  37. data/lib/solargraph/diagnostics/type_check.rb +54 -54
  38. data/lib/solargraph/diagnostics/update_errors.rb +41 -41
  39. data/lib/solargraph/diagnostics.rb +55 -55
  40. data/lib/solargraph/documentor.rb +76 -76
  41. data/lib/solargraph/environ.rb +45 -45
  42. data/lib/solargraph/language_server/completion_item_kinds.rb +35 -35
  43. data/lib/solargraph/language_server/error_codes.rb +20 -20
  44. data/lib/solargraph/language_server/host/cataloger.rb +56 -56
  45. data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
  46. data/lib/solargraph/language_server/host/dispatch.rb +111 -111
  47. data/lib/solargraph/language_server/host/message_worker.rb +59 -59
  48. data/lib/solargraph/language_server/host/sources.rb +156 -156
  49. data/lib/solargraph/language_server/host.rb +865 -865
  50. data/lib/solargraph/language_server/message/base.rb +89 -89
  51. data/lib/solargraph/language_server/message/cancel_request.rb +13 -13
  52. data/lib/solargraph/language_server/message/client/register_capability.rb +15 -15
  53. data/lib/solargraph/language_server/message/client.rb +11 -11
  54. data/lib/solargraph/language_server/message/completion_item/resolve.rb +58 -58
  55. data/lib/solargraph/language_server/message/completion_item.rb +11 -11
  56. data/lib/solargraph/language_server/message/exit_notification.rb +13 -13
  57. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +100 -100
  58. data/lib/solargraph/language_server/message/extended/document.rb +20 -20
  59. data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -32
  60. data/lib/solargraph/language_server/message/extended/download_core.rb +23 -23
  61. data/lib/solargraph/language_server/message/extended/environment.rb +25 -25
  62. data/lib/solargraph/language_server/message/extended/search.rb +20 -20
  63. data/lib/solargraph/language_server/message/extended.rb +21 -21
  64. data/lib/solargraph/language_server/message/initialize.rb +162 -162
  65. data/lib/solargraph/language_server/message/initialized.rb +27 -27
  66. data/lib/solargraph/language_server/message/method_not_found.rb +16 -16
  67. data/lib/solargraph/language_server/message/method_not_implemented.rb +14 -14
  68. data/lib/solargraph/language_server/message/shutdown.rb +13 -13
  69. data/lib/solargraph/language_server/message/text_document/base.rb +19 -19
  70. data/lib/solargraph/language_server/message/text_document/code_action.rb +17 -17
  71. data/lib/solargraph/language_server/message/text_document/completion.rb +59 -59
  72. data/lib/solargraph/language_server/message/text_document/definition.rb +38 -38
  73. data/lib/solargraph/language_server/message/text_document/did_change.rb +15 -15
  74. data/lib/solargraph/language_server/message/text_document/did_close.rb +15 -15
  75. data/lib/solargraph/language_server/message/text_document/did_open.rb +15 -15
  76. data/lib/solargraph/language_server/message/text_document/did_save.rb +17 -17
  77. data/lib/solargraph/language_server/message/text_document/document_highlight.rb +16 -16
  78. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +23 -23
  79. data/lib/solargraph/language_server/message/text_document/folding_range.rb +26 -26
  80. data/lib/solargraph/language_server/message/text_document/formatting.rb +126 -126
  81. data/lib/solargraph/language_server/message/text_document/hover.rb +54 -44
  82. data/lib/solargraph/language_server/message/text_document/on_type_formatting.rb +34 -34
  83. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +11 -11
  84. data/lib/solargraph/language_server/message/text_document/references.rb +16 -16
  85. data/lib/solargraph/language_server/message/text_document/rename.rb +19 -19
  86. data/lib/solargraph/language_server/message/text_document/signature_help.rb +29 -29
  87. data/lib/solargraph/language_server/message/text_document.rb +28 -28
  88. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +30 -30
  89. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +33 -33
  90. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +24 -24
  91. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +23 -23
  92. data/lib/solargraph/language_server/message/workspace.rb +14 -14
  93. data/lib/solargraph/language_server/message.rb +93 -93
  94. data/lib/solargraph/language_server/message_types.rb +14 -14
  95. data/lib/solargraph/language_server/request.rb +24 -24
  96. data/lib/solargraph/language_server/symbol_kinds.rb +36 -36
  97. data/lib/solargraph/language_server/transport/adapter.rb +53 -53
  98. data/lib/solargraph/language_server/transport/data_reader.rb +72 -72
  99. data/lib/solargraph/language_server/transport.rb +13 -13
  100. data/lib/solargraph/language_server/uri_helpers.rb +49 -49
  101. data/lib/solargraph/language_server.rb +19 -19
  102. data/lib/solargraph/library.rb +546 -546
  103. data/lib/solargraph/location.rb +37 -37
  104. data/lib/solargraph/logging.rb +27 -27
  105. data/lib/solargraph/page.rb +83 -83
  106. data/lib/solargraph/parser/comment_ripper.rb +52 -52
  107. data/lib/solargraph/parser/legacy/class_methods.rb +135 -140
  108. data/lib/solargraph/parser/legacy/flawed_builder.rb +16 -16
  109. data/lib/solargraph/parser/legacy/node_chainer.rb +148 -148
  110. data/lib/solargraph/parser/legacy/node_methods.rb +325 -325
  111. data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +23 -23
  112. data/lib/solargraph/parser/legacy/node_processors/args_node.rb +35 -35
  113. data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +15 -15
  114. data/lib/solargraph/parser/legacy/node_processors/block_node.rb +42 -42
  115. data/lib/solargraph/parser/legacy/node_processors/casgn_node.rb +25 -25
  116. data/lib/solargraph/parser/legacy/node_processors/cvasgn_node.rb +23 -23
  117. data/lib/solargraph/parser/legacy/node_processors/def_node.rb +63 -63
  118. data/lib/solargraph/parser/legacy/node_processors/defs_node.rb +36 -36
  119. data/lib/solargraph/parser/legacy/node_processors/gvasgn_node.rb +23 -23
  120. data/lib/solargraph/parser/legacy/node_processors/ivasgn_node.rb +38 -38
  121. data/lib/solargraph/parser/legacy/node_processors/lvasgn_node.rb +28 -28
  122. data/lib/solargraph/parser/legacy/node_processors/namespace_node.rb +39 -39
  123. data/lib/solargraph/parser/legacy/node_processors/orasgn_node.rb +16 -16
  124. data/lib/solargraph/parser/legacy/node_processors/resbody_node.rb +36 -36
  125. data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +21 -21
  126. data/lib/solargraph/parser/legacy/node_processors/send_node.rb +257 -257
  127. data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +18 -18
  128. data/lib/solargraph/parser/legacy/node_processors.rb +54 -54
  129. data/lib/solargraph/parser/legacy.rb +12 -12
  130. data/lib/solargraph/parser/node_methods.rb +43 -43
  131. data/lib/solargraph/parser/node_processor/base.rb +77 -77
  132. data/lib/solargraph/parser/node_processor.rb +43 -43
  133. data/lib/solargraph/parser/region.rb +66 -66
  134. data/lib/solargraph/parser/rubyvm/class_methods.rb +144 -155
  135. data/lib/solargraph/parser/rubyvm/node_chainer.rb +160 -160
  136. data/lib/solargraph/parser/rubyvm/node_methods.rb +315 -315
  137. data/lib/solargraph/parser/rubyvm/node_processors/alias_node.rb +23 -23
  138. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +85 -85
  139. data/lib/solargraph/parser/rubyvm/node_processors/begin_node.rb +15 -15
  140. data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +42 -42
  141. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +22 -22
  142. data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +23 -23
  143. data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +63 -64
  144. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +57 -57
  145. data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +23 -23
  146. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +38 -38
  147. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +39 -39
  148. data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +20 -20
  149. data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +27 -27
  150. data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +39 -39
  151. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +26 -26
  152. data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +15 -15
  153. data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +45 -45
  154. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +21 -21
  155. data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +15 -15
  156. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +277 -277
  157. data/lib/solargraph/parser/rubyvm/node_processors/sym_node.rb +18 -18
  158. data/lib/solargraph/parser/rubyvm/node_processors.rb +63 -62
  159. data/lib/solargraph/parser/rubyvm.rb +40 -40
  160. data/lib/solargraph/parser/snippet.rb +13 -13
  161. data/lib/solargraph/parser.rb +26 -26
  162. data/lib/solargraph/pin/base.rb +296 -296
  163. data/lib/solargraph/pin/base_variable.rb +84 -84
  164. data/lib/solargraph/pin/block.rb +72 -72
  165. data/lib/solargraph/pin/class_variable.rb +8 -8
  166. data/lib/solargraph/pin/closure.rb +37 -37
  167. data/lib/solargraph/pin/common.rb +70 -70
  168. data/lib/solargraph/pin/constant.rb +43 -43
  169. data/lib/solargraph/pin/conversions.rb +96 -96
  170. data/lib/solargraph/pin/documenting.rb +105 -105
  171. data/lib/solargraph/pin/duck_method.rb +16 -16
  172. data/lib/solargraph/pin/global_variable.rb +8 -8
  173. data/lib/solargraph/pin/instance_variable.rb +30 -30
  174. data/lib/solargraph/pin/keyword.rb +15 -15
  175. data/lib/solargraph/pin/keyword_param.rb +8 -8
  176. data/lib/solargraph/pin/local_variable.rb +55 -55
  177. data/lib/solargraph/pin/method.rb +245 -245
  178. data/lib/solargraph/pin/method_alias.rb +31 -31
  179. data/lib/solargraph/pin/namespace.rb +91 -91
  180. data/lib/solargraph/pin/parameter.rb +201 -206
  181. data/lib/solargraph/pin/proxy_type.rb +29 -29
  182. data/lib/solargraph/pin/reference/extend.rb +10 -10
  183. data/lib/solargraph/pin/reference/include.rb +10 -10
  184. data/lib/solargraph/pin/reference/override.rb +29 -29
  185. data/lib/solargraph/pin/reference/prepend.rb +10 -10
  186. data/lib/solargraph/pin/reference/require.rb +14 -14
  187. data/lib/solargraph/pin/reference/superclass.rb +10 -10
  188. data/lib/solargraph/pin/reference.rb +14 -14
  189. data/lib/solargraph/pin/search.rb +56 -0
  190. data/lib/solargraph/pin/singleton.rb +11 -11
  191. data/lib/solargraph/pin/symbol.rb +47 -47
  192. data/lib/solargraph/pin.rb +37 -36
  193. data/lib/solargraph/position.rb +100 -100
  194. data/lib/solargraph/range.rb +95 -95
  195. data/lib/solargraph/server_methods.rb +16 -16
  196. data/lib/solargraph/shell.rb +226 -226
  197. data/lib/solargraph/source/chain/block_variable.rb +13 -13
  198. data/lib/solargraph/source/chain/call.rb +204 -204
  199. data/lib/solargraph/source/chain/class_variable.rb +13 -13
  200. data/lib/solargraph/source/chain/constant.rb +75 -75
  201. data/lib/solargraph/source/chain/global_variable.rb +13 -13
  202. data/lib/solargraph/source/chain/hash.rb +28 -28
  203. data/lib/solargraph/source/chain/head.rb +19 -19
  204. data/lib/solargraph/source/chain/instance_variable.rb +13 -13
  205. data/lib/solargraph/source/chain/link.rb +71 -71
  206. data/lib/solargraph/source/chain/literal.rb +23 -23
  207. data/lib/solargraph/source/chain/or.rb +23 -23
  208. data/lib/solargraph/source/chain/q_call.rb +11 -11
  209. data/lib/solargraph/source/chain/variable.rb +13 -13
  210. data/lib/solargraph/source/chain/z_super.rb +30 -30
  211. data/lib/solargraph/source/chain.rb +164 -164
  212. data/lib/solargraph/source/change.rb +79 -79
  213. data/lib/solargraph/source/cursor.rb +164 -164
  214. data/lib/solargraph/source/source_chainer.rb +191 -191
  215. data/lib/solargraph/source/updater.rb +54 -54
  216. data/lib/solargraph/source.rb +522 -522
  217. data/lib/solargraph/source_map/clip.rb +224 -224
  218. data/lib/solargraph/source_map/completion.rb +23 -23
  219. data/lib/solargraph/source_map/mapper.rb +212 -212
  220. data/lib/solargraph/source_map.rb +180 -189
  221. data/lib/solargraph/type_checker/checks.rb +99 -99
  222. data/lib/solargraph/type_checker/param_def.rb +35 -35
  223. data/lib/solargraph/type_checker/problem.rb +32 -32
  224. data/lib/solargraph/type_checker/rules.rb +57 -57
  225. data/lib/solargraph/type_checker.rb +543 -510
  226. data/lib/solargraph/version.rb +5 -5
  227. data/lib/solargraph/views/environment.erb +58 -58
  228. data/lib/solargraph/workspace/config.rb +231 -231
  229. data/lib/solargraph/workspace.rb +215 -214
  230. data/lib/solargraph/yard_map/cache.rb +19 -19
  231. data/lib/solargraph/yard_map/core_docs.rb +170 -170
  232. data/lib/solargraph/yard_map/core_fills.rb +208 -203
  233. data/lib/solargraph/yard_map/core_gen.rb +76 -76
  234. data/lib/solargraph/yard_map/helpers.rb +16 -16
  235. data/lib/solargraph/yard_map/mapper/to_constant.rb +25 -25
  236. data/lib/solargraph/yard_map/mapper/to_method.rb +78 -78
  237. data/lib/solargraph/yard_map/mapper/to_namespace.rb +27 -27
  238. data/lib/solargraph/yard_map/mapper.rb +77 -77
  239. data/lib/solargraph/yard_map/rdoc_to_yard.rb +140 -140
  240. data/lib/solargraph/yard_map/stdlib_fills.rb +43 -43
  241. data/lib/solargraph/yard_map/to_method.rb +79 -79
  242. data/lib/solargraph/yard_map.rb +460 -443
  243. data/lib/solargraph.rb +69 -69
  244. data/lib/yard-solargraph.rb +33 -33
  245. data/solargraph.gemspec +0 -0
  246. metadata +14 -12
@@ -1,214 +1,215 @@
1
- # frozen_string_literal: true
2
-
3
- require 'open3'
4
- require 'rubygems'
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
-
14
- # @return [String]
15
- attr_reader :directory
16
-
17
- # The require paths associated with the workspace.
18
- #
19
- # @return [Array<String>]
20
- attr_reader :require_paths
21
-
22
- # @return [Array<String>]
23
- attr_reader :gemnames
24
- alias source_gems gemnames
25
-
26
- # @param directory [String]
27
- # @param config [Config, nil]
28
- def initialize directory = '', config = nil
29
- @directory = directory
30
- @config = config
31
- load_sources
32
- @gemnames = []
33
- @require_paths = generate_require_paths
34
- require_plugins
35
- end
36
-
37
- # @return [Solargraph::Workspace::Config]
38
- def config
39
- @config ||= Solargraph::Workspace::Config.new(directory)
40
- end
41
-
42
- # Merge the source. A merge will update the existing source for the file
43
- # or add it to the sources if the workspace is configured to include it.
44
- # The source is ignored if the configuration excludes it.
45
- #
46
- # @param source [Solargraph::Source]
47
- # @return [Boolean] True if the source was added to the workspace
48
- def merge source
49
- unless directory == '*' || source_hash.key?(source.filename)
50
- # Reload the config to determine if a new source should be included
51
- @config = Solargraph::Workspace::Config.new(directory)
52
- return false unless config.calculated.include?(source.filename)
53
- end
54
- source_hash[source.filename] = source
55
- true
56
- end
57
-
58
- # Determine whether a file would be merged into the workspace.
59
- #
60
- # @param filename [String]
61
- # @return [Boolean]
62
- def would_merge? filename
63
- return true if directory == '*' || source_hash.include?(filename)
64
- @config = Solargraph::Workspace::Config.new(directory)
65
- config.calculated.include?(filename)
66
- end
67
-
68
- # Remove a source from the workspace. The source will not be removed if
69
- # its file exists and the workspace is configured to include it.
70
- #
71
- # @param filename [String]
72
- # @return [Boolean] True if the source was removed from the workspace
73
- def remove filename
74
- return false unless source_hash.key?(filename)
75
- source_hash.delete filename
76
- true
77
- end
78
-
79
- # @return [Array<String>]
80
- def filenames
81
- source_hash.keys
82
- end
83
-
84
- # @return [Array<Solargraph::Source>]
85
- def sources
86
- source_hash.values
87
- end
88
-
89
- # @param filename [String]
90
- # @return [Boolean]
91
- def has_file? filename
92
- source_hash.key?(filename)
93
- end
94
-
95
- # Get a source by its filename.
96
- #
97
- # @param filename [String]
98
- # @return [Solargraph::Source]
99
- def source filename
100
- source_hash[filename]
101
- end
102
-
103
- # True if the path resolves to a file in the workspace's require paths.
104
- #
105
- # @param path [String]
106
- # @return [Boolean]
107
- def would_require? path
108
- require_paths.each do |rp|
109
- return true if File.exist?(File.join(rp, "#{path}.rb"))
110
- end
111
- false
112
- end
113
-
114
- # True if the workspace contains at least one gemspec file.
115
- #
116
- # @return [Boolean]
117
- def gemspec?
118
- !gemspecs.empty?
119
- end
120
-
121
- # Get an array of all gemspec files in the workspace.
122
- #
123
- # @return [Array<String>]
124
- def gemspecs
125
- return [] if directory.empty? || directory == '*'
126
- @gemspecs ||= Dir[File.join(directory, '**/*.gemspec')].select do |gs|
127
- config.allow? gs
128
- end
129
- end
130
-
131
- # Synchronize the workspace from the provided updater.
132
- #
133
- # @param updater [Source::Updater]
134
- # @return [void]
135
- def synchronize! updater
136
- source_hash[updater.filename] = source_hash[updater.filename].synchronize(updater)
137
- end
138
-
139
- private
140
-
141
- # @return [Hash{String => Solargraph::Source}]
142
- def source_hash
143
- @source_hash ||= {}
144
- end
145
-
146
- # @return [void]
147
- def load_sources
148
- source_hash.clear
149
- unless directory.empty? || directory == '*'
150
- size = config.calculated.length
151
- 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
152
- config.calculated.each do |filename|
153
- begin
154
- source_hash[filename] = Solargraph::Source.load(filename)
155
- rescue Errno::ENOENT => e
156
- Solargraph.logger.warn("Error loading #{filename}: [#{e.class}] #{e.message}")
157
- end
158
- end
159
- end
160
- end
161
-
162
- # Generate require paths from gemspecs if they exist or assume the default
163
- # lib directory.
164
- #
165
- # @return [Array<String>]
166
- def generate_require_paths
167
- return configured_require_paths unless gemspec?
168
- result = []
169
- gemspecs.each do |file|
170
- base = File.dirname(file)
171
- # HACK: Evaluating gemspec files violates the goal of not running
172
- # workspace code, but this is how Gem::Specification.load does it
173
- # anyway.
174
- 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)"]
175
- o, e, s = Open3.capture3(*cmd)
176
- if s.success?
177
- begin
178
- hash = o && !o.empty? ? JSON.parse(o.split("\n").last) : {}
179
- next if hash.empty?
180
- @gemnames.push hash['name']
181
- result.concat(hash['paths'].map { |path| File.join(base, path) })
182
- rescue StandardError => e
183
- Solargraph.logger.warn "Error reading #{file}: [#{e.class}] #{e.message}"
184
- end
185
- else
186
- Solargraph.logger.warn "Error reading #{file}"
187
- Solargraph.logger.warn e
188
- end
189
- end
190
- result.concat(config.require_paths.map { |p| File.join(directory, p) })
191
- result.push File.join(directory, 'lib') if result.empty?
192
- result
193
- end
194
-
195
- # Get additional require paths defined in the configuration.
196
- #
197
- # @return [Array<String>]
198
- def configured_require_paths
199
- return ['lib'] if directory.empty?
200
- return [File.join(directory, 'lib')] if config.require_paths.empty?
201
- config.require_paths.map{|p| File.join(directory, p)}
202
- end
203
-
204
- def require_plugins
205
- config.plugins.each do |plugin|
206
- begin
207
- require plugin
208
- rescue LoadError
209
- Solargraph.logger.warn "Failed to load plugin '#{plugin}'"
210
- end
211
- end
212
- end
213
- end
214
- end
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 source
50
+ unless directory == '*' || 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
+ return false unless config.calculated.include?(source.filename)
54
+ end
55
+ source_hash[source.filename] = source
56
+ true
57
+ end
58
+
59
+ # Determine whether a file would be merged into the workspace.
60
+ #
61
+ # @param filename [String]
62
+ # @return [Boolean]
63
+ def would_merge? filename
64
+ return true if directory == '*' || source_hash.include?(filename)
65
+ @config = Solargraph::Workspace::Config.new(directory)
66
+ config.calculated.include?(filename)
67
+ end
68
+
69
+ # Remove a source from the workspace. The source will not be removed if
70
+ # its file exists and the workspace is configured to include it.
71
+ #
72
+ # @param filename [String]
73
+ # @return [Boolean] True if the source was removed from the workspace
74
+ def remove filename
75
+ return false unless source_hash.key?(filename)
76
+ source_hash.delete filename
77
+ true
78
+ end
79
+
80
+ # @return [Array<String>]
81
+ def filenames
82
+ source_hash.keys
83
+ end
84
+
85
+ # @return [Array<Solargraph::Source>]
86
+ def sources
87
+ source_hash.values
88
+ end
89
+
90
+ # @param filename [String]
91
+ # @return [Boolean]
92
+ def has_file? filename
93
+ source_hash.key?(filename)
94
+ end
95
+
96
+ # Get a source by its filename.
97
+ #
98
+ # @param filename [String]
99
+ # @return [Solargraph::Source]
100
+ def source filename
101
+ source_hash[filename]
102
+ end
103
+
104
+ # True if the path resolves to a file in the workspace's require paths.
105
+ #
106
+ # @param path [String]
107
+ # @return [Boolean]
108
+ def would_require? path
109
+ require_paths.each do |rp|
110
+ return true if File.exist?(File.join(rp, "#{path}.rb"))
111
+ end
112
+ false
113
+ end
114
+
115
+ # True if the workspace contains at least one gemspec file.
116
+ #
117
+ # @return [Boolean]
118
+ def gemspec?
119
+ !gemspecs.empty?
120
+ end
121
+
122
+ # Get an array of all gemspec files in the workspace.
123
+ #
124
+ # @return [Array<String>]
125
+ def gemspecs
126
+ return [] if directory.empty? || directory == '*'
127
+ @gemspecs ||= Dir[File.join(directory, '**/*.gemspec')].select do |gs|
128
+ config.allow? gs
129
+ end
130
+ end
131
+
132
+ # Synchronize the workspace from the provided updater.
133
+ #
134
+ # @param updater [Source::Updater]
135
+ # @return [void]
136
+ def synchronize! updater
137
+ source_hash[updater.filename] = source_hash[updater.filename].synchronize(updater)
138
+ end
139
+
140
+ private
141
+
142
+ # @return [Hash{String => Solargraph::Source}]
143
+ def source_hash
144
+ @source_hash ||= {}
145
+ end
146
+
147
+ # @return [void]
148
+ def load_sources
149
+ source_hash.clear
150
+ unless directory.empty? || directory == '*'
151
+ size = config.calculated.length
152
+ 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
153
+ config.calculated.each do |filename|
154
+ begin
155
+ source_hash[filename] = Solargraph::Source.load(filename)
156
+ rescue Errno::ENOENT => e
157
+ Solargraph.logger.warn("Error loading #{filename}: [#{e.class}] #{e.message}")
158
+ end
159
+ end
160
+ end
161
+ end
162
+
163
+ # Generate require paths from gemspecs if they exist or assume the default
164
+ # lib directory.
165
+ #
166
+ # @return [Array<String>]
167
+ def generate_require_paths
168
+ return configured_require_paths unless gemspec?
169
+ result = []
170
+ gemspecs.each do |file|
171
+ base = File.dirname(file)
172
+ # HACK: Evaluating gemspec files violates the goal of not running
173
+ # workspace code, but this is how Gem::Specification.load does it
174
+ # anyway.
175
+ 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)"]
176
+ o, e, s = Open3.capture3(*cmd)
177
+ if s.success?
178
+ begin
179
+ hash = o && !o.empty? ? JSON.parse(o.split("\n").last) : {}
180
+ next if hash.empty?
181
+ @gemnames.push hash['name']
182
+ result.concat(hash['paths'].map { |path| File.join(base, path) })
183
+ rescue StandardError => e
184
+ Solargraph.logger.warn "Error reading #{file}: [#{e.class}] #{e.message}"
185
+ end
186
+ else
187
+ Solargraph.logger.warn "Error reading #{file}"
188
+ Solargraph.logger.warn e
189
+ end
190
+ end
191
+ result.concat(config.require_paths.map { |p| File.join(directory, p) })
192
+ result.push File.join(directory, 'lib') if result.empty?
193
+ result
194
+ end
195
+
196
+ # Get additional require paths defined in the configuration.
197
+ #
198
+ # @return [Array<String>]
199
+ def configured_require_paths
200
+ return ['lib'] if directory.empty?
201
+ return [File.join(directory, 'lib')] if config.require_paths.empty?
202
+ config.require_paths.map{|p| File.join(directory, p)}
203
+ end
204
+
205
+ def require_plugins
206
+ config.plugins.each do |plugin|
207
+ begin
208
+ require plugin
209
+ rescue LoadError
210
+ Solargraph.logger.warn "Failed to load plugin '#{plugin}'"
211
+ end
212
+ end
213
+ end
214
+ end
215
+ end
@@ -1,19 +1,19 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- class YardMap
5
- class Cache
6
- def initialize
7
- @path_pins = {}
8
- end
9
-
10
- def set_path_pins path, pins
11
- @path_pins[path] = pins
12
- end
13
-
14
- def get_path_pins path
15
- @path_pins[path]
16
- end
17
- end
18
- end
19
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ class YardMap
5
+ class Cache
6
+ def initialize
7
+ @path_pins = {}
8
+ end
9
+
10
+ def set_path_pins path, pins
11
+ @path_pins[path] = pins
12
+ end
13
+
14
+ def get_path_pins path
15
+ @path_pins[path]
16
+ end
17
+ end
18
+ end
19
+ end