jimeh-solargraph 0.40.4.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 (252) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ci.yml +54 -0
  3. data/.gitignore +9 -0
  4. data/.rspec +2 -0
  5. data/.travis.yml +24 -0
  6. data/.yardopts +2 -0
  7. data/CHANGELOG.md +1003 -0
  8. data/Gemfile +7 -0
  9. data/LICENSE +21 -0
  10. data/README.md +123 -0
  11. data/Rakefile +25 -0
  12. data/SPONSORS.md +15 -0
  13. data/bin/solargraph +5 -0
  14. data/jimeh-solargraph.gemspec +44 -0
  15. data/lib/.rubocop.yml +21 -0
  16. data/lib/solargraph.rb +67 -0
  17. data/lib/solargraph/api_map.rb +752 -0
  18. data/lib/solargraph/api_map/bundler_methods.rb +27 -0
  19. data/lib/solargraph/api_map/cache.rb +70 -0
  20. data/lib/solargraph/api_map/source_to_yard.rb +81 -0
  21. data/lib/solargraph/api_map/store.rb +256 -0
  22. data/lib/solargraph/bench.rb +30 -0
  23. data/lib/solargraph/compat.rb +23 -0
  24. data/lib/solargraph/complex_type.rb +213 -0
  25. data/lib/solargraph/complex_type/type_methods.rb +127 -0
  26. data/lib/solargraph/complex_type/unique_type.rb +75 -0
  27. data/lib/solargraph/convention.rb +47 -0
  28. data/lib/solargraph/convention/base.rb +33 -0
  29. data/lib/solargraph/convention/gemfile.rb +15 -0
  30. data/lib/solargraph/convention/gemspec.rb +22 -0
  31. data/lib/solargraph/convention/rspec.rb +21 -0
  32. data/lib/solargraph/converters/dd.rb +12 -0
  33. data/lib/solargraph/converters/dl.rb +12 -0
  34. data/lib/solargraph/converters/dt.rb +12 -0
  35. data/lib/solargraph/converters/misc.rb +1 -0
  36. data/lib/solargraph/diagnostics.rb +55 -0
  37. data/lib/solargraph/diagnostics/base.rb +29 -0
  38. data/lib/solargraph/diagnostics/require_not_found.rb +37 -0
  39. data/lib/solargraph/diagnostics/rubocop.rb +90 -0
  40. data/lib/solargraph/diagnostics/rubocop_helpers.rb +45 -0
  41. data/lib/solargraph/diagnostics/severities.rb +15 -0
  42. data/lib/solargraph/diagnostics/type_check.rb +54 -0
  43. data/lib/solargraph/diagnostics/update_errors.rb +41 -0
  44. data/lib/solargraph/documentor.rb +78 -0
  45. data/lib/solargraph/environ.rb +45 -0
  46. data/lib/solargraph/language_server.rb +19 -0
  47. data/lib/solargraph/language_server/completion_item_kinds.rb +35 -0
  48. data/lib/solargraph/language_server/error_codes.rb +20 -0
  49. data/lib/solargraph/language_server/host.rb +746 -0
  50. data/lib/solargraph/language_server/host/cataloger.rb +56 -0
  51. data/lib/solargraph/language_server/host/diagnoser.rb +81 -0
  52. data/lib/solargraph/language_server/host/dispatch.rb +112 -0
  53. data/lib/solargraph/language_server/host/sources.rb +156 -0
  54. data/lib/solargraph/language_server/message.rb +92 -0
  55. data/lib/solargraph/language_server/message/base.rb +85 -0
  56. data/lib/solargraph/language_server/message/cancel_request.rb +13 -0
  57. data/lib/solargraph/language_server/message/client.rb +11 -0
  58. data/lib/solargraph/language_server/message/client/register_capability.rb +15 -0
  59. data/lib/solargraph/language_server/message/completion_item.rb +11 -0
  60. data/lib/solargraph/language_server/message/completion_item/resolve.rb +57 -0
  61. data/lib/solargraph/language_server/message/exit_notification.rb +13 -0
  62. data/lib/solargraph/language_server/message/extended.rb +21 -0
  63. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +100 -0
  64. data/lib/solargraph/language_server/message/extended/document.rb +20 -0
  65. data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -0
  66. data/lib/solargraph/language_server/message/extended/download_core.rb +23 -0
  67. data/lib/solargraph/language_server/message/extended/environment.rb +25 -0
  68. data/lib/solargraph/language_server/message/extended/search.rb +20 -0
  69. data/lib/solargraph/language_server/message/initialize.rb +153 -0
  70. data/lib/solargraph/language_server/message/initialized.rb +26 -0
  71. data/lib/solargraph/language_server/message/method_not_found.rb +16 -0
  72. data/lib/solargraph/language_server/message/method_not_implemented.rb +14 -0
  73. data/lib/solargraph/language_server/message/shutdown.rb +13 -0
  74. data/lib/solargraph/language_server/message/text_document.rb +28 -0
  75. data/lib/solargraph/language_server/message/text_document/base.rb +19 -0
  76. data/lib/solargraph/language_server/message/text_document/code_action.rb +17 -0
  77. data/lib/solargraph/language_server/message/text_document/completion.rb +57 -0
  78. data/lib/solargraph/language_server/message/text_document/definition.rb +38 -0
  79. data/lib/solargraph/language_server/message/text_document/did_change.rb +15 -0
  80. data/lib/solargraph/language_server/message/text_document/did_close.rb +15 -0
  81. data/lib/solargraph/language_server/message/text_document/did_open.rb +15 -0
  82. data/lib/solargraph/language_server/message/text_document/did_save.rb +17 -0
  83. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +23 -0
  84. data/lib/solargraph/language_server/message/text_document/folding_range.rb +26 -0
  85. data/lib/solargraph/language_server/message/text_document/formatting.rb +105 -0
  86. data/lib/solargraph/language_server/message/text_document/hover.rb +44 -0
  87. data/lib/solargraph/language_server/message/text_document/on_type_formatting.rb +34 -0
  88. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +11 -0
  89. data/lib/solargraph/language_server/message/text_document/references.rb +16 -0
  90. data/lib/solargraph/language_server/message/text_document/rename.rb +19 -0
  91. data/lib/solargraph/language_server/message/text_document/signature_help.rb +29 -0
  92. data/lib/solargraph/language_server/message/workspace.rb +14 -0
  93. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +29 -0
  94. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +33 -0
  95. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +24 -0
  96. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +23 -0
  97. data/lib/solargraph/language_server/message_types.rb +14 -0
  98. data/lib/solargraph/language_server/request.rb +24 -0
  99. data/lib/solargraph/language_server/symbol_kinds.rb +36 -0
  100. data/lib/solargraph/language_server/transport.rb +13 -0
  101. data/lib/solargraph/language_server/transport/adapter.rb +56 -0
  102. data/lib/solargraph/language_server/transport/data_reader.rb +72 -0
  103. data/lib/solargraph/language_server/uri_helpers.rb +49 -0
  104. data/lib/solargraph/library.rb +426 -0
  105. data/lib/solargraph/location.rb +37 -0
  106. data/lib/solargraph/logging.rb +27 -0
  107. data/lib/solargraph/page.rb +83 -0
  108. data/lib/solargraph/parser.rb +26 -0
  109. data/lib/solargraph/parser/comment_ripper.rb +52 -0
  110. data/lib/solargraph/parser/legacy.rb +12 -0
  111. data/lib/solargraph/parser/legacy/class_methods.rb +109 -0
  112. data/lib/solargraph/parser/legacy/flawed_builder.rb +16 -0
  113. data/lib/solargraph/parser/legacy/node_chainer.rb +118 -0
  114. data/lib/solargraph/parser/legacy/node_methods.rb +311 -0
  115. data/lib/solargraph/parser/legacy/node_processors.rb +54 -0
  116. data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +23 -0
  117. data/lib/solargraph/parser/legacy/node_processors/args_node.rb +35 -0
  118. data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +15 -0
  119. data/lib/solargraph/parser/legacy/node_processors/block_node.rb +22 -0
  120. data/lib/solargraph/parser/legacy/node_processors/casgn_node.rb +25 -0
  121. data/lib/solargraph/parser/legacy/node_processors/cvasgn_node.rb +23 -0
  122. data/lib/solargraph/parser/legacy/node_processors/def_node.rb +63 -0
  123. data/lib/solargraph/parser/legacy/node_processors/defs_node.rb +36 -0
  124. data/lib/solargraph/parser/legacy/node_processors/gvasgn_node.rb +23 -0
  125. data/lib/solargraph/parser/legacy/node_processors/ivasgn_node.rb +38 -0
  126. data/lib/solargraph/parser/legacy/node_processors/lvasgn_node.rb +28 -0
  127. data/lib/solargraph/parser/legacy/node_processors/namespace_node.rb +39 -0
  128. data/lib/solargraph/parser/legacy/node_processors/orasgn_node.rb +16 -0
  129. data/lib/solargraph/parser/legacy/node_processors/resbody_node.rb +36 -0
  130. data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +21 -0
  131. data/lib/solargraph/parser/legacy/node_processors/send_node.rb +257 -0
  132. data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +18 -0
  133. data/lib/solargraph/parser/node_methods.rb +43 -0
  134. data/lib/solargraph/parser/node_processor.rb +43 -0
  135. data/lib/solargraph/parser/node_processor/base.rb +80 -0
  136. data/lib/solargraph/parser/region.rb +66 -0
  137. data/lib/solargraph/parser/rubyvm.rb +40 -0
  138. data/lib/solargraph/parser/rubyvm/class_methods.rb +150 -0
  139. data/lib/solargraph/parser/rubyvm/node_chainer.rb +135 -0
  140. data/lib/solargraph/parser/rubyvm/node_methods.rb +301 -0
  141. data/lib/solargraph/parser/rubyvm/node_processors.rb +62 -0
  142. data/lib/solargraph/parser/rubyvm/node_processors/alias_node.rb +23 -0
  143. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +86 -0
  144. data/lib/solargraph/parser/rubyvm/node_processors/begin_node.rb +15 -0
  145. data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +22 -0
  146. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +22 -0
  147. data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +23 -0
  148. data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +64 -0
  149. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +57 -0
  150. data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +23 -0
  151. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +38 -0
  152. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +39 -0
  153. data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +20 -0
  154. data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +27 -0
  155. data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +39 -0
  156. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +26 -0
  157. data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +15 -0
  158. data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +45 -0
  159. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +21 -0
  160. data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +15 -0
  161. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +277 -0
  162. data/lib/solargraph/parser/rubyvm/node_processors/sym_node.rb +18 -0
  163. data/lib/solargraph/parser/snippet.rb +13 -0
  164. data/lib/solargraph/pin.rb +36 -0
  165. data/lib/solargraph/pin/base.rb +296 -0
  166. data/lib/solargraph/pin/base_variable.rb +84 -0
  167. data/lib/solargraph/pin/block.rb +62 -0
  168. data/lib/solargraph/pin/class_variable.rb +8 -0
  169. data/lib/solargraph/pin/closure.rb +37 -0
  170. data/lib/solargraph/pin/common.rb +70 -0
  171. data/lib/solargraph/pin/constant.rb +43 -0
  172. data/lib/solargraph/pin/conversions.rb +96 -0
  173. data/lib/solargraph/pin/documenting.rb +105 -0
  174. data/lib/solargraph/pin/duck_method.rb +16 -0
  175. data/lib/solargraph/pin/global_variable.rb +8 -0
  176. data/lib/solargraph/pin/instance_variable.rb +30 -0
  177. data/lib/solargraph/pin/keyword.rb +15 -0
  178. data/lib/solargraph/pin/keyword_param.rb +8 -0
  179. data/lib/solargraph/pin/local_variable.rb +21 -0
  180. data/lib/solargraph/pin/localized.rb +43 -0
  181. data/lib/solargraph/pin/method.rb +245 -0
  182. data/lib/solargraph/pin/method_alias.rb +31 -0
  183. data/lib/solargraph/pin/namespace.rb +85 -0
  184. data/lib/solargraph/pin/parameter.rb +206 -0
  185. data/lib/solargraph/pin/proxy_type.rb +29 -0
  186. data/lib/solargraph/pin/reference.rb +14 -0
  187. data/lib/solargraph/pin/reference/extend.rb +10 -0
  188. data/lib/solargraph/pin/reference/include.rb +10 -0
  189. data/lib/solargraph/pin/reference/override.rb +29 -0
  190. data/lib/solargraph/pin/reference/prepend.rb +10 -0
  191. data/lib/solargraph/pin/reference/require.rb +14 -0
  192. data/lib/solargraph/pin/reference/superclass.rb +10 -0
  193. data/lib/solargraph/pin/singleton.rb +11 -0
  194. data/lib/solargraph/pin/symbol.rb +47 -0
  195. data/lib/solargraph/position.rb +100 -0
  196. data/lib/solargraph/range.rb +95 -0
  197. data/lib/solargraph/server_methods.rb +16 -0
  198. data/lib/solargraph/shell.rb +222 -0
  199. data/lib/solargraph/source.rb +537 -0
  200. data/lib/solargraph/source/chain.rb +154 -0
  201. data/lib/solargraph/source/chain/block_variable.rb +13 -0
  202. data/lib/solargraph/source/chain/call.rb +203 -0
  203. data/lib/solargraph/source/chain/class_variable.rb +13 -0
  204. data/lib/solargraph/source/chain/constant.rb +75 -0
  205. data/lib/solargraph/source/chain/global_variable.rb +13 -0
  206. data/lib/solargraph/source/chain/head.rb +35 -0
  207. data/lib/solargraph/source/chain/instance_variable.rb +13 -0
  208. data/lib/solargraph/source/chain/link.rb +67 -0
  209. data/lib/solargraph/source/chain/literal.rb +23 -0
  210. data/lib/solargraph/source/chain/or.rb +23 -0
  211. data/lib/solargraph/source/chain/variable.rb +13 -0
  212. data/lib/solargraph/source/chain/z_super.rb +30 -0
  213. data/lib/solargraph/source/change.rb +79 -0
  214. data/lib/solargraph/source/cursor.rb +164 -0
  215. data/lib/solargraph/source/encoding_fixes.rb +23 -0
  216. data/lib/solargraph/source/source_chainer.rb +190 -0
  217. data/lib/solargraph/source/updater.rb +54 -0
  218. data/lib/solargraph/source_map.rb +188 -0
  219. data/lib/solargraph/source_map/clip.rb +224 -0
  220. data/lib/solargraph/source_map/completion.rb +23 -0
  221. data/lib/solargraph/source_map/mapper.rb +215 -0
  222. data/lib/solargraph/type_checker.rb +503 -0
  223. data/lib/solargraph/type_checker/checks.rb +99 -0
  224. data/lib/solargraph/type_checker/param_def.rb +35 -0
  225. data/lib/solargraph/type_checker/problem.rb +32 -0
  226. data/lib/solargraph/type_checker/rules.rb +57 -0
  227. data/lib/solargraph/version.rb +5 -0
  228. data/lib/solargraph/views/_method.erb +62 -0
  229. data/lib/solargraph/views/_name_type_tag.erb +10 -0
  230. data/lib/solargraph/views/_namespace.erb +24 -0
  231. data/lib/solargraph/views/document.erb +23 -0
  232. data/lib/solargraph/views/environment.erb +58 -0
  233. data/lib/solargraph/views/layout.erb +44 -0
  234. data/lib/solargraph/views/search.erb +11 -0
  235. data/lib/solargraph/workspace.rb +209 -0
  236. data/lib/solargraph/workspace/config.rb +230 -0
  237. data/lib/solargraph/yard_map.rb +435 -0
  238. data/lib/solargraph/yard_map/cache.rb +19 -0
  239. data/lib/solargraph/yard_map/core_docs.rb +170 -0
  240. data/lib/solargraph/yard_map/core_fills.rb +185 -0
  241. data/lib/solargraph/yard_map/core_gen.rb +76 -0
  242. data/lib/solargraph/yard_map/helpers.rb +16 -0
  243. data/lib/solargraph/yard_map/mapper.rb +77 -0
  244. data/lib/solargraph/yard_map/mapper/to_constant.rb +25 -0
  245. data/lib/solargraph/yard_map/mapper/to_method.rb +78 -0
  246. data/lib/solargraph/yard_map/mapper/to_namespace.rb +27 -0
  247. data/lib/solargraph/yard_map/rdoc_to_yard.rb +140 -0
  248. data/lib/solargraph/yard_map/stdlib_fills.rb +43 -0
  249. data/lib/solargraph/yard_map/to_method.rb +79 -0
  250. data/lib/yard-solargraph.rb +30 -0
  251. data/yardoc/2.2.2.tar.gz +0 -0
  252. metadata +564 -0
@@ -0,0 +1,11 @@
1
+ <h1>Search Results for <kbd><%= query %></kbd></h1>
2
+
3
+ <% unless results.empty? %>
4
+ <ul class="doc-list">
5
+ <% results.each do |result| %>
6
+ <li>
7
+ <a href="solargraph:/document?query=<%= CGI.escape(result) %>"><%= result %></a>
8
+ </li>
9
+ <% end %>
10
+ </ul>
11
+ <% end %>
@@ -0,0 +1,209 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ # A workspace consists of the files in a project's directory and the
5
+ # project's configuration. It provides a Source for each file to be used
6
+ # in an associated Library or ApiMap.
7
+ #
8
+ class Workspace
9
+ autoload :Config, 'solargraph/workspace/config'
10
+
11
+ # @return [String]
12
+ attr_reader :directory
13
+
14
+ # The require paths associated with the workspace.
15
+ #
16
+ # @return [Array<String>]
17
+ attr_reader :require_paths
18
+
19
+ # @return [Array<String>]
20
+ attr_reader :gemnames
21
+
22
+ # @param directory [String]
23
+ # @param config [Config, nil]
24
+ def initialize directory = '', config = nil
25
+ @directory = directory
26
+ @config = config
27
+ load_sources
28
+ @gemnames = []
29
+ @require_paths = generate_require_paths
30
+ require_plugins
31
+ end
32
+
33
+ # @return [Solargraph::Workspace::Config]
34
+ def config
35
+ @config ||= Solargraph::Workspace::Config.new(directory)
36
+ end
37
+
38
+ # Merge the source. A merge will update the existing source for the file
39
+ # or add it to the sources if the workspace is configured to include it.
40
+ # The source is ignored if the configuration excludes it.
41
+ #
42
+ # @param source [Solargraph::Source]
43
+ # @return [Boolean] True if the source was added to the workspace
44
+ def merge source
45
+ unless directory == '*' || source_hash.key?(source.filename)
46
+ # Reload the config to determine if a new source should be included
47
+ @config = Solargraph::Workspace::Config.new(directory)
48
+ return false unless config.calculated.include?(source.filename)
49
+ end
50
+ source_hash[source.filename] = source
51
+ true
52
+ end
53
+
54
+ # Determine whether a file would be merged into the workspace.
55
+ #
56
+ # @param filename [String]
57
+ # @return [Boolean]
58
+ def would_merge? filename
59
+ return true if directory == '*' || source_hash.include?(filename)
60
+ @config = Solargraph::Workspace::Config.new(directory)
61
+ config.calculated.include?(filename)
62
+ end
63
+
64
+ # Remove a source from the workspace. The source will not be removed if
65
+ # its file exists and the workspace is configured to include it.
66
+ #
67
+ # @param filename [String]
68
+ # @return [Boolean] True if the source was removed from the workspace
69
+ def remove filename
70
+ return false unless source_hash.key?(filename)
71
+ source_hash.delete filename
72
+ true
73
+ end
74
+
75
+ # @return [Array<String>]
76
+ def filenames
77
+ source_hash.keys
78
+ end
79
+
80
+ # @return [Array<Solargraph::Source>]
81
+ def sources
82
+ source_hash.values
83
+ end
84
+
85
+ # @param filename [String]
86
+ # @return [Boolean]
87
+ def has_file? filename
88
+ source_hash.key?(filename)
89
+ end
90
+
91
+ # Get a source by its filename.
92
+ #
93
+ # @param filename [String]
94
+ # @return [Solargraph::Source]
95
+ def source filename
96
+ source_hash[filename]
97
+ end
98
+
99
+ # True if the path resolves to a file in the workspace's require paths.
100
+ #
101
+ # @param path [String]
102
+ # @return [Boolean]
103
+ def would_require? path
104
+ require_paths.each do |rp|
105
+ return true if File.exist?(File.join(rp, "#{path}.rb"))
106
+ end
107
+ false
108
+ end
109
+
110
+ # True if the workspace contains at least one gemspec file.
111
+ #
112
+ # @return [Boolean]
113
+ def gemspec?
114
+ !gemspecs.empty?
115
+ end
116
+
117
+ # Get an array of all gemspec files in the workspace.
118
+ #
119
+ # @return [Array<String>]
120
+ def gemspecs
121
+ return [] if directory.empty? || directory == '*'
122
+ @gemspecs ||= Dir[File.join(directory, '**/*.gemspec')].select do |gs|
123
+ config.allow? gs
124
+ end
125
+ end
126
+
127
+ # Synchronize the workspace from the provided updater.
128
+ #
129
+ # @param updater [Source::Updater]
130
+ # @return [void]
131
+ def synchronize! updater
132
+ source_hash[updater.filename] = source_hash[updater.filename].synchronize(updater)
133
+ end
134
+
135
+ private
136
+
137
+ # @return [Hash{String => Solargraph::Source}]
138
+ def source_hash
139
+ @source_hash ||= {}
140
+ end
141
+
142
+ # @return [void]
143
+ def load_sources
144
+ source_hash.clear
145
+ unless directory.empty? || directory == '*'
146
+ size = config.calculated.length
147
+ 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
148
+ config.calculated.each do |filename|
149
+ begin
150
+ source_hash[filename] = Solargraph::Source.load(filename)
151
+ rescue Errno::ENOENT => e
152
+ Solargraph.logger.warn("Error loading #{filename}: [#{e.class}] #{e.message}")
153
+ end
154
+ end
155
+ end
156
+ end
157
+
158
+ # Generate require paths from gemspecs if they exist or assume the default
159
+ # lib directory.
160
+ #
161
+ # @return [Array<String>]
162
+ def generate_require_paths
163
+ return configured_require_paths unless gemspec?
164
+ result = []
165
+ gemspecs.each do |file|
166
+ base = File.dirname(file)
167
+ # HACK: Evaluating gemspec files violates the goal of not running
168
+ # workspace code, but this is how Gem::Specification.load does it
169
+ # anyway.
170
+ Dir.chdir base do
171
+ begin
172
+ # @type [Gem::Specification]
173
+ spec = eval(File.read(file), TOPLEVEL_BINDING, file)
174
+ next unless Gem::Specification === spec
175
+ @gemnames.push spec.name
176
+ result.concat(spec.require_paths.map { |path| File.join(base, path) })
177
+ rescue RuntimeError, ScriptError, Errno::ENOENT => e
178
+ # Don't die if we have an error during eval-ing a gem spec.
179
+ # Concat the default lib directory instead.
180
+ Solargraph.logger.warn "Error reading #{file}: [#{e.class}] #{e.message}"
181
+ result.push File.join(base, 'lib')
182
+ end
183
+ end
184
+ end
185
+ result.concat config.require_paths
186
+ result.push File.join(directory, 'lib') if result.empty?
187
+ result
188
+ end
189
+
190
+ # Get additional require paths defined in the configuration.
191
+ #
192
+ # @return [Array<String>]
193
+ def configured_require_paths
194
+ return ['lib'] if directory.empty?
195
+ return [File.join(directory, 'lib')] if config.require_paths.empty?
196
+ config.require_paths.map{|p| File.join(directory, p)}
197
+ end
198
+
199
+ def require_plugins
200
+ config.plugins.each do |plugin|
201
+ begin
202
+ require plugin
203
+ rescue LoadError
204
+ Solargraph.logger.warn "Failed to load plugin '#{plugin}'"
205
+ end
206
+ end
207
+ end
208
+ end
209
+ end
@@ -0,0 +1,230 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+
5
+ module Solargraph
6
+ class Workspace
7
+ # Configuration data for a workspace.
8
+ #
9
+ class Config
10
+ # The maximum number of files that can be added to a workspace.
11
+ # The workspace's .solargraph.yml can override this value.
12
+ MAX_FILES = 5000
13
+
14
+ # @return [String]
15
+ attr_reader :directory
16
+
17
+ # @return [Hash]
18
+ attr_reader :raw_data
19
+
20
+ # @param directory [String]
21
+ def initialize directory = ''
22
+ @directory = directory
23
+ @raw_data = config_data
24
+ included
25
+ excluded
26
+ end
27
+
28
+ # An array of files included in the workspace (before calculating excluded files).
29
+ #
30
+ # @return [Array<String>]
31
+ def included
32
+ return [] if directory.empty? || directory == '*'
33
+ @included ||= process_globs(@raw_data['include'])
34
+ end
35
+
36
+ # An array of files excluded from the workspace.
37
+ #
38
+ # @return [Array<String>]
39
+ def excluded
40
+ return [] if directory.empty? || directory == '*'
41
+ @excluded ||= process_exclusions(@raw_data['exclude'])
42
+ end
43
+
44
+ def allow? filename
45
+ filename.start_with?(directory) &&
46
+ !excluded.include?(filename) &&
47
+ excluded_directories.none? { |d| filename.start_with?(d) }
48
+ end
49
+
50
+ # The calculated array of (included - excluded) files in the workspace.
51
+ #
52
+ # @return [Array<String>]
53
+ def calculated
54
+ Solargraph.logger.info "Indexing workspace files in #{directory}" unless @calculated || directory.empty? || directory == '*'
55
+ @calculated ||= included - excluded
56
+ end
57
+
58
+ # An array of domains configured for the workspace.
59
+ # A domain is a namespace that the ApiMap should include in the global
60
+ # namespace. It's typically used to identify available DSLs.
61
+ #
62
+ # @return [Array<String>]
63
+ def domains
64
+ raw_data['domains']
65
+ end
66
+
67
+ # An array of required paths to add to the workspace.
68
+ #
69
+ # @return [Array<String>]
70
+ def required
71
+ raw_data['require']
72
+ end
73
+
74
+ # An array of load paths for required paths.
75
+ #
76
+ # @return [Array<String>]
77
+ def require_paths
78
+ raw_data['require_paths'] || []
79
+ end
80
+
81
+ # An array of reporters to use for diagnostics.
82
+ #
83
+ # @return [Array<String>]
84
+ def reporters
85
+ raw_data['reporters']
86
+ end
87
+
88
+ # A hash of options supported by the formatter
89
+ #
90
+ # @return [Hash]
91
+ def formatter
92
+ raw_data['formatter']
93
+ end
94
+
95
+ # An array of plugins to require.
96
+ #
97
+ # @return [Array<String>]
98
+ def plugins
99
+ raw_data['plugins']
100
+ end
101
+
102
+ # The maximum number of files to parse from the workspace.
103
+ #
104
+ # @return [Integer]
105
+ def max_files
106
+ raw_data['max_files']
107
+ end
108
+
109
+ private
110
+
111
+ # @return [String]
112
+ def global_config_path
113
+ ENV['SOLARGRAPH_GLOBAL_CONFIG'] ||
114
+ File.join(Dir.home, '.config', 'solargraph', 'config.yml')
115
+ end
116
+
117
+ # @return [String]
118
+ def workspace_config_path
119
+ return '' if @directory.empty?
120
+ File.join(@directory, '.solargraph.yml')
121
+ end
122
+
123
+ # @return [Hash]
124
+ def config_data
125
+ workspace_config = read_config(workspace_config_path)
126
+ global_config = read_config(global_config_path)
127
+
128
+ defaults = default_config
129
+ defaults.merge({'exclude' => []}) unless workspace_config.nil?
130
+
131
+ defaults
132
+ .merge(global_config || {})
133
+ .merge(workspace_config || {})
134
+ end
135
+
136
+ # Read a .solargraph yaml config
137
+ #
138
+ # @param directory [String]
139
+ # @return [Hash, nil]
140
+ def read_config config_path = ''
141
+ return nil if config_path.empty?
142
+ return nil unless File.file?(config_path)
143
+ YAML.safe_load(File.read(config_path))
144
+ end
145
+
146
+ # @return [Hash]
147
+ def default_config
148
+ {
149
+ 'include' => ['**/*.rb'],
150
+ 'exclude' => ['spec/**/*', 'test/**/*', 'vendor/**/*', '.bundle/**/*'],
151
+ 'require' => [],
152
+ 'domains' => [],
153
+ 'reporters' => %w[rubocop require_not_found],
154
+ 'formatter' => {
155
+ 'rubocop' => {
156
+ 'cops' => 'safe',
157
+ 'except' => [],
158
+ 'only' => [],
159
+ 'extra_args' =>[]
160
+ }
161
+ },
162
+ 'require_paths' => [],
163
+ 'plugins' => [],
164
+ 'max_files' => MAX_FILES
165
+ }
166
+ end
167
+
168
+ # Get an array of files from the provided globs.
169
+ #
170
+ # @param globs [Array<String>]
171
+ # @return [Array<String>]
172
+ def process_globs globs
173
+ result = []
174
+ globs.each do |glob|
175
+ result.concat Dir[File.join directory, glob].map{ |f| f.gsub(/\\/, '/') }
176
+ end
177
+ result
178
+ end
179
+
180
+ # Modify the included files based on excluded directories and get an
181
+ # array of additional files to exclude.
182
+ #
183
+ # @param globs [Array<String>]
184
+ # @return [Array<String>]
185
+ def process_exclusions globs
186
+ remainder = globs.select do |glob|
187
+ if glob_is_directory?(glob)
188
+ exdir = File.join(directory, glob_to_directory(glob))
189
+ included.delete_if { |file| file.start_with?(exdir) }
190
+ false
191
+ else
192
+ true
193
+ end
194
+ end
195
+ process_globs remainder
196
+ end
197
+
198
+ # True if the glob translates to a whole directory.
199
+ #
200
+ # @example
201
+ # glob_is_directory?('path/to/dir') # => true
202
+ # glob_is_directory?('path/to/dir/**/*) # => true
203
+ # glob_is_directory?('path/to/file.txt') # => false
204
+ # glob_is_directory?('path/to/*.txt') # => false
205
+ #
206
+ # @param glob [String]
207
+ # @return [Boolean]
208
+ def glob_is_directory? glob
209
+ File.directory?(glob) || File.directory?(glob_to_directory(glob))
210
+ end
211
+
212
+ # Translate a glob to a base directory if applicable
213
+ #
214
+ # @example
215
+ # glob_to_directory('path/to/dir/**/*') # => 'path/to/dir'
216
+ #
217
+ # @param glob [String]
218
+ # @return [String]
219
+ def glob_to_directory glob
220
+ glob.gsub(/(\/\*|\/\*\*\/\*\*?)$/, '')
221
+ end
222
+
223
+ def excluded_directories
224
+ @raw_data['exclude']
225
+ .select { |g| glob_is_directory?(g) }
226
+ .map { |g| File.join(directory, glob_to_directory(g)) }
227
+ end
228
+ end
229
+ end
230
+ end