solargraph 0.54.4 → 0.58.3

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 (238) 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 +185 -6
  5. data/.github/workflows/rspec.yml +55 -5
  6. data/.github/workflows/typecheck.yml +8 -3
  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 +1 -0
  13. data/CHANGELOG.md +143 -0
  14. data/README.md +20 -6
  15. data/Rakefile +125 -13
  16. data/bin/solargraph +3 -0
  17. data/lib/solargraph/api_map/cache.rb +110 -109
  18. data/lib/solargraph/api_map/constants.rb +279 -0
  19. data/lib/solargraph/api_map/index.rb +193 -167
  20. data/lib/solargraph/api_map/source_to_yard.rb +97 -88
  21. data/lib/solargraph/api_map/store.rb +384 -241
  22. data/lib/solargraph/api_map.rb +945 -875
  23. data/lib/solargraph/bench.rb +45 -28
  24. data/lib/solargraph/complex_type/type_methods.rb +228 -217
  25. data/lib/solargraph/complex_type/unique_type.rb +482 -386
  26. data/lib/solargraph/complex_type.rb +444 -394
  27. data/lib/solargraph/convention/active_support_concern.rb +111 -0
  28. data/lib/solargraph/convention/base.rb +20 -3
  29. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -0
  30. data/lib/solargraph/convention/data_definition/data_definition_node.rb +91 -0
  31. data/lib/solargraph/convention/data_definition.rb +105 -0
  32. data/lib/solargraph/convention/gemfile.rb +15 -15
  33. data/lib/solargraph/convention/gemspec.rb +23 -22
  34. data/lib/solargraph/convention/rakefile.rb +17 -17
  35. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +61 -0
  36. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +102 -0
  37. data/lib/solargraph/convention/struct_definition.rb +164 -0
  38. data/lib/solargraph/convention.rb +78 -47
  39. data/lib/solargraph/converters/dd.rb +17 -17
  40. data/lib/solargraph/converters/dl.rb +15 -15
  41. data/lib/solargraph/converters/dt.rb +15 -15
  42. data/lib/solargraph/converters/misc.rb +1 -1
  43. data/lib/solargraph/diagnostics/require_not_found.rb +53 -53
  44. data/lib/solargraph/diagnostics/rubocop.rb +118 -113
  45. data/lib/solargraph/diagnostics/rubocop_helpers.rb +68 -66
  46. data/lib/solargraph/diagnostics/type_check.rb +55 -55
  47. data/lib/solargraph/diagnostics/update_errors.rb +41 -41
  48. data/lib/solargraph/doc_map.rb +439 -188
  49. data/lib/solargraph/environ.rb +9 -2
  50. data/lib/solargraph/equality.rb +34 -33
  51. data/lib/solargraph/gem_pins.rb +98 -72
  52. data/lib/solargraph/language_server/error_codes.rb +20 -20
  53. data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
  54. data/lib/solargraph/language_server/host/dispatch.rb +130 -128
  55. data/lib/solargraph/language_server/host/message_worker.rb +112 -106
  56. data/lib/solargraph/language_server/host/sources.rb +99 -99
  57. data/lib/solargraph/language_server/host.rb +878 -861
  58. data/lib/solargraph/language_server/message/base.rb +97 -96
  59. data/lib/solargraph/language_server/message/client/register_capability.rb +15 -15
  60. data/lib/solargraph/language_server/message/completion_item/resolve.rb +60 -60
  61. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +114 -112
  62. data/lib/solargraph/language_server/message/extended/document.rb +23 -20
  63. data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -32
  64. data/lib/solargraph/language_server/message/extended/download_core.rb +19 -19
  65. data/lib/solargraph/language_server/message/extended/search.rb +20 -20
  66. data/lib/solargraph/language_server/message/initialize.rb +191 -191
  67. data/lib/solargraph/language_server/message/text_document/completion.rb +56 -56
  68. data/lib/solargraph/language_server/message/text_document/definition.rb +40 -38
  69. data/lib/solargraph/language_server/message/text_document/document_highlight.rb +16 -16
  70. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +26 -26
  71. data/lib/solargraph/language_server/message/text_document/formatting.rb +148 -131
  72. data/lib/solargraph/language_server/message/text_document/hover.rb +58 -58
  73. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +11 -11
  74. data/lib/solargraph/language_server/message/text_document/references.rb +16 -16
  75. data/lib/solargraph/language_server/message/text_document/rename.rb +19 -19
  76. data/lib/solargraph/language_server/message/text_document/signature_help.rb +24 -24
  77. data/lib/solargraph/language_server/message/text_document/type_definition.rb +25 -24
  78. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +35 -35
  79. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +40 -40
  80. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +26 -24
  81. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +23 -23
  82. data/lib/solargraph/language_server/message.rb +94 -94
  83. data/lib/solargraph/language_server/progress.rb +8 -0
  84. data/lib/solargraph/language_server/request.rb +27 -24
  85. data/lib/solargraph/language_server/transport/data_reader.rb +74 -74
  86. data/lib/solargraph/language_server/uri_helpers.rb +49 -49
  87. data/lib/solargraph/library.rb +683 -662
  88. data/lib/solargraph/location.rb +82 -58
  89. data/lib/solargraph/logging.rb +37 -27
  90. data/lib/solargraph/page.rb +92 -89
  91. data/lib/solargraph/parser/comment_ripper.rb +69 -56
  92. data/lib/solargraph/parser/flow_sensitive_typing.rb +255 -0
  93. data/lib/solargraph/parser/node_processor/base.rb +92 -87
  94. data/lib/solargraph/parser/node_processor.rb +62 -45
  95. data/lib/solargraph/parser/parser_gem/class_methods.rb +149 -157
  96. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +19 -18
  97. data/lib/solargraph/parser/parser_gem/node_chainer.rb +166 -164
  98. data/lib/solargraph/parser/parser_gem/node_methods.rb +486 -495
  99. data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +2 -1
  100. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +22 -0
  101. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +59 -57
  102. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +15 -15
  103. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +46 -43
  104. data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +2 -1
  105. data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +2 -1
  106. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +53 -50
  107. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +37 -36
  108. data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +2 -1
  109. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +23 -0
  110. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +40 -38
  111. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +29 -28
  112. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +59 -53
  113. data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +8 -7
  114. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +98 -0
  115. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +17 -16
  116. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +38 -36
  117. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +52 -42
  118. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +291 -259
  119. data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +3 -1
  120. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -0
  121. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +29 -0
  122. data/lib/solargraph/parser/parser_gem/node_processors.rb +70 -56
  123. data/lib/solargraph/parser/parser_gem.rb +12 -12
  124. data/lib/solargraph/parser/region.rb +69 -66
  125. data/lib/solargraph/parser/snippet.rb +17 -15
  126. data/lib/solargraph/parser.rb +23 -22
  127. data/lib/solargraph/pin/base.rb +729 -378
  128. data/lib/solargraph/pin/base_variable.rb +126 -118
  129. data/lib/solargraph/pin/block.rb +104 -101
  130. data/lib/solargraph/pin/breakable.rb +9 -0
  131. data/lib/solargraph/pin/callable.rb +231 -147
  132. data/lib/solargraph/pin/closure.rb +72 -57
  133. data/lib/solargraph/pin/common.rb +79 -70
  134. data/lib/solargraph/pin/constant.rb +45 -43
  135. data/lib/solargraph/pin/conversions.rb +123 -123
  136. data/lib/solargraph/pin/delegated_method.rb +120 -101
  137. data/lib/solargraph/pin/documenting.rb +114 -98
  138. data/lib/solargraph/pin/instance_variable.rb +34 -34
  139. data/lib/solargraph/pin/keyword.rb +20 -15
  140. data/lib/solargraph/pin/local_variable.rb +75 -67
  141. data/lib/solargraph/pin/method.rb +672 -527
  142. data/lib/solargraph/pin/method_alias.rb +34 -31
  143. data/lib/solargraph/pin/namespace.rb +115 -107
  144. data/lib/solargraph/pin/parameter.rb +275 -212
  145. data/lib/solargraph/pin/proxy_type.rb +39 -29
  146. data/lib/solargraph/pin/reference/override.rb +47 -29
  147. data/lib/solargraph/pin/reference/require.rb +2 -2
  148. data/lib/solargraph/pin/reference/superclass.rb +15 -10
  149. data/lib/solargraph/pin/reference.rb +39 -22
  150. data/lib/solargraph/pin/search.rb +61 -56
  151. data/lib/solargraph/pin/signature.rb +61 -17
  152. data/lib/solargraph/pin/singleton.rb +1 -1
  153. data/lib/solargraph/pin/symbol.rb +53 -47
  154. data/lib/solargraph/pin/until.rb +18 -0
  155. data/lib/solargraph/pin/while.rb +18 -0
  156. data/lib/solargraph/pin.rb +44 -41
  157. data/lib/solargraph/pin_cache.rb +245 -0
  158. data/lib/solargraph/position.rb +132 -107
  159. data/lib/solargraph/range.rb +112 -98
  160. data/lib/solargraph/rbs_map/conversions.rb +823 -646
  161. data/lib/solargraph/rbs_map/core_fills.rb +84 -50
  162. data/lib/solargraph/rbs_map/core_map.rb +58 -28
  163. data/lib/solargraph/rbs_map/stdlib_map.rb +43 -33
  164. data/lib/solargraph/rbs_map.rb +163 -93
  165. data/lib/solargraph/server_methods.rb +16 -16
  166. data/lib/solargraph/shell.rb +363 -269
  167. data/lib/solargraph/source/chain/array.rb +37 -33
  168. data/lib/solargraph/source/chain/block_symbol.rb +1 -1
  169. data/lib/solargraph/source/chain/block_variable.rb +1 -1
  170. data/lib/solargraph/source/chain/call.rb +337 -303
  171. data/lib/solargraph/source/chain/class_variable.rb +13 -13
  172. data/lib/solargraph/source/chain/constant.rb +26 -89
  173. data/lib/solargraph/source/chain/global_variable.rb +13 -13
  174. data/lib/solargraph/source/chain/hash.rb +34 -33
  175. data/lib/solargraph/source/chain/head.rb +1 -1
  176. data/lib/solargraph/source/chain/if.rb +28 -28
  177. data/lib/solargraph/source/chain/instance_variable.rb +13 -13
  178. data/lib/solargraph/source/chain/link.rb +109 -98
  179. data/lib/solargraph/source/chain/literal.rb +48 -28
  180. data/lib/solargraph/source/chain/or.rb +23 -23
  181. data/lib/solargraph/source/chain/q_call.rb +11 -11
  182. data/lib/solargraph/source/chain/variable.rb +13 -13
  183. data/lib/solargraph/source/chain/z_super.rb +30 -30
  184. data/lib/solargraph/source/chain.rb +291 -252
  185. data/lib/solargraph/source/change.rb +82 -82
  186. data/lib/solargraph/source/cursor.rb +166 -167
  187. data/lib/solargraph/source/encoding_fixes.rb +23 -23
  188. data/lib/solargraph/source/source_chainer.rb +194 -194
  189. data/lib/solargraph/source/updater.rb +55 -55
  190. data/lib/solargraph/source.rb +498 -495
  191. data/lib/solargraph/source_map/clip.rb +226 -232
  192. data/lib/solargraph/source_map/data.rb +34 -30
  193. data/lib/solargraph/source_map/mapper.rb +259 -255
  194. data/lib/solargraph/source_map.rb +212 -217
  195. data/lib/solargraph/type_checker/checks.rb +124 -120
  196. data/lib/solargraph/type_checker/param_def.rb +37 -35
  197. data/lib/solargraph/type_checker/problem.rb +32 -32
  198. data/lib/solargraph/type_checker/rules.rb +84 -62
  199. data/lib/solargraph/type_checker.rb +814 -672
  200. data/lib/solargraph/version.rb +5 -5
  201. data/lib/solargraph/views/_method.erb +10 -10
  202. data/lib/solargraph/views/_namespace.erb +3 -3
  203. data/lib/solargraph/views/document.erb +10 -10
  204. data/lib/solargraph/workspace/config.rb +255 -239
  205. data/lib/solargraph/workspace/require_paths.rb +97 -0
  206. data/lib/solargraph/workspace.rb +220 -239
  207. data/lib/solargraph/yard_map/helpers.rb +44 -16
  208. data/lib/solargraph/yard_map/mapper/to_constant.rb +7 -5
  209. data/lib/solargraph/yard_map/mapper/to_method.rb +130 -94
  210. data/lib/solargraph/yard_map/mapper/to_namespace.rb +31 -28
  211. data/lib/solargraph/yard_map/mapper.rb +79 -78
  212. data/lib/solargraph/yard_map/to_method.rb +89 -86
  213. data/lib/solargraph/yard_tags.rb +20 -20
  214. data/lib/solargraph/yardoc.rb +87 -52
  215. data/lib/solargraph.rb +105 -72
  216. data/rbs/fills/bundler/0/bundler.rbs +4271 -0
  217. data/rbs/fills/open3/0/open3.rbs +172 -0
  218. data/rbs/fills/rubygems/0/basic_specification.rbs +326 -0
  219. data/rbs/fills/rubygems/0/errors.rbs +364 -0
  220. data/rbs/fills/rubygems/0/spec_fetcher.rbs +107 -0
  221. data/rbs/fills/rubygems/0/specification.rbs +1753 -0
  222. data/rbs/fills/tuple/tuple.rbs +149 -0
  223. data/rbs/shims/ast/0/node.rbs +5 -0
  224. data/rbs/shims/ast/2.4/.rbs_meta.yaml +9 -0
  225. data/rbs/shims/ast/2.4/ast.rbs +73 -0
  226. data/rbs/shims/parser/3.2.0.1/builders/default.rbs +195 -0
  227. data/rbs/shims/parser/3.2.0.1/manifest.yaml +7 -0
  228. data/rbs/shims/parser/3.2.0.1/parser.rbs +201 -0
  229. data/rbs/shims/parser/3.2.0.1/polyfill.rbs +4 -0
  230. data/rbs/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
  231. data/rbs/shims/thor/1.2.0.1/manifest.yaml +7 -0
  232. data/rbs/shims/thor/1.2.0.1/thor.rbs +17 -0
  233. data/rbs_collection.yaml +19 -0
  234. data/solargraph.gemspec +27 -5
  235. metadata +215 -18
  236. data/lib/.rubocop.yml +0 -22
  237. data/lib/solargraph/cache.rb +0 -77
  238. data/lib/solargraph/parser/node_methods.rb +0 -83
@@ -1,5 +1,5 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- VERSION = '0.54.4'
5
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ VERSION = '0.58.3'
5
+ end
@@ -2,33 +2,33 @@
2
2
  Namespace:
3
3
  </h2>
4
4
  <p>
5
- <a href="solargraph:/document?query=<%= CGI.escape object.namespace.path %>"><%= object.namespace %></a>
5
+ <a href="solargraph:/document?query=<%= CGI.escape pin.namespace.path %>"><%= pin.namespace %></a>
6
6
  </p>
7
7
  <h2>
8
8
  Overview:
9
9
  </h2>
10
- <%= htmlify object.docstring %>
10
+ <%= htmlify pin.docstring %>
11
11
  <p class="document-section">
12
- <big><strong>Visibility:</strong></big> <%= object.visibility %>
12
+ <big><strong>Visibility:</strong></big> <%= pin.visibility %>
13
13
  </p>
14
- <% unless object.tags(:param).empty? %>
14
+ <% unless pin.docstring.tags(:param).empty? %>
15
15
  <h2>
16
16
  Parameters:
17
17
  </h2>
18
18
  <ul>
19
- <% object.tags(:param).each do |tag| %>
19
+ <% pin.docstring.tags(:param).each do |tag| %>
20
20
  <li>
21
21
  <%= erb :_name_type_tag, layout: false, locals: {tag: tag} %>
22
22
  </li>
23
23
  <% end %>
24
24
  </ul>
25
25
  <% end %>
26
- <% unless object.tags(:raise).empty? %>
26
+ <% unless pin.docstring.tags(:raise).empty? %>
27
27
  <h2>
28
28
  Raises:
29
29
  </h2>
30
30
  <ul>
31
- <% object.tags(:raise).each do |tag| %>
31
+ <% pin.docstring.tags(:raise).each do |tag| %>
32
32
  <li>
33
33
  <%= erb :_name_type_tag, layout: false, locals: {tag: tag} %>
34
34
  </li>
@@ -38,20 +38,20 @@
38
38
  <h2>
39
39
  Returns:
40
40
  </h2>
41
- <% if object.tag(:return).nil? %>
41
+ <% if pin.docstring.tag(:return).nil? %>
42
42
  <p>
43
43
  Undefined/unknown
44
44
  </p>
45
45
  <% else %>
46
46
  <ul>
47
- <% object.tags(:return).each do |tag| %>
47
+ <% pin.tags(:return).each do |tag| %>
48
48
  <li>
49
49
  <%= erb :_name_type_tag, layout: false, locals: {tag: tag} %>
50
50
  </li>
51
51
  <% end %>
52
52
  </ul>
53
53
  <% end %>
54
- <% examples = object.tags(:example) %>
54
+ <% examples = pin.docstring.tags(:example) %>
55
55
  <% unless examples.nil? %>
56
56
  <% examples.each do |example| %>
57
57
  <h2>
@@ -1,12 +1,12 @@
1
1
  <h2>
2
2
  Overview:
3
3
  </h2>
4
- <%= htmlify object.docstring %>
4
+ <%= htmlify pin.docstring %>
5
5
  <h2>
6
6
  Class Methods
7
7
  </h2>
8
8
  <ul class="doc-list">
9
- <% object.meths(scope: :class).sort{|a, b| a.name <=> b.name}.each do |meth| %>
9
+ <% api_map.get_methods(pin.path, scope: :class, deep: false).sort{|a, b| a.name <=> b.name}.each do |meth| %>
10
10
  <li>
11
11
  <a href="solargraph:/document?query=<%= CGI.escape(meth.path) %>"><%= meth.name %></a>
12
12
  </li>
@@ -16,7 +16,7 @@
16
16
  Instance Methods
17
17
  </h2>
18
18
  <ul class="doc-list">
19
- <% object.meths(scope: :instance).sort{|a, b| a.name <=> b.name}.each do |meth| %>
19
+ <% api_map.get_methods(pin.path, scope: :instance, deep: false).sort{|a, b| a.name <=> b.name}.each do |meth| %>
20
20
  <li>
21
21
  <a href="solargraph:/document?query=<%= CGI.escape(meth.path) %>"><%= meth.name %></a>
22
22
  </li>
@@ -1,23 +1,23 @@
1
- <% objects.reverse.each do |object| %>
1
+ <% pins.each do |pin| %>
2
2
  <h1>
3
- <%= object.name %>
4
- <% if object.is_a?(YARD::CodeObjects::MethodObject) and !object.parameters.empty? %>
5
- <small>(<%= object.parameters.map {|p| "#{p[0]}#{p[1] and p[0].end_with?(':') ? ' ' : (p[1] ? ' = ' : '')}#{p[1]}"}.join(', ') %>)</small>
3
+ <%= pin.name %>
4
+ <% if pin.is_a?(Solargraph::Pin::Method) && !pin.parameters.empty? %>
5
+ <small>(<%= pin.parameters.map {|p| "#{p[0]}#{p[1] and p[0].end_with?(':') ? ' ' : (p[1] ? ' = ' : '')}#{p[1]}"}.join(', ') %>)</small>
6
6
  <% end %>
7
7
  </h1>
8
- <% unless object.files.empty? %>
8
+ <% unless pins.map(&:location).compact.empty? %>
9
9
  <h2>
10
10
  Defined in:
11
11
  </h2>
12
12
  <ul>
13
- <% object.files.each do |f| %>
13
+ <% pins.map(&:location).compact.map(&:filename).each do |f| %>
14
14
  <li><%= f %></li>
15
15
  <% end %>
16
16
  </ul>
17
17
  <% end %>
18
- <% if object.is_a?(YARD::CodeObjects::NamespaceObject) %>
19
- <%= erb :_namespace, layout: false, locals: {object: object} %>
20
- <% elsif object.is_a?(YARD::CodeObjects::MethodObject) %>
21
- <%= erb :_method, layout: false, locals: {object: object} %>
18
+ <% if pin.is_a?(Solargraph::Pin::Namespace) %>
19
+ <%= erb :_namespace, layout: false, locals: {api_map: api_map, pin: pin} %>
20
+ <% elsif pin.is_a?(Solargraph::Pin::Method) %>
21
+ <%= erb :_method, layout: false, locals: {api_map: api_map, pin: pin} %>
22
22
  <% end %>
23
23
  <% end %>
@@ -1,239 +1,255 @@
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
- # @todo To make this strongly typed we'll need a record syntax
18
- # @return [Hash{String => Array, Hash, Integer, nil}]
19
- attr_reader :raw_data
20
-
21
- # @param directory [String]
22
- def initialize directory = ''
23
- @directory = File.absolute_path(directory)
24
- @raw_data = config_data
25
- included
26
- excluded
27
- end
28
-
29
- # An array of files included in the workspace (before calculating excluded files).
30
- #
31
- # @return [Array<String>]
32
- def included
33
- return [] if directory.empty? || directory == '*'
34
- @included ||= process_globs(@raw_data['include'])
35
- end
36
-
37
- # An array of files excluded from the workspace.
38
- #
39
- # @return [Array<String>]
40
- def excluded
41
- return [] if directory.empty? || directory == '*'
42
- @excluded ||= process_exclusions(@raw_data['exclude'])
43
- end
44
-
45
- # @param filename [String]
46
- def allow? filename
47
- filename = File.absolute_path(filename, directory)
48
- filename.start_with?(directory) &&
49
- !excluded.include?(filename) &&
50
- excluded_directories.none? { |d| filename.start_with?(d) }
51
- end
52
-
53
- # The calculated array of (included - excluded) files in the workspace.
54
- #
55
- # @return [Array<String>]
56
- def calculated
57
- Solargraph.logger.info "Indexing workspace files in #{directory}" unless @calculated || directory.empty? || directory == '*'
58
- @calculated ||= included - excluded
59
- end
60
-
61
- # An array of domains configured for the workspace.
62
- # A domain is a namespace that the ApiMap should include in the global
63
- # namespace. It's typically used to identify available DSLs.
64
- #
65
- # @return [Array<String>]
66
- def domains
67
- raw_data['domains']
68
- end
69
-
70
- # An array of required paths to add to the workspace.
71
- #
72
- # @return [Array<String>]
73
- def required
74
- raw_data['require']
75
- end
76
-
77
- # An array of load paths for required paths.
78
- #
79
- # @return [Array<String>]
80
- def require_paths
81
- raw_data['require_paths'] || []
82
- end
83
-
84
- # An array of reporters to use for diagnostics.
85
- #
86
- # @return [Array<String>]
87
- def reporters
88
- raw_data['reporters']
89
- end
90
-
91
- # A hash of options supported by the formatter
92
- #
93
- # @sg-ignore pending https://github.com/castwide/solargraph/pull/905
94
- # @return [Hash]
95
- def formatter
96
- raw_data['formatter']
97
- end
98
-
99
- # An array of plugins to require.
100
- #
101
- # @return [Array<String>]
102
- def plugins
103
- raw_data['plugins']
104
- end
105
-
106
- # The maximum number of files to parse from the workspace.
107
- #
108
- # @sg-ignore pending https://github.com/castwide/solargraph/pull/905
109
- # @return [Integer]
110
- def max_files
111
- raw_data['max_files']
112
- end
113
-
114
- private
115
-
116
- # @return [String]
117
- def global_config_path
118
- ENV['SOLARGRAPH_GLOBAL_CONFIG'] ||
119
- File.join(Dir.home, '.config', 'solargraph', 'config.yml')
120
- end
121
-
122
- # @return [String]
123
- def workspace_config_path
124
- return '' if @directory.empty?
125
- File.join(@directory, '.solargraph.yml')
126
- end
127
-
128
- # @return [Hash{String => Array<undefined>, Hash{String => undefined}, Integer}]
129
- def config_data
130
- workspace_config = read_config(workspace_config_path)
131
- global_config = read_config(global_config_path)
132
-
133
- defaults = default_config
134
- defaults.merge({'exclude' => []}) unless workspace_config.nil?
135
-
136
- defaults
137
- .merge(global_config || {})
138
- .merge(workspace_config || {})
139
- end
140
-
141
- # Read a .solargraph yaml config
142
- #
143
- # @param config_path [String]
144
- # @return [Hash{String => Array, Hash, Integer}, nil]
145
- def read_config config_path = ''
146
- return nil if config_path.empty?
147
- return nil unless File.file?(config_path)
148
- YAML.safe_load(File.read(config_path))
149
- end
150
-
151
- # @return [Hash{String => Array, Hash, Integer}]
152
- def default_config
153
- {
154
- 'include' => ['**/*.rb'],
155
- 'exclude' => ['spec/**/*', 'test/**/*', 'vendor/**/*', '.bundle/**/*'],
156
- 'require' => [],
157
- 'domains' => [],
158
- 'reporters' => %w[rubocop require_not_found],
159
- 'formatter' => {
160
- 'rubocop' => {
161
- 'cops' => 'safe',
162
- 'except' => [],
163
- 'only' => [],
164
- 'extra_args' =>[]
165
- }
166
- },
167
- 'require_paths' => [],
168
- 'plugins' => [],
169
- 'max_files' => MAX_FILES
170
- }
171
- end
172
-
173
- # Get an array of files from the provided globs.
174
- #
175
- # @param globs [Array<String>]
176
- # @return [Array<String>]
177
- def process_globs globs
178
- result = globs.flat_map do |glob|
179
- Dir[File.absolute_path(glob, directory)]
180
- .map{ |f| f.gsub(/\\/, '/') }
181
- .select { |f| File.file?(f) }
182
- end
183
- result
184
- end
185
-
186
- # Modify the included files based on excluded directories and get an
187
- # array of additional files to exclude.
188
- #
189
- # @param globs [Array<String>]
190
- # @return [Array<String>]
191
- def process_exclusions globs
192
- remainder = globs.select do |glob|
193
- if glob_is_directory?(glob)
194
- exdir = File.absolute_path(glob_to_directory(glob), directory)
195
- included.delete_if { |file| file.start_with?(exdir) }
196
- false
197
- else
198
- true
199
- end
200
- end
201
- process_globs remainder
202
- end
203
-
204
- # True if the glob translates to a whole directory.
205
- #
206
- # @example
207
- # glob_is_directory?('path/to/dir') # => true
208
- # glob_is_directory?('path/to/dir/**/*) # => true
209
- # glob_is_directory?('path/to/file.txt') # => false
210
- # glob_is_directory?('path/to/*.txt') # => false
211
- #
212
- # @param glob [String]
213
- # @return [Boolean]
214
- def glob_is_directory? glob
215
- File.directory?(glob) || File.directory?(glob_to_directory(glob))
216
- end
217
-
218
- # Translate a glob to a base directory if applicable
219
- #
220
- # @example
221
- # glob_to_directory('path/to/dir/**/*') # => 'path/to/dir'
222
- #
223
- # @param glob [String]
224
- # @return [String]
225
- def glob_to_directory glob
226
- glob.gsub(/(\/\*|\/\*\*\/\*\*?)$/, '')
227
- end
228
-
229
- # @return [Array<String>]
230
- def excluded_directories
231
- # @type [Array<String>]
232
- excluded = @raw_data['exclude']
233
- excluded
234
- .select { |g| glob_is_directory?(g) }
235
- .map { |g| File.absolute_path(glob_to_directory(g), directory) }
236
- end
237
- end
238
- end
239
- end
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
+ # @todo To make JSON strongly typed we'll need a record syntax
18
+ # @return [Hash{String => undefined, nil}]
19
+ attr_reader :raw_data
20
+
21
+ # @param directory [String]
22
+ def initialize directory = ''
23
+ @directory = File.absolute_path(directory)
24
+ @raw_data = config_data
25
+ included
26
+ excluded
27
+ end
28
+
29
+ # An array of files included in the workspace (before calculating excluded files).
30
+ #
31
+ # @return [Array<String>]
32
+ def included
33
+ return [] if directory.empty? || directory == '*'
34
+ @included ||= process_globs(@raw_data['include'])
35
+ end
36
+
37
+ # An array of files excluded from the workspace.
38
+ #
39
+ # @return [Array<String>]
40
+ def excluded
41
+ return [] if directory.empty? || directory == '*'
42
+ @excluded ||= process_exclusions(@raw_data['exclude'])
43
+ end
44
+
45
+ # @param filename [String]
46
+ def allow? filename
47
+ filename = File.absolute_path(filename, directory)
48
+ filename.start_with?(directory) &&
49
+ !excluded.include?(filename) &&
50
+ excluded_directories.none? { |d| filename.start_with?(d) }
51
+ end
52
+
53
+ # The calculated array of (included - excluded) files in the workspace.
54
+ #
55
+ # @return [Array<String>]
56
+ def calculated
57
+ Solargraph.logger.info "Indexing workspace files in #{directory}" unless @calculated || directory.empty? || directory == '*'
58
+ @calculated ||= included - excluded
59
+ end
60
+
61
+ # An array of domains configured for the workspace.
62
+ # A domain is a namespace that the ApiMap should include in the global
63
+ # namespace. It's typically used to identify available DSLs.
64
+ #
65
+ # @return [Array<String>]
66
+ # @sg-ignore Need to validate config
67
+ def domains
68
+ raw_data['domains']
69
+ end
70
+
71
+ # An array of required paths to add to the workspace.
72
+ #
73
+ # @return [Array<String>]
74
+ # @sg-ignore Need to validate config
75
+ def required
76
+ raw_data['require']
77
+ end
78
+
79
+ # An array of load paths for required paths.
80
+ #
81
+ # @return [Array<String>]
82
+ def require_paths
83
+ raw_data['require_paths'] || []
84
+ end
85
+
86
+ # An array of reporters to use for diagnostics.
87
+ #
88
+ # @sg-ignore Need to validate config
89
+ # @return [Array<String>]
90
+ def reporters
91
+ raw_data['reporters']
92
+ end
93
+
94
+ # A hash of options supported by the formatter
95
+ #
96
+ # @sg-ignore Need to validate config
97
+ # @return [Hash]
98
+ def formatter
99
+ raw_data['formatter']
100
+ end
101
+
102
+ # An array of plugins to require.
103
+ #
104
+ # @sg-ignore Need to validate config
105
+ # @return [Array<String>]
106
+ def plugins
107
+ raw_data['plugins']
108
+ end
109
+
110
+ # The maximum number of files to parse from the workspace.
111
+ #
112
+ # @sg-ignore Need to validate config
113
+ # @return [Integer]
114
+ def max_files
115
+ raw_data['max_files']
116
+ end
117
+
118
+ # @return [Hash{Symbol => Symbol}]
119
+ def type_checker_rules
120
+ # @type [Hash{String => String}]
121
+ raw_rules = raw_data.fetch('type_checker', {}).fetch('rules', {})
122
+ raw_rules.to_h do |k, v|
123
+ [k.to_sym, v.to_sym]
124
+ end
125
+ end
126
+
127
+ private
128
+
129
+ # @return [String]
130
+ def global_config_path
131
+ ENV['SOLARGRAPH_GLOBAL_CONFIG'] ||
132
+ File.join(Dir.home, '.config', 'solargraph', 'config.yml')
133
+ end
134
+
135
+ # @return [String]
136
+ def workspace_config_path
137
+ return '' if @directory.empty?
138
+ File.join(@directory, '.solargraph.yml')
139
+ end
140
+
141
+ # @return [Hash{String => undefined}]
142
+ def config_data
143
+ workspace_config = read_config(workspace_config_path)
144
+ global_config = read_config(global_config_path)
145
+
146
+ defaults = default_config
147
+ defaults.merge({'exclude' => []}) unless workspace_config.nil?
148
+
149
+ defaults
150
+ .merge(global_config || {})
151
+ .merge(workspace_config || {})
152
+ end
153
+
154
+ # Read a .solargraph yaml config
155
+ #
156
+ # @param config_path [String]
157
+ # @return [Hash{String => Array, Hash, Integer}, nil]
158
+ def read_config config_path = ''
159
+ return nil if config_path.empty?
160
+ return nil unless File.file?(config_path)
161
+ YAML.safe_load(File.read(config_path))
162
+ end
163
+
164
+ # @return [Hash{String => Array, Hash, Integer}]
165
+ def default_config
166
+ {
167
+ 'include' => ['Rakefile', 'Gemfile', '*.gemspec', '**/*.rb'],
168
+ 'exclude' => ['spec/**/*', 'test/**/*', 'vendor/**/*', '.bundle/**/*'],
169
+ 'require' => [],
170
+ 'domains' => [],
171
+ 'reporters' => %w[rubocop require_not_found],
172
+ 'formatter' => {
173
+ 'rubocop' => {
174
+ 'cops' => 'safe',
175
+ 'except' => [],
176
+ 'only' => [],
177
+ 'extra_args' =>[]
178
+ }
179
+ },
180
+ 'type_checker' => {
181
+ 'rules' => { }
182
+ },
183
+ 'require_paths' => [],
184
+ 'plugins' => [],
185
+ 'max_files' => MAX_FILES
186
+ }
187
+ end
188
+
189
+ # Get an array of files from the provided globs.
190
+ #
191
+ # @param globs [Array<String>]
192
+ # @return [Array<String>]
193
+ def process_globs globs
194
+ result = globs.flat_map do |glob|
195
+ Dir[File.absolute_path(glob, directory)]
196
+ .map{ |f| f.gsub(/\\/, '/') }
197
+ .select { |f| File.file?(f) }
198
+ end
199
+ result
200
+ end
201
+
202
+ # Modify the included files based on excluded directories and get an
203
+ # array of additional files to exclude.
204
+ #
205
+ # @param globs [Array<String>]
206
+ # @return [Array<String>]
207
+ def process_exclusions globs
208
+ remainder = globs.select do |glob|
209
+ if glob_is_directory?(glob)
210
+ exdir = File.absolute_path(glob_to_directory(glob), directory)
211
+ included.delete_if { |file| file.start_with?(exdir) }
212
+ false
213
+ else
214
+ true
215
+ end
216
+ end
217
+ process_globs remainder
218
+ end
219
+
220
+ # True if the glob translates to a whole directory.
221
+ #
222
+ # @example
223
+ # glob_is_directory?('path/to/dir') # => true
224
+ # glob_is_directory?('path/to/dir/**/*) # => true
225
+ # glob_is_directory?('path/to/file.txt') # => false
226
+ # glob_is_directory?('path/to/*.txt') # => false
227
+ #
228
+ # @param glob [String]
229
+ # @return [Boolean]
230
+ def glob_is_directory? glob
231
+ File.directory?(glob) || File.directory?(glob_to_directory(glob))
232
+ end
233
+
234
+ # Translate a glob to a base directory if applicable
235
+ #
236
+ # @example
237
+ # glob_to_directory('path/to/dir/**/*') # => 'path/to/dir'
238
+ #
239
+ # @param glob [String]
240
+ # @return [String]
241
+ def glob_to_directory glob
242
+ glob.gsub(/(\/\*|\/\*\*\/\*\*?)$/, '')
243
+ end
244
+
245
+ # @return [Array<String>]
246
+ def excluded_directories
247
+ # @type [Array<String>]
248
+ excluded = @raw_data['exclude']
249
+ excluded
250
+ .select { |g| glob_is_directory?(g) }
251
+ .map { |g| File.absolute_path(glob_to_directory(g), directory) }
252
+ end
253
+ end
254
+ end
255
+ end