solargraph 0.58.1 → 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 (195) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/plugins.yml +3 -2
  3. data/.gitignore +1 -0
  4. data/CHANGELOG.md +10 -1
  5. data/lib/solargraph/api_map/cache.rb +110 -110
  6. data/lib/solargraph/api_map/constants.rb +279 -279
  7. data/lib/solargraph/api_map/index.rb +193 -193
  8. data/lib/solargraph/api_map/source_to_yard.rb +97 -97
  9. data/lib/solargraph/api_map/store.rb +384 -384
  10. data/lib/solargraph/api_map.rb +945 -945
  11. data/lib/solargraph/bench.rb +45 -45
  12. data/lib/solargraph/complex_type/type_methods.rb +228 -228
  13. data/lib/solargraph/complex_type/unique_type.rb +482 -482
  14. data/lib/solargraph/complex_type.rb +444 -444
  15. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -61
  16. data/lib/solargraph/convention/data_definition/data_definition_node.rb +91 -91
  17. data/lib/solargraph/convention/data_definition.rb +105 -105
  18. data/lib/solargraph/convention/gemfile.rb +15 -15
  19. data/lib/solargraph/convention/gemspec.rb +23 -23
  20. data/lib/solargraph/convention/rakefile.rb +17 -17
  21. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +61 -61
  22. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +102 -102
  23. data/lib/solargraph/convention/struct_definition.rb +164 -164
  24. data/lib/solargraph/convention.rb +78 -78
  25. data/lib/solargraph/converters/dd.rb +17 -17
  26. data/lib/solargraph/converters/dl.rb +15 -15
  27. data/lib/solargraph/converters/dt.rb +15 -15
  28. data/lib/solargraph/converters/misc.rb +1 -1
  29. data/lib/solargraph/diagnostics/require_not_found.rb +53 -53
  30. data/lib/solargraph/diagnostics/rubocop.rb +118 -118
  31. data/lib/solargraph/diagnostics/rubocop_helpers.rb +68 -68
  32. data/lib/solargraph/diagnostics/type_check.rb +55 -55
  33. data/lib/solargraph/diagnostics/update_errors.rb +41 -41
  34. data/lib/solargraph/doc_map.rb +439 -439
  35. data/lib/solargraph/equality.rb +34 -34
  36. data/lib/solargraph/gem_pins.rb +98 -98
  37. data/lib/solargraph/language_server/error_codes.rb +20 -20
  38. data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
  39. data/lib/solargraph/language_server/host/dispatch.rb +130 -130
  40. data/lib/solargraph/language_server/host/message_worker.rb +112 -112
  41. data/lib/solargraph/language_server/host/sources.rb +99 -99
  42. data/lib/solargraph/language_server/host.rb +878 -878
  43. data/lib/solargraph/language_server/message/base.rb +97 -97
  44. data/lib/solargraph/language_server/message/client/register_capability.rb +15 -15
  45. data/lib/solargraph/language_server/message/completion_item/resolve.rb +60 -60
  46. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +114 -114
  47. data/lib/solargraph/language_server/message/extended/document.rb +23 -23
  48. data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -32
  49. data/lib/solargraph/language_server/message/extended/download_core.rb +19 -19
  50. data/lib/solargraph/language_server/message/extended/search.rb +20 -20
  51. data/lib/solargraph/language_server/message/initialize.rb +191 -191
  52. data/lib/solargraph/language_server/message/text_document/completion.rb +56 -56
  53. data/lib/solargraph/language_server/message/text_document/definition.rb +40 -40
  54. data/lib/solargraph/language_server/message/text_document/document_highlight.rb +16 -16
  55. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +26 -26
  56. data/lib/solargraph/language_server/message/text_document/formatting.rb +148 -148
  57. data/lib/solargraph/language_server/message/text_document/hover.rb +58 -58
  58. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +11 -11
  59. data/lib/solargraph/language_server/message/text_document/references.rb +16 -16
  60. data/lib/solargraph/language_server/message/text_document/rename.rb +19 -19
  61. data/lib/solargraph/language_server/message/text_document/signature_help.rb +24 -24
  62. data/lib/solargraph/language_server/message/text_document/type_definition.rb +25 -25
  63. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +35 -35
  64. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +40 -40
  65. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +26 -26
  66. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +23 -23
  67. data/lib/solargraph/language_server/message.rb +94 -94
  68. data/lib/solargraph/language_server/request.rb +27 -27
  69. data/lib/solargraph/language_server/transport/data_reader.rb +74 -74
  70. data/lib/solargraph/language_server/uri_helpers.rb +49 -49
  71. data/lib/solargraph/library.rb +683 -683
  72. data/lib/solargraph/location.rb +82 -82
  73. data/lib/solargraph/logging.rb +37 -37
  74. data/lib/solargraph/page.rb +92 -92
  75. data/lib/solargraph/parser/comment_ripper.rb +69 -69
  76. data/lib/solargraph/parser/flow_sensitive_typing.rb +255 -255
  77. data/lib/solargraph/parser/node_processor/base.rb +92 -92
  78. data/lib/solargraph/parser/node_processor.rb +62 -62
  79. data/lib/solargraph/parser/parser_gem/class_methods.rb +149 -149
  80. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +19 -19
  81. data/lib/solargraph/parser/parser_gem/node_chainer.rb +166 -166
  82. data/lib/solargraph/parser/parser_gem/node_methods.rb +486 -486
  83. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +22 -22
  84. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +59 -59
  85. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +15 -15
  86. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +46 -46
  87. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +53 -53
  88. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +37 -37
  89. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +23 -23
  90. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +40 -40
  91. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +29 -29
  92. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +59 -59
  93. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +98 -98
  94. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +17 -17
  95. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +38 -38
  96. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +52 -52
  97. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +291 -291
  98. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -29
  99. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +29 -29
  100. data/lib/solargraph/parser/parser_gem/node_processors.rb +70 -70
  101. data/lib/solargraph/parser/parser_gem.rb +12 -12
  102. data/lib/solargraph/parser/region.rb +69 -69
  103. data/lib/solargraph/parser/snippet.rb +17 -17
  104. data/lib/solargraph/parser.rb +23 -23
  105. data/lib/solargraph/pin/base.rb +729 -729
  106. data/lib/solargraph/pin/base_variable.rb +126 -126
  107. data/lib/solargraph/pin/block.rb +104 -104
  108. data/lib/solargraph/pin/breakable.rb +9 -9
  109. data/lib/solargraph/pin/callable.rb +231 -231
  110. data/lib/solargraph/pin/closure.rb +72 -72
  111. data/lib/solargraph/pin/common.rb +79 -79
  112. data/lib/solargraph/pin/constant.rb +45 -45
  113. data/lib/solargraph/pin/conversions.rb +123 -123
  114. data/lib/solargraph/pin/delegated_method.rb +120 -120
  115. data/lib/solargraph/pin/documenting.rb +114 -114
  116. data/lib/solargraph/pin/instance_variable.rb +34 -34
  117. data/lib/solargraph/pin/keyword.rb +20 -20
  118. data/lib/solargraph/pin/local_variable.rb +75 -75
  119. data/lib/solargraph/pin/method.rb +672 -672
  120. data/lib/solargraph/pin/method_alias.rb +34 -34
  121. data/lib/solargraph/pin/namespace.rb +115 -115
  122. data/lib/solargraph/pin/parameter.rb +275 -275
  123. data/lib/solargraph/pin/proxy_type.rb +39 -39
  124. data/lib/solargraph/pin/reference/override.rb +47 -47
  125. data/lib/solargraph/pin/reference/superclass.rb +15 -15
  126. data/lib/solargraph/pin/reference.rb +39 -39
  127. data/lib/solargraph/pin/search.rb +61 -61
  128. data/lib/solargraph/pin/signature.rb +61 -61
  129. data/lib/solargraph/pin/symbol.rb +53 -53
  130. data/lib/solargraph/pin/until.rb +18 -18
  131. data/lib/solargraph/pin/while.rb +18 -18
  132. data/lib/solargraph/pin.rb +44 -44
  133. data/lib/solargraph/pin_cache.rb +245 -245
  134. data/lib/solargraph/position.rb +132 -119
  135. data/lib/solargraph/range.rb +112 -112
  136. data/lib/solargraph/rbs_map/conversions.rb +823 -823
  137. data/lib/solargraph/rbs_map/core_fills.rb +84 -84
  138. data/lib/solargraph/rbs_map/core_map.rb +58 -58
  139. data/lib/solargraph/rbs_map/stdlib_map.rb +43 -43
  140. data/lib/solargraph/rbs_map.rb +163 -163
  141. data/lib/solargraph/server_methods.rb +16 -16
  142. data/lib/solargraph/shell.rb +363 -352
  143. data/lib/solargraph/source/chain/array.rb +37 -37
  144. data/lib/solargraph/source/chain/call.rb +337 -337
  145. data/lib/solargraph/source/chain/class_variable.rb +13 -13
  146. data/lib/solargraph/source/chain/constant.rb +26 -26
  147. data/lib/solargraph/source/chain/global_variable.rb +13 -13
  148. data/lib/solargraph/source/chain/hash.rb +34 -34
  149. data/lib/solargraph/source/chain/if.rb +28 -28
  150. data/lib/solargraph/source/chain/instance_variable.rb +13 -13
  151. data/lib/solargraph/source/chain/link.rb +109 -109
  152. data/lib/solargraph/source/chain/literal.rb +48 -48
  153. data/lib/solargraph/source/chain/or.rb +23 -23
  154. data/lib/solargraph/source/chain/q_call.rb +11 -11
  155. data/lib/solargraph/source/chain/variable.rb +13 -13
  156. data/lib/solargraph/source/chain/z_super.rb +30 -30
  157. data/lib/solargraph/source/chain.rb +291 -291
  158. data/lib/solargraph/source/change.rb +82 -82
  159. data/lib/solargraph/source/cursor.rb +166 -166
  160. data/lib/solargraph/source/source_chainer.rb +194 -194
  161. data/lib/solargraph/source/updater.rb +55 -55
  162. data/lib/solargraph/source.rb +498 -498
  163. data/lib/solargraph/source_map/clip.rb +226 -226
  164. data/lib/solargraph/source_map/data.rb +34 -34
  165. data/lib/solargraph/source_map/mapper.rb +259 -259
  166. data/lib/solargraph/source_map.rb +212 -212
  167. data/lib/solargraph/type_checker/checks.rb +124 -124
  168. data/lib/solargraph/type_checker/param_def.rb +37 -37
  169. data/lib/solargraph/type_checker/problem.rb +32 -32
  170. data/lib/solargraph/type_checker/rules.rb +84 -84
  171. data/lib/solargraph/type_checker.rb +814 -814
  172. data/lib/solargraph/version.rb +1 -1
  173. data/lib/solargraph/workspace/config.rb +255 -255
  174. data/lib/solargraph/workspace/require_paths.rb +97 -97
  175. data/lib/solargraph/workspace.rb +220 -220
  176. data/lib/solargraph/yard_map/helpers.rb +44 -44
  177. data/lib/solargraph/yard_map/mapper/to_method.rb +130 -130
  178. data/lib/solargraph/yard_map/mapper/to_namespace.rb +31 -31
  179. data/lib/solargraph/yard_map/mapper.rb +79 -79
  180. data/lib/solargraph/yard_map/to_method.rb +89 -89
  181. data/lib/solargraph/yard_tags.rb +20 -20
  182. data/lib/solargraph/yardoc.rb +87 -87
  183. data/lib/solargraph.rb +105 -105
  184. data/rbs_collection.yaml +1 -1
  185. metadata +12 -12
  186. /data/{sig → rbs}/shims/ast/0/node.rbs +0 -0
  187. /data/{sig → rbs}/shims/ast/2.4/.rbs_meta.yaml +0 -0
  188. /data/{sig → rbs}/shims/ast/2.4/ast.rbs +0 -0
  189. /data/{sig → rbs}/shims/parser/3.2.0.1/builders/default.rbs +0 -0
  190. /data/{sig → rbs}/shims/parser/3.2.0.1/manifest.yaml +0 -0
  191. /data/{sig → rbs}/shims/parser/3.2.0.1/parser.rbs +0 -0
  192. /data/{sig → rbs}/shims/parser/3.2.0.1/polyfill.rbs +0 -0
  193. /data/{sig → rbs}/shims/thor/1.2.0.1/.rbs_meta.yaml +0 -0
  194. /data/{sig → rbs}/shims/thor/1.2.0.1/manifest.yaml +0 -0
  195. /data/{sig → rbs}/shims/thor/1.2.0.1/thor.rbs +0 -0
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Solargraph
4
- VERSION = '0.58.1'
4
+ VERSION = '0.58.3'
5
5
  end
@@ -1,255 +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 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
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