solargraph 0.46.0 → 0.47.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 (246) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rspec.yml +41 -41
  3. data/.gitignore +9 -9
  4. data/.rspec +2 -2
  5. data/.travis.yml +19 -19
  6. data/CHANGELOG.md +1130 -1115
  7. data/Gemfile +0 -0
  8. data/LICENSE +0 -0
  9. data/README.md +128 -128
  10. data/Rakefile +0 -0
  11. data/SPONSORS.md +17 -18
  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 -686
  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 +225 -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 -30
  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 -53
  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 +56 -54
  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 -135
  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 -144
  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 -63
  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 -63
  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 +73 -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 -201
  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 -56
  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 -37
  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 +239 -212
  220. data/lib/solargraph/source_map.rb +180 -180
  221. data/lib/solargraph/type_checker/checks.rb +112 -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 -543
  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 -215
  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 -208
  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 -460
  243. data/lib/solargraph.rb +69 -69
  244. data/lib/yard-solargraph.rb +33 -33
  245. data/solargraph.gemspec +0 -0
  246. metadata +12 -12
@@ -1,215 +1,215 @@
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
+ # 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