solargraph 0.32.1 → 0.32.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 (177) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +9 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +6 -0
  5. data/.travis.yml +25 -0
  6. data/EXAMPLES.md +76 -0
  7. data/Gemfile +3 -0
  8. data/LANGUAGE_SERVER.md +51 -0
  9. data/LICENSE +21 -0
  10. data/OVERVIEW.md +37 -0
  11. data/README.md +106 -0
  12. data/Rakefile +14 -0
  13. data/SERVER.md +95 -0
  14. data/bin/solargraph +0 -0
  15. data/bin/solargraph-runtime +5 -5
  16. data/lib/solargraph.rb +54 -54
  17. data/lib/solargraph/api_map.rb +659 -659
  18. data/lib/solargraph/api_map/cache.rb +49 -49
  19. data/lib/solargraph/api_map/source_to_yard.rb +67 -67
  20. data/lib/solargraph/api_map/store.rb +201 -201
  21. data/lib/solargraph/bundle.rb +24 -24
  22. data/lib/solargraph/complex_type.rb +150 -150
  23. data/lib/solargraph/complex_type/type_methods.rb +124 -124
  24. data/lib/solargraph/complex_type/unique_type.rb +44 -44
  25. data/lib/solargraph/core_fills.rb +37 -37
  26. data/lib/solargraph/diagnostics.rb +52 -52
  27. data/lib/solargraph/diagnostics/base.rb +20 -20
  28. data/lib/solargraph/diagnostics/require_not_found.rb +28 -28
  29. data/lib/solargraph/diagnostics/rubocop.rb +98 -98
  30. data/lib/solargraph/diagnostics/rubocop_helpers.rb +46 -46
  31. data/lib/solargraph/diagnostics/type_not_defined.rb +108 -108
  32. data/lib/solargraph/diagnostics/update_errors.rb +38 -38
  33. data/lib/solargraph/language_server/completion_item_kinds.rb +33 -33
  34. data/lib/solargraph/language_server/error_codes.rb +18 -18
  35. data/lib/solargraph/language_server/host.rb +684 -681
  36. data/lib/solargraph/language_server/host/cataloger.rb +54 -79
  37. data/lib/solargraph/language_server/host/diagnoser.rb +80 -80
  38. data/lib/solargraph/language_server/host/dispatch.rb +112 -113
  39. data/lib/solargraph/language_server/host/sources.rb +138 -138
  40. data/lib/solargraph/language_server/message.rb +90 -90
  41. data/lib/solargraph/language_server/message/base.rb +83 -83
  42. data/lib/solargraph/language_server/message/completion_item/resolve.rb +40 -40
  43. data/lib/solargraph/language_server/message/exit_notification.rb +11 -11
  44. data/lib/solargraph/language_server/message/extended.rb +19 -19
  45. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +86 -86
  46. data/lib/solargraph/language_server/message/extended/document.rb +18 -18
  47. data/lib/solargraph/language_server/message/extended/document_gems.rb +30 -30
  48. data/lib/solargraph/language_server/message/extended/environment.rb +20 -20
  49. data/lib/solargraph/language_server/message/extended/search.rb +18 -18
  50. data/lib/solargraph/language_server/message/initialize.rb +141 -141
  51. data/lib/solargraph/language_server/message/initialized.rb +23 -23
  52. data/lib/solargraph/language_server/message/shutdown.rb +11 -11
  53. data/lib/solargraph/language_server/message/text_document.rb +25 -25
  54. data/lib/solargraph/language_server/message/text_document/completion.rb +51 -51
  55. data/lib/solargraph/language_server/message/text_document/definition.rb +18 -18
  56. data/lib/solargraph/language_server/message/text_document/did_change.rb +13 -13
  57. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +21 -21
  58. data/lib/solargraph/language_server/message/text_document/folding_range.rb +24 -24
  59. data/lib/solargraph/language_server/message/text_document/formatting.rb +50 -50
  60. data/lib/solargraph/language_server/message/text_document/hover.rb +31 -31
  61. data/lib/solargraph/language_server/message/text_document/on_type_formatting.rb +32 -32
  62. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +9 -9
  63. data/lib/solargraph/language_server/message/text_document/references.rb +14 -14
  64. data/lib/solargraph/language_server/message/text_document/rename.rb +17 -17
  65. data/lib/solargraph/language_server/message/text_document/signature_help.rb +19 -19
  66. data/lib/solargraph/language_server/message/workspace.rb +12 -12
  67. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +29 -29
  68. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +29 -27
  69. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +24 -24
  70. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +21 -21
  71. data/lib/solargraph/language_server/request.rb +22 -22
  72. data/lib/solargraph/language_server/symbol_kinds.rb +34 -34
  73. data/lib/solargraph/language_server/transport.rb +11 -11
  74. data/lib/solargraph/language_server/transport/adapter.rb +60 -60
  75. data/lib/solargraph/language_server/transport/data_reader.rb +66 -66
  76. data/lib/solargraph/language_server/uri_helpers.rb +25 -25
  77. data/lib/solargraph/library.rb +421 -419
  78. data/lib/solargraph/live_map.rb +126 -126
  79. data/lib/solargraph/live_map/cache.rb +38 -38
  80. data/lib/solargraph/location.rb +31 -31
  81. data/lib/solargraph/logging.rb +25 -25
  82. data/lib/solargraph/page.rb +68 -68
  83. data/lib/solargraph/pin.rb +50 -50
  84. data/lib/solargraph/pin/attribute.rb +41 -41
  85. data/lib/solargraph/pin/base.rb +280 -280
  86. data/lib/solargraph/pin/base_method.rb +76 -76
  87. data/lib/solargraph/pin/base_variable.rb +72 -72
  88. data/lib/solargraph/pin/block.rb +32 -32
  89. data/lib/solargraph/pin/block_parameter.rb +103 -103
  90. data/lib/solargraph/pin/class_variable.rb +9 -9
  91. data/lib/solargraph/pin/constant.rb +30 -30
  92. data/lib/solargraph/pin/conversions.rb +79 -79
  93. data/lib/solargraph/pin/documenting.rb +41 -41
  94. data/lib/solargraph/pin/duck_method.rb +14 -14
  95. data/lib/solargraph/pin/global_variable.rb +9 -9
  96. data/lib/solargraph/pin/instance_variable.rb +9 -9
  97. data/lib/solargraph/pin/keyword.rb +17 -17
  98. data/lib/solargraph/pin/local_variable.rb +23 -23
  99. data/lib/solargraph/pin/localized.rb +22 -22
  100. data/lib/solargraph/pin/method.rb +126 -126
  101. data/lib/solargraph/pin/method_alias.rb +30 -30
  102. data/lib/solargraph/pin/method_parameter.rb +40 -40
  103. data/lib/solargraph/pin/namespace.rb +54 -54
  104. data/lib/solargraph/pin/plugin/method.rb +25 -25
  105. data/lib/solargraph/pin/proxy_type.rb +35 -35
  106. data/lib/solargraph/pin/reference.rb +22 -22
  107. data/lib/solargraph/pin/reference/extend.rb +11 -11
  108. data/lib/solargraph/pin/reference/include.rb +11 -11
  109. data/lib/solargraph/pin/reference/require.rb +15 -15
  110. data/lib/solargraph/pin/reference/superclass.rb +11 -11
  111. data/lib/solargraph/pin/symbol.rb +44 -44
  112. data/lib/solargraph/pin/yard_pin.rb +10 -10
  113. data/lib/solargraph/pin/yard_pin/constant.rb +14 -14
  114. data/lib/solargraph/pin/yard_pin/method.rb +35 -35
  115. data/lib/solargraph/pin/yard_pin/namespace.rb +19 -19
  116. data/lib/solargraph/pin/yard_pin/yard_mixin.rb +14 -14
  117. data/lib/solargraph/plugin.rb +8 -8
  118. data/lib/solargraph/plugin/base.rb +41 -41
  119. data/lib/solargraph/plugin/canceler.rb +11 -11
  120. data/lib/solargraph/plugin/process.rb +172 -172
  121. data/lib/solargraph/plugin/runtime.rb +134 -134
  122. data/lib/solargraph/position.rb +110 -110
  123. data/lib/solargraph/range.rb +83 -83
  124. data/lib/solargraph/server_methods.rb +14 -14
  125. data/lib/solargraph/shell.rb +102 -102
  126. data/lib/solargraph/source.rb +521 -521
  127. data/lib/solargraph/source/chain.rb +120 -120
  128. data/lib/solargraph/source/chain/call.rb +107 -107
  129. data/lib/solargraph/source/chain/class_variable.rb +11 -11
  130. data/lib/solargraph/source/chain/constant.rb +30 -30
  131. data/lib/solargraph/source/chain/global_variable.rb +11 -11
  132. data/lib/solargraph/source/chain/head.rb +33 -33
  133. data/lib/solargraph/source/chain/instance_variable.rb +11 -11
  134. data/lib/solargraph/source/chain/link.rb +33 -33
  135. data/lib/solargraph/source/chain/literal.rb +21 -21
  136. data/lib/solargraph/source/chain/variable.rb +11 -11
  137. data/lib/solargraph/source/change.rb +77 -77
  138. data/lib/solargraph/source/cursor.rb +157 -157
  139. data/lib/solargraph/source/node_chainer.rb +96 -96
  140. data/lib/solargraph/source/node_methods.rb +225 -225
  141. data/lib/solargraph/source/source_chainer.rb +183 -183
  142. data/lib/solargraph/source_map.rb +169 -169
  143. data/lib/solargraph/source_map/clip.rb +145 -145
  144. data/lib/solargraph/source_map/completion.rb +21 -21
  145. data/lib/solargraph/source_map/mapper.rb +149 -149
  146. data/lib/solargraph/source_map/node_processor.rb +78 -78
  147. data/lib/solargraph/source_map/node_processor/alias_node.rb +19 -19
  148. data/lib/solargraph/source_map/node_processor/args_node.rb +28 -28
  149. data/lib/solargraph/source_map/node_processor/base.rb +68 -68
  150. data/lib/solargraph/source_map/node_processor/begin_node.rb +11 -11
  151. data/lib/solargraph/source_map/node_processor/block_node.rb +14 -14
  152. data/lib/solargraph/source_map/node_processor/casgn_node.rb +14 -14
  153. data/lib/solargraph/source_map/node_processor/cvasgn_node.rb +14 -14
  154. data/lib/solargraph/source_map/node_processor/def_node.rb +54 -54
  155. data/lib/solargraph/source_map/node_processor/defs_node.rb +21 -21
  156. data/lib/solargraph/source_map/node_processor/gvasgn_node.rb +12 -12
  157. data/lib/solargraph/source_map/node_processor/ivasgn_node.rb +18 -18
  158. data/lib/solargraph/source_map/node_processor/lvasgn_node.rb +16 -16
  159. data/lib/solargraph/source_map/node_processor/namespace_node.rb +26 -26
  160. data/lib/solargraph/source_map/node_processor/orasgn_node.rb +12 -12
  161. data/lib/solargraph/source_map/node_processor/sclass_node.rb +11 -11
  162. data/lib/solargraph/source_map/node_processor/send_node.rb +162 -162
  163. data/lib/solargraph/source_map/node_processor/sym_node.rb +11 -11
  164. data/lib/solargraph/source_map/region.rb +58 -58
  165. data/lib/solargraph/version.rb +3 -3
  166. data/lib/solargraph/views/environment.erb +53 -53
  167. data/lib/solargraph/workspace.rb +183 -183
  168. data/lib/solargraph/workspace/config.rb +170 -170
  169. data/lib/solargraph/yard_map.rb +298 -298
  170. data/lib/solargraph/yard_map/cache.rb +17 -17
  171. data/lib/solargraph/yard_map/core_docs.rb +163 -163
  172. data/lib/solargraph/yard_map/core_gen.rb +76 -76
  173. data/lib/yard-coregen.rb +16 -16
  174. data/lib/yard-solargraph.rb +18 -18
  175. data/solargraph.gemspec +37 -0
  176. data/travis-bundler.rb +10 -0
  177. metadata +19 -6
@@ -1,11 +1,11 @@
1
- module Solargraph
2
- class SourceMap
3
- module NodeProcessor
4
- class SymNode < Base
5
- def process
6
- pins.push Solargraph::Pin::Symbol.new(get_node_location(node), ":#{node.children[0]}")
7
- end
8
- end
9
- end
10
- end
11
- end
1
+ module Solargraph
2
+ class SourceMap
3
+ module NodeProcessor
4
+ class SymNode < Base
5
+ def process
6
+ pins.push Solargraph::Pin::Symbol.new(get_node_location(node), ":#{node.children[0]}")
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,58 +1,58 @@
1
- module Solargraph
2
- class SourceMap
3
- # Data used by the NodeProcessor library to track context at various
4
- # locations in a source.
5
- #
6
- class Region
7
- # @return [String]
8
- attr_reader :namespace
9
-
10
- # @return [Symbol]
11
- attr_reader :scope
12
-
13
- # @return [Symbol]
14
- attr_reader :visibility
15
-
16
- # @return [Solargraph::Source]
17
- attr_reader :source
18
-
19
- # @param source [Source]
20
- # @param namespace [String]
21
- # @param scope [Symbol]
22
- # @param visibility [Symbol]
23
- def initialize source: Solargraph::Source.load_string(''), namespace: '',
24
- scope: :instance, visibility: :public
25
- @source = source
26
- @namespace = namespace
27
- @scope = scope
28
- @visibility = visibility
29
- end
30
-
31
- # @return [String]
32
- def filename
33
- source.filename
34
- end
35
-
36
- # Generate a new Region with the provided attribute changes.
37
- #
38
- # @param namespace [String, nil]
39
- # @param scope [Symbol, nil]
40
- # @param visibility [Symbol, nil]
41
- # @return [Region]
42
- def update namespace: nil, scope: nil, visibility: nil
43
- Region.new(
44
- source: source,
45
- namespace: namespace || self.namespace,
46
- scope: scope || self.scope,
47
- visibility: visibility || self.visibility
48
- )
49
- end
50
-
51
- # @param node [Parser::AST::Node]
52
- # @return [String]
53
- def code_for node
54
- source.code_for(node)
55
- end
56
- end
57
- end
58
- end
1
+ module Solargraph
2
+ class SourceMap
3
+ # Data used by the NodeProcessor library to track context at various
4
+ # locations in a source.
5
+ #
6
+ class Region
7
+ # @return [String]
8
+ attr_reader :namespace
9
+
10
+ # @return [Symbol]
11
+ attr_reader :scope
12
+
13
+ # @return [Symbol]
14
+ attr_reader :visibility
15
+
16
+ # @return [Solargraph::Source]
17
+ attr_reader :source
18
+
19
+ # @param source [Source]
20
+ # @param namespace [String]
21
+ # @param scope [Symbol]
22
+ # @param visibility [Symbol]
23
+ def initialize source: Solargraph::Source.load_string(''), namespace: '',
24
+ scope: :instance, visibility: :public
25
+ @source = source
26
+ @namespace = namespace
27
+ @scope = scope
28
+ @visibility = visibility
29
+ end
30
+
31
+ # @return [String]
32
+ def filename
33
+ source.filename
34
+ end
35
+
36
+ # Generate a new Region with the provided attribute changes.
37
+ #
38
+ # @param namespace [String, nil]
39
+ # @param scope [Symbol, nil]
40
+ # @param visibility [Symbol, nil]
41
+ # @return [Region]
42
+ def update namespace: nil, scope: nil, visibility: nil
43
+ Region.new(
44
+ source: source,
45
+ namespace: namespace || self.namespace,
46
+ scope: scope || self.scope,
47
+ visibility: visibility || self.visibility
48
+ )
49
+ end
50
+
51
+ # @param node [Parser::AST::Node]
52
+ # @return [String]
53
+ def code_for node
54
+ source.code_for(node)
55
+ end
56
+ end
57
+ end
58
+ end
@@ -1,3 +1,3 @@
1
- module Solargraph
2
- VERSION = '0.32.1'
3
- end
1
+ module Solargraph
2
+ VERSION = '0.32.2'
3
+ end
@@ -1,53 +1,53 @@
1
- <html>
2
- <head>
3
- <title>Solargraph Environment</title>
4
- </head>
5
- <h1>
6
- Solargraph Environment Info
7
- </h1>
8
- <h2>
9
- System
10
- </h2>
11
- <ul>
12
- <li>
13
- Platform: <%= RUBY_PLATFORM %>
14
- </li>
15
- <li>
16
- Shell: <%= ENV['SHELL'] %>
17
- </li>
18
- <li>
19
- Ruby Version: <%= RUBY_VERSION %>
20
- </li>
21
- </ul>
22
- <h2>
23
- Solargraph
24
- </h2>
25
- <ul>
26
- <li>
27
- Solargraph Version: <%= Solargraph::VERSION %>
28
- </li>
29
- <li>
30
- Core Documentation Version: <%= Solargraph::YardMap::CoreDocs.best_match %>
31
- </li>
32
- <li>
33
- Core Cache Directory: <%= Solargraph::YardMap::CoreDocs.cache_dir %>
34
- </li>
35
- <li>
36
- Parser Target Version: <%= Solargraph::Source.parser.version %>
37
- </li>
38
- <li>
39
- Using Bundler: <%= ENV.key?('BUNDLE_GEMFILE') %>
40
- </li>
41
- </ul>
42
- <h2>
43
- Project
44
- </h2>
45
- <ul>
46
- <li>
47
- Config: <%= config %>
48
- </li>
49
- <li>
50
- Workspace folders: <%= folders %>
51
- </li>
52
- </ul>
53
- </html>
1
+ <html>
2
+ <head>
3
+ <title>Solargraph Environment</title>
4
+ </head>
5
+ <h1>
6
+ Solargraph Environment Info
7
+ </h1>
8
+ <h2>
9
+ System
10
+ </h2>
11
+ <ul>
12
+ <li>
13
+ Platform: <%= RUBY_PLATFORM %>
14
+ </li>
15
+ <li>
16
+ Shell: <%= ENV['SHELL'] %>
17
+ </li>
18
+ <li>
19
+ Ruby Version: <%= RUBY_VERSION %>
20
+ </li>
21
+ </ul>
22
+ <h2>
23
+ Solargraph
24
+ </h2>
25
+ <ul>
26
+ <li>
27
+ Solargraph Version: <%= Solargraph::VERSION %>
28
+ </li>
29
+ <li>
30
+ Core Documentation Version: <%= Solargraph::YardMap::CoreDocs.best_match %>
31
+ </li>
32
+ <li>
33
+ Core Cache Directory: <%= Solargraph::YardMap::CoreDocs.cache_dir %>
34
+ </li>
35
+ <li>
36
+ Parser Target Version: <%= Solargraph::Source.parser.version %>
37
+ </li>
38
+ <li>
39
+ Using Bundler: <%= ENV.key?('BUNDLE_GEMFILE') %>
40
+ </li>
41
+ </ul>
42
+ <h2>
43
+ Project
44
+ </h2>
45
+ <ul>
46
+ <li>
47
+ Config: <%= config %>
48
+ </li>
49
+ <li>
50
+ Workspace folders: <%= folders %>
51
+ </li>
52
+ </ul>
53
+ </html>
@@ -1,183 +1,183 @@
1
- module Solargraph
2
- # A workspace consists of the files in a project's directory and the
3
- # project's configuration. It provides a Source for each file to be used
4
- # in an associated Library or ApiMap.
5
- #
6
- class Workspace
7
- autoload :Config, 'solargraph/workspace/config'
8
-
9
- # @return [String]
10
- attr_reader :directory
11
-
12
- # @param directory [String]
13
- # @param config [Config, nil]
14
- def initialize directory = '', config = nil
15
- @directory = directory
16
- @config = config
17
- load_sources
18
- end
19
-
20
- # @return [Solargraph::Workspace::Config]
21
- def config
22
- @config ||= Solargraph::Workspace::Config.new(directory)
23
- end
24
-
25
- # Merge the source. A merge will update the existing source for the file
26
- # or add it to the sources if the workspace is configured to include it.
27
- # The source is ignored if the configuration excludes it.
28
- #
29
- # @param source [Solargraph::Source]
30
- # @return [Boolean] True if the source was added to the workspace
31
- def merge source
32
- unless directory == '*' || source_hash.key?(source.filename)
33
- # Reload the config to determine if a new source should be included
34
- @config = Solargraph::Workspace::Config.new(directory)
35
- return false unless config.calculated.include?(source.filename)
36
- end
37
- source_hash[source.filename] = source
38
- true
39
- end
40
-
41
- # Determine whether a file would be merged into the workspace.
42
- #
43
- # @param filename [String]
44
- # @return [Boolean]
45
- def would_merge? filename
46
- return true if directory == '*' || source_hash.include?(filename)
47
- @config = Solargraph::Workspace::Config.new(directory)
48
- config.calculated.include?(filename)
49
- end
50
-
51
- # Remove a source from the workspace. The source will not be removed if
52
- # its file exists and the workspace is configured to include it.
53
- #
54
- # @param filename [String]
55
- # @return [Boolean] True if the source was removed from the workspace
56
- def remove filename
57
- return false unless source_hash.key?(filename)
58
- source_hash.delete filename
59
- true
60
- end
61
-
62
- # @return [Array<String>]
63
- def filenames
64
- source_hash.keys
65
- end
66
-
67
- # @return [Array<Solargraph::Source>]
68
- def sources
69
- source_hash.values
70
- end
71
-
72
- # @param filename [String]
73
- # @return [Boolean]
74
- def has_file? filename
75
- source_hash.key?(filename)
76
- end
77
-
78
- # Get a source by its filename.
79
- #
80
- # @param filename [String]
81
- # @return [Solargraph::Source]
82
- def source filename
83
- source_hash[filename]
84
- end
85
-
86
- # The require paths associated with the workspace.
87
- #
88
- # @return [Array<String>]
89
- def require_paths
90
- @require_paths ||= generate_require_paths
91
- end
92
-
93
- # True if the path resolves to a file in the workspace's require paths.
94
- #
95
- # @param path [String]
96
- # @return [Boolean]
97
- def would_require? path
98
- require_paths.each do |rp|
99
- return true if File.exist?(File.join(rp, "#{path}.rb"))
100
- end
101
- false
102
- end
103
-
104
- # True if the workspace contains at least one gemspec file.
105
- #
106
- # @return [Boolean]
107
- def gemspec?
108
- !gemspecs.empty?
109
- end
110
-
111
- # Get an array of all gemspec files in the workspace.
112
- #
113
- # @return [Array<String>]
114
- def gemspecs
115
- return [] if directory.empty? || directory == '*'
116
- @gemspecs ||= Dir[File.join(directory, '**/*.gemspec')]
117
- end
118
-
119
- # Synchronize the workspace from the provided updater.
120
- #
121
- # @param updater [Source::Updater]
122
- # @return [void]
123
- def synchronize! updater
124
- source_hash[updater.filename] = source_hash[updater.filename].synchronize(updater)
125
- end
126
-
127
- private
128
-
129
- # @return [Hash<String, Solargraph::Source>]
130
- def source_hash
131
- @source_hash ||= {}
132
- end
133
-
134
- # @return [void]
135
- def load_sources
136
- source_hash.clear
137
- unless directory.empty? || directory == '*'
138
- size = config.calculated.length
139
- 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
140
- config.calculated.each do |filename|
141
- source_hash[filename] = Solargraph::Source.load(filename)
142
- end
143
- end
144
- end
145
-
146
- # Generate require paths from gemspecs if they exist or assume the default
147
- # lib directory.
148
- #
149
- # @return [Array<String>]
150
- def generate_require_paths
151
- return configured_require_paths unless gemspec?
152
- result = []
153
- gemspecs.each do |file|
154
- base = File.dirname(file)
155
- # @todo Evaluating gemspec files violates the goal of not running
156
- # workspace code, but this is how Gem::Specification.load does it
157
- # anyway.
158
- begin
159
- spec = eval(File.read(file), binding, file)
160
- next unless Gem::Specification === spec
161
- result.concat(spec.require_paths.map { |path| File.join(base, path) })
162
- rescue Exception => e
163
- # Don't die if we have an error during eval-ing a gem spec.
164
- # Concat the default lib directory instead.
165
- Solargraph.logger.warn "Error reading #{file}: [#{e.class}] #{e.message}"
166
- result.push File.join(base, 'lib')
167
- end
168
- end
169
- result.concat config.require_paths
170
- result.push File.join(directory, 'lib') if result.empty?
171
- result
172
- end
173
-
174
- # Get additional require paths defined in the configuration.
175
- #
176
- # @return [Array<String>]
177
- def configured_require_paths
178
- return ['lib'] if directory.empty?
179
- return [File.join(directory, 'lib')] if config.require_paths.empty?
180
- config.require_paths.map{|p| File.join(directory, p)}
181
- end
182
- end
183
- end
1
+ module Solargraph
2
+ # A workspace consists of the files in a project's directory and the
3
+ # project's configuration. It provides a Source for each file to be used
4
+ # in an associated Library or ApiMap.
5
+ #
6
+ class Workspace
7
+ autoload :Config, 'solargraph/workspace/config'
8
+
9
+ # @return [String]
10
+ attr_reader :directory
11
+
12
+ # @param directory [String]
13
+ # @param config [Config, nil]
14
+ def initialize directory = '', config = nil
15
+ @directory = directory
16
+ @config = config
17
+ load_sources
18
+ end
19
+
20
+ # @return [Solargraph::Workspace::Config]
21
+ def config
22
+ @config ||= Solargraph::Workspace::Config.new(directory)
23
+ end
24
+
25
+ # Merge the source. A merge will update the existing source for the file
26
+ # or add it to the sources if the workspace is configured to include it.
27
+ # The source is ignored if the configuration excludes it.
28
+ #
29
+ # @param source [Solargraph::Source]
30
+ # @return [Boolean] True if the source was added to the workspace
31
+ def merge source
32
+ unless directory == '*' || source_hash.key?(source.filename)
33
+ # Reload the config to determine if a new source should be included
34
+ @config = Solargraph::Workspace::Config.new(directory)
35
+ return false unless config.calculated.include?(source.filename)
36
+ end
37
+ source_hash[source.filename] = source
38
+ true
39
+ end
40
+
41
+ # Determine whether a file would be merged into the workspace.
42
+ #
43
+ # @param filename [String]
44
+ # @return [Boolean]
45
+ def would_merge? filename
46
+ return true if directory == '*' || source_hash.include?(filename)
47
+ @config = Solargraph::Workspace::Config.new(directory)
48
+ config.calculated.include?(filename)
49
+ end
50
+
51
+ # Remove a source from the workspace. The source will not be removed if
52
+ # its file exists and the workspace is configured to include it.
53
+ #
54
+ # @param filename [String]
55
+ # @return [Boolean] True if the source was removed from the workspace
56
+ def remove filename
57
+ return false unless source_hash.key?(filename)
58
+ source_hash.delete filename
59
+ true
60
+ end
61
+
62
+ # @return [Array<String>]
63
+ def filenames
64
+ source_hash.keys
65
+ end
66
+
67
+ # @return [Array<Solargraph::Source>]
68
+ def sources
69
+ source_hash.values
70
+ end
71
+
72
+ # @param filename [String]
73
+ # @return [Boolean]
74
+ def has_file? filename
75
+ source_hash.key?(filename)
76
+ end
77
+
78
+ # Get a source by its filename.
79
+ #
80
+ # @param filename [String]
81
+ # @return [Solargraph::Source]
82
+ def source filename
83
+ source_hash[filename]
84
+ end
85
+
86
+ # The require paths associated with the workspace.
87
+ #
88
+ # @return [Array<String>]
89
+ def require_paths
90
+ @require_paths ||= generate_require_paths
91
+ end
92
+
93
+ # True if the path resolves to a file in the workspace's require paths.
94
+ #
95
+ # @param path [String]
96
+ # @return [Boolean]
97
+ def would_require? path
98
+ require_paths.each do |rp|
99
+ return true if File.exist?(File.join(rp, "#{path}.rb"))
100
+ end
101
+ false
102
+ end
103
+
104
+ # True if the workspace contains at least one gemspec file.
105
+ #
106
+ # @return [Boolean]
107
+ def gemspec?
108
+ !gemspecs.empty?
109
+ end
110
+
111
+ # Get an array of all gemspec files in the workspace.
112
+ #
113
+ # @return [Array<String>]
114
+ def gemspecs
115
+ return [] if directory.empty? || directory == '*'
116
+ @gemspecs ||= Dir[File.join(directory, '**/*.gemspec')]
117
+ end
118
+
119
+ # Synchronize the workspace from the provided updater.
120
+ #
121
+ # @param updater [Source::Updater]
122
+ # @return [void]
123
+ def synchronize! updater
124
+ source_hash[updater.filename] = source_hash[updater.filename].synchronize(updater)
125
+ end
126
+
127
+ private
128
+
129
+ # @return [Hash<String, Solargraph::Source>]
130
+ def source_hash
131
+ @source_hash ||= {}
132
+ end
133
+
134
+ # @return [void]
135
+ def load_sources
136
+ source_hash.clear
137
+ unless directory.empty? || directory == '*'
138
+ size = config.calculated.length
139
+ 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
140
+ config.calculated.each do |filename|
141
+ source_hash[filename] = Solargraph::Source.load(filename)
142
+ end
143
+ end
144
+ end
145
+
146
+ # Generate require paths from gemspecs if they exist or assume the default
147
+ # lib directory.
148
+ #
149
+ # @return [Array<String>]
150
+ def generate_require_paths
151
+ return configured_require_paths unless gemspec?
152
+ result = []
153
+ gemspecs.each do |file|
154
+ base = File.dirname(file)
155
+ # @todo Evaluating gemspec files violates the goal of not running
156
+ # workspace code, but this is how Gem::Specification.load does it
157
+ # anyway.
158
+ begin
159
+ spec = eval(File.read(file), binding, file)
160
+ next unless Gem::Specification === spec
161
+ result.concat(spec.require_paths.map { |path| File.join(base, path) })
162
+ rescue Exception => e
163
+ # Don't die if we have an error during eval-ing a gem spec.
164
+ # Concat the default lib directory instead.
165
+ Solargraph.logger.warn "Error reading #{file}: [#{e.class}] #{e.message}"
166
+ result.push File.join(base, 'lib')
167
+ end
168
+ end
169
+ result.concat config.require_paths
170
+ result.push File.join(directory, 'lib') if result.empty?
171
+ result
172
+ end
173
+
174
+ # Get additional require paths defined in the configuration.
175
+ #
176
+ # @return [Array<String>]
177
+ def configured_require_paths
178
+ return ['lib'] if directory.empty?
179
+ return [File.join(directory, 'lib')] if config.require_paths.empty?
180
+ config.require_paths.map{|p| File.join(directory, p)}
181
+ end
182
+ end
183
+ end