solargraph 0.54.4 → 0.57.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.
- checksums.yaml +4 -4
- data/.github/workflows/linting.yml +125 -0
- data/.github/workflows/plugins.yml +149 -5
- data/.github/workflows/rspec.yml +39 -4
- data/.github/workflows/typecheck.yml +8 -3
- data/.gitignore +7 -0
- data/.overcommit.yml +72 -0
- data/.rspec +1 -0
- data/.rubocop.yml +66 -0
- data/.rubocop_todo.yml +2627 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +104 -0
- data/README.md +20 -6
- data/Rakefile +125 -13
- data/lib/solargraph/api_map/cache.rb +3 -2
- data/lib/solargraph/api_map/constants.rb +218 -0
- data/lib/solargraph/api_map/index.rb +44 -42
- data/lib/solargraph/api_map/source_to_yard.rb +10 -4
- data/lib/solargraph/api_map/store.rb +165 -32
- data/lib/solargraph/api_map.rb +319 -243
- data/lib/solargraph/bench.rb +18 -1
- data/lib/solargraph/complex_type/type_methods.rb +7 -1
- data/lib/solargraph/complex_type/unique_type.rb +105 -16
- data/lib/solargraph/complex_type.rb +40 -7
- data/lib/solargraph/convention/active_support_concern.rb +111 -0
- data/lib/solargraph/convention/base.rb +20 -3
- data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -0
- data/lib/solargraph/convention/data_definition/data_definition_node.rb +91 -0
- data/lib/solargraph/convention/data_definition.rb +105 -0
- data/lib/solargraph/convention/gemspec.rb +3 -2
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +61 -0
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +102 -0
- data/lib/solargraph/convention/struct_definition.rb +164 -0
- data/lib/solargraph/convention.rb +35 -4
- data/lib/solargraph/diagnostics/rubocop.rb +6 -1
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +1 -1
- data/lib/solargraph/doc_map.rb +313 -65
- data/lib/solargraph/environ.rb +9 -2
- data/lib/solargraph/gem_pins.rb +60 -38
- data/lib/solargraph/language_server/host/dispatch.rb +2 -0
- data/lib/solargraph/language_server/host/message_worker.rb +13 -7
- data/lib/solargraph/language_server/host.rb +14 -3
- data/lib/solargraph/language_server/message/base.rb +2 -1
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -0
- data/lib/solargraph/language_server/message/extended/document.rb +5 -2
- data/lib/solargraph/language_server/message/extended/document_gems.rb +3 -3
- data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/formatting.rb +16 -2
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +1 -0
- data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +2 -0
- data/lib/solargraph/language_server/progress.rb +8 -0
- data/lib/solargraph/language_server/request.rb +1 -0
- data/lib/solargraph/library.rb +53 -32
- data/lib/solargraph/location.rb +23 -0
- data/lib/solargraph/logging.rb +12 -2
- data/lib/solargraph/page.rb +4 -0
- data/lib/solargraph/parser/comment_ripper.rb +20 -7
- data/lib/solargraph/parser/flow_sensitive_typing.rb +255 -0
- data/lib/solargraph/parser/node_methods.rb +16 -2
- data/lib/solargraph/parser/node_processor/base.rb +10 -5
- data/lib/solargraph/parser/node_processor.rb +26 -9
- data/lib/solargraph/parser/parser_gem/class_methods.rb +17 -15
- data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +13 -11
- data/lib/solargraph/parser/parser_gem/node_methods.rb +8 -4
- data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +21 -0
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +4 -2
- data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +7 -4
- data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +6 -3
- data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +23 -0
- data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +4 -2
- data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +7 -1
- data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +8 -7
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +42 -0
- data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +3 -1
- data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +4 -3
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +63 -30
- data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +3 -1
- data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -0
- data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +29 -0
- data/lib/solargraph/parser/parser_gem/node_processors.rb +14 -0
- data/lib/solargraph/parser/region.rb +4 -1
- data/lib/solargraph/parser/snippet.rb +2 -0
- data/lib/solargraph/parser.rb +1 -0
- data/lib/solargraph/pin/base.rb +360 -30
- data/lib/solargraph/pin/base_variable.rb +16 -10
- data/lib/solargraph/pin/block.rb +2 -0
- data/lib/solargraph/pin/breakable.rb +9 -0
- data/lib/solargraph/pin/callable.rb +83 -3
- data/lib/solargraph/pin/closure.rb +20 -1
- data/lib/solargraph/pin/common.rb +10 -1
- data/lib/solargraph/pin/constant.rb +2 -0
- data/lib/solargraph/pin/delegated_method.rb +21 -1
- data/lib/solargraph/pin/documenting.rb +16 -0
- data/lib/solargraph/pin/keyword.rb +7 -2
- data/lib/solargraph/pin/local_variable.rb +18 -6
- data/lib/solargraph/pin/method.rb +175 -46
- data/lib/solargraph/pin/method_alias.rb +3 -0
- data/lib/solargraph/pin/namespace.rb +17 -9
- data/lib/solargraph/pin/parameter.rb +78 -19
- data/lib/solargraph/pin/proxy_type.rb +13 -6
- data/lib/solargraph/pin/reference/override.rb +24 -6
- data/lib/solargraph/pin/reference/require.rb +2 -2
- data/lib/solargraph/pin/reference/superclass.rb +5 -0
- data/lib/solargraph/pin/reference.rb +26 -0
- data/lib/solargraph/pin/search.rb +3 -1
- data/lib/solargraph/pin/signature.rb +44 -0
- data/lib/solargraph/pin/singleton.rb +1 -1
- data/lib/solargraph/pin/symbol.rb +8 -2
- data/lib/solargraph/pin/until.rb +18 -0
- data/lib/solargraph/pin/while.rb +18 -0
- data/lib/solargraph/pin.rb +4 -1
- data/lib/solargraph/pin_cache.rb +245 -0
- data/lib/solargraph/position.rb +11 -0
- data/lib/solargraph/range.rb +10 -0
- data/lib/solargraph/rbs_map/conversions.rb +226 -70
- data/lib/solargraph/rbs_map/core_fills.rb +32 -16
- data/lib/solargraph/rbs_map/core_map.rb +37 -11
- data/lib/solargraph/rbs_map/stdlib_map.rb +15 -5
- data/lib/solargraph/rbs_map.rb +88 -18
- data/lib/solargraph/shell.rb +20 -18
- data/lib/solargraph/source/chain/array.rb +11 -7
- data/lib/solargraph/source/chain/block_symbol.rb +1 -1
- data/lib/solargraph/source/chain/block_variable.rb +1 -1
- data/lib/solargraph/source/chain/call.rb +53 -23
- data/lib/solargraph/source/chain/constant.rb +1 -1
- data/lib/solargraph/source/chain/hash.rb +4 -3
- data/lib/solargraph/source/chain/head.rb +1 -1
- data/lib/solargraph/source/chain/if.rb +1 -1
- data/lib/solargraph/source/chain/link.rb +12 -1
- data/lib/solargraph/source/chain/literal.rb +22 -2
- data/lib/solargraph/source/chain/or.rb +1 -1
- data/lib/solargraph/source/chain/z_super.rb +1 -1
- data/lib/solargraph/source/chain.rb +84 -47
- data/lib/solargraph/source/change.rb +2 -2
- data/lib/solargraph/source/cursor.rb +2 -3
- data/lib/solargraph/source/source_chainer.rb +3 -3
- data/lib/solargraph/source.rb +5 -2
- data/lib/solargraph/source_map/clip.rb +4 -2
- data/lib/solargraph/source_map/data.rb +4 -0
- data/lib/solargraph/source_map/mapper.rb +13 -7
- data/lib/solargraph/source_map.rb +21 -31
- data/lib/solargraph/type_checker/checks.rb +4 -0
- data/lib/solargraph/type_checker/param_def.rb +2 -0
- data/lib/solargraph/type_checker/rules.rb +8 -0
- data/lib/solargraph/type_checker.rb +208 -128
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/views/_method.erb +10 -10
- data/lib/solargraph/views/_namespace.erb +3 -3
- data/lib/solargraph/views/document.erb +10 -10
- data/lib/solargraph/workspace/config.rb +1 -3
- data/lib/solargraph/workspace/require_paths.rb +98 -0
- data/lib/solargraph/workspace.rb +38 -52
- data/lib/solargraph/yard_map/helpers.rb +29 -1
- data/lib/solargraph/yard_map/mapper/to_constant.rb +7 -5
- data/lib/solargraph/yard_map/mapper/to_method.rb +53 -18
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +9 -7
- data/lib/solargraph/yard_map/mapper.rb +4 -3
- data/lib/solargraph/yard_map/to_method.rb +4 -2
- data/lib/solargraph/yardoc.rb +22 -10
- data/lib/solargraph.rb +34 -1
- data/rbs/fills/tuple.rbs +149 -0
- data/rbs_collection.yaml +19 -0
- data/sig/shims/parser/3.2.0.1/builders/default.rbs +195 -0
- data/sig/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
- data/sig/shims/thor/1.2.0.1/manifest.yaml +7 -0
- data/sig/shims/thor/1.2.0.1/thor.rbs +17 -0
- data/solargraph.gemspec +15 -4
- metadata +157 -15
- data/lib/.rubocop.yml +0 -22
- data/lib/solargraph/cache.rb +0 -77
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'open3'
|
4
|
+
|
5
|
+
module Solargraph
|
6
|
+
# A workspace consists of the files in a project's directory and the
|
7
|
+
# project's configuration. It provides a Source for each file to be used
|
8
|
+
# in an associated Library or ApiMap.
|
9
|
+
#
|
10
|
+
class Workspace
|
11
|
+
# Manages determining which gemspecs are available in a workspace
|
12
|
+
class RequirePaths
|
13
|
+
attr_reader :directory, :config
|
14
|
+
|
15
|
+
# @param directory [String, nil]
|
16
|
+
# @param config [Config, nil]
|
17
|
+
def initialize directory, config
|
18
|
+
@directory = directory
|
19
|
+
@config = config
|
20
|
+
end
|
21
|
+
|
22
|
+
# Generate require paths from gemspecs if they exist or assume the default
|
23
|
+
# lib directory.
|
24
|
+
#
|
25
|
+
# @return [Array<String>]
|
26
|
+
def generate
|
27
|
+
result = require_paths_from_gemspec_files
|
28
|
+
return configured_require_paths if result.empty?
|
29
|
+
result.concat(config.require_paths.map { |p| File.join(directory, p) }) if config
|
30
|
+
result
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# @return [Array<String>]
|
36
|
+
def require_paths_from_gemspec_files
|
37
|
+
results = []
|
38
|
+
gemspec_file_paths.each do |gemspec_file_path|
|
39
|
+
results.concat require_path_from_gemspec_file(gemspec_file_path)
|
40
|
+
end
|
41
|
+
results
|
42
|
+
end
|
43
|
+
|
44
|
+
# Get an array of all gemspec files in the workspace.
|
45
|
+
#
|
46
|
+
# @return [Array<String>]
|
47
|
+
def gemspec_file_paths
|
48
|
+
return [] if directory.nil?
|
49
|
+
@gemspec_file_paths ||= Dir[File.join(directory, '**/*.gemspec')].select do |gs|
|
50
|
+
config.nil? || config.allow?(gs)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Get additional require paths defined in the configuration.
|
55
|
+
#
|
56
|
+
# @return [Array<String>]
|
57
|
+
def configured_require_paths
|
58
|
+
return ['lib'] unless directory
|
59
|
+
return [File.join(directory, 'lib')] if !config || config.require_paths.empty?
|
60
|
+
config.require_paths.map { |p| File.join(directory, p) }
|
61
|
+
end
|
62
|
+
|
63
|
+
# Generate require paths from gemspecs if they exist or assume the default
|
64
|
+
# lib directory.
|
65
|
+
#
|
66
|
+
# @param gemspec_file_path [String]
|
67
|
+
# @return [Array<String>]
|
68
|
+
def require_path_from_gemspec_file gemspec_file_path
|
69
|
+
base = File.dirname(gemspec_file_path)
|
70
|
+
# HACK: Evaluating gemspec files violates the goal of not running
|
71
|
+
# workspace code, but this is how Gem::Specification.load does it
|
72
|
+
# anyway.
|
73
|
+
cmd = ['ruby', '-e',
|
74
|
+
"require 'rubygems'; " \
|
75
|
+
"require 'json'; " \
|
76
|
+
"spec = eval(File.read('#{gemspec_file_path}'), TOPLEVEL_BINDING, '#{gemspec_file_path}'); " \
|
77
|
+
'return unless Gem::Specification === spec; ' \
|
78
|
+
'puts({name: spec.name, paths: spec.require_paths}.to_json)']
|
79
|
+
# @sg-ignore Unresolved call to capture3 on Module<Open3>
|
80
|
+
o, e, s = Open3.capture3(*cmd)
|
81
|
+
if s.success?
|
82
|
+
begin
|
83
|
+
hash = o && !o.empty? ? JSON.parse(o.split("\n").last) : {}
|
84
|
+
return [] if hash.empty?
|
85
|
+
hash['paths'].map { |path| File.join(base, path) }
|
86
|
+
rescue StandardError => e
|
87
|
+
Solargraph.logger.warn "Error reading #{gemspec_file_path}: [#{e.class}] #{e.message}"
|
88
|
+
[]
|
89
|
+
end
|
90
|
+
else
|
91
|
+
Solargraph.logger.warn "Error reading #{gemspec_file_path}"
|
92
|
+
Solargraph.logger.warn e
|
93
|
+
[]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
data/lib/solargraph/workspace.rb
CHANGED
@@ -10,15 +10,11 @@ module Solargraph
|
|
10
10
|
#
|
11
11
|
class Workspace
|
12
12
|
autoload :Config, 'solargraph/workspace/config'
|
13
|
+
autoload :RequirePaths, 'solargraph/workspace/require_paths'
|
13
14
|
|
14
15
|
# @return [String]
|
15
16
|
attr_reader :directory
|
16
17
|
|
17
|
-
# The require paths associated with the workspace.
|
18
|
-
#
|
19
|
-
# @return [Array<String>]
|
20
|
-
attr_reader :require_paths
|
21
|
-
|
22
18
|
# @return [Array<String>]
|
23
19
|
attr_reader :gemnames
|
24
20
|
alias source_gems gemnames
|
@@ -32,10 +28,17 @@ module Solargraph
|
|
32
28
|
@server = server
|
33
29
|
load_sources
|
34
30
|
@gemnames = []
|
35
|
-
@require_paths = generate_require_paths
|
36
31
|
require_plugins
|
37
32
|
end
|
38
33
|
|
34
|
+
# The require paths associated with the workspace.
|
35
|
+
#
|
36
|
+
# @return [Array<String>]
|
37
|
+
def require_paths
|
38
|
+
# @todo are the semantics of '*' the same as '', meaning 'don't send back any require paths'?
|
39
|
+
@require_paths ||= RequirePaths.new(directory_or_nil, config).generate
|
40
|
+
end
|
41
|
+
|
39
42
|
# @return [Solargraph::Workspace::Config]
|
40
43
|
def config
|
41
44
|
@config ||= Solargraph::Workspace::Config.new(directory)
|
@@ -106,7 +109,7 @@ module Solargraph
|
|
106
109
|
def would_require? path
|
107
110
|
require_paths.each do |rp|
|
108
111
|
full = File.join rp, path
|
109
|
-
return true if File.
|
112
|
+
return true if File.file?(full) || File.file?(full << ".rb")
|
110
113
|
end
|
111
114
|
false
|
112
115
|
end
|
@@ -133,6 +136,16 @@ module Solargraph
|
|
133
136
|
@gem_rbs_collection ||= read_rbs_collection_path
|
134
137
|
end
|
135
138
|
|
139
|
+
# @return [String, nil]
|
140
|
+
def rbs_collection_config_path
|
141
|
+
@rbs_collection_config_path ||= begin
|
142
|
+
unless directory.empty? || directory == '*'
|
143
|
+
yaml_file = File.join(directory, 'rbs_collection.yaml')
|
144
|
+
yaml_file if File.file?(yaml_file)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
136
149
|
# Synchronize the workspace from the provided updater.
|
137
150
|
#
|
138
151
|
# @param updater [Source::Updater]
|
@@ -146,6 +159,20 @@ module Solargraph
|
|
146
159
|
server['commandPath'] || 'solargraph'
|
147
160
|
end
|
148
161
|
|
162
|
+
# @return [String, nil]
|
163
|
+
def directory_or_nil
|
164
|
+
return nil if directory.empty? || directory == '*'
|
165
|
+
directory
|
166
|
+
end
|
167
|
+
|
168
|
+
# True if the workspace has a root Gemfile.
|
169
|
+
#
|
170
|
+
# @todo Handle projects with custom Bundler/Gemfile setups (see DocMap#gemspecs_required_from_bundler)
|
171
|
+
#
|
172
|
+
def gemfile?
|
173
|
+
directory && File.file?(File.join(directory, 'Gemfile'))
|
174
|
+
end
|
175
|
+
|
149
176
|
private
|
150
177
|
|
151
178
|
# The language server configuration (or an empty hash if the workspace was
|
@@ -175,48 +202,6 @@ module Solargraph
|
|
175
202
|
end
|
176
203
|
end
|
177
204
|
|
178
|
-
# Generate require paths from gemspecs if they exist or assume the default
|
179
|
-
# lib directory.
|
180
|
-
#
|
181
|
-
# @return [Array<String>]
|
182
|
-
def generate_require_paths
|
183
|
-
return configured_require_paths unless gemspec?
|
184
|
-
result = []
|
185
|
-
gemspecs.each do |file|
|
186
|
-
base = File.dirname(file)
|
187
|
-
# HACK: Evaluating gemspec files violates the goal of not running
|
188
|
-
# workspace code, but this is how Gem::Specification.load does it
|
189
|
-
# anyway.
|
190
|
-
cmd = ['ruby', '-e', "require 'rubygems'; require 'json'; spec = eval(File.read('#{file}'), TOPLEVEL_BINDING, '#{file}'); return unless Gem::Specification === spec; puts({name: spec.name, paths: spec.require_paths}.to_json)"]
|
191
|
-
o, e, s = Open3.capture3(*cmd)
|
192
|
-
if s.success?
|
193
|
-
begin
|
194
|
-
hash = o && !o.empty? ? JSON.parse(o.split("\n").last) : {}
|
195
|
-
next if hash.empty?
|
196
|
-
@gemnames.push hash['name']
|
197
|
-
result.concat(hash['paths'].map { |path| File.join(base, path) })
|
198
|
-
rescue StandardError => e
|
199
|
-
Solargraph.logger.warn "Error reading #{file}: [#{e.class}] #{e.message}"
|
200
|
-
end
|
201
|
-
else
|
202
|
-
Solargraph.logger.warn "Error reading #{file}"
|
203
|
-
Solargraph.logger.warn e
|
204
|
-
end
|
205
|
-
end
|
206
|
-
result.concat(config.require_paths.map { |p| File.join(directory, p) })
|
207
|
-
result.push File.join(directory, 'lib') if result.empty?
|
208
|
-
result
|
209
|
-
end
|
210
|
-
|
211
|
-
# Get additional require paths defined in the configuration.
|
212
|
-
#
|
213
|
-
# @return [Array<String>]
|
214
|
-
def configured_require_paths
|
215
|
-
return ['lib'] if directory.empty?
|
216
|
-
return [File.join(directory, 'lib')] if config.require_paths.empty?
|
217
|
-
config.require_paths.map{|p| File.join(directory, p)}
|
218
|
-
end
|
219
|
-
|
220
205
|
# @return [void]
|
221
206
|
def require_plugins
|
222
207
|
config.plugins.each do |plugin|
|
@@ -230,10 +215,11 @@ module Solargraph
|
|
230
215
|
|
231
216
|
# @return [String, nil]
|
232
217
|
def read_rbs_collection_path
|
233
|
-
|
234
|
-
return unless File.file?(yaml_file)
|
218
|
+
return unless rbs_collection_config_path
|
235
219
|
|
236
|
-
YAML.load_file(
|
220
|
+
path = YAML.load_file(rbs_collection_config_path)&.fetch('path')
|
221
|
+
# make fully qualified
|
222
|
+
File.expand_path(path, directory)
|
237
223
|
end
|
238
224
|
end
|
239
225
|
end
|
@@ -7,10 +7,38 @@ module Solargraph
|
|
7
7
|
# @param spec [Gem::Specification, nil]
|
8
8
|
# @return [Solargraph::Location, nil]
|
9
9
|
def object_location code_object, spec
|
10
|
-
|
10
|
+
if spec.nil? || code_object.nil? || code_object.file.nil? || code_object.line.nil?
|
11
|
+
if code_object.namespace.is_a?(YARD::CodeObjects::NamespaceObject)
|
12
|
+
# If the code object is a namespace, use the namespace's location
|
13
|
+
return object_location(code_object.namespace, spec)
|
14
|
+
end
|
15
|
+
return Solargraph::Location.new(__FILE__, Solargraph::Range.from_to(__LINE__ - 1, 0, __LINE__ - 1, 0))
|
16
|
+
end
|
11
17
|
file = File.join(spec.full_gem_path, code_object.file)
|
12
18
|
Solargraph::Location.new(file, Solargraph::Range.from_to(code_object.line - 1, 0, code_object.line - 1, 0))
|
13
19
|
end
|
20
|
+
|
21
|
+
# @param code_object [YARD::CodeObjects::Base]
|
22
|
+
# @param spec [Gem::Specification, nil]
|
23
|
+
# @return [Solargraph::Pin::Namespace]
|
24
|
+
def create_closure_namespace_for(code_object, spec)
|
25
|
+
code_object_for_location = code_object
|
26
|
+
# code_object.namespace is sometimes a YARD proxy object pointing to a method path ("Object#new")
|
27
|
+
code_object_for_location = code_object.namespace if code_object.namespace.is_a?(YARD::CodeObjects::NamespaceObject)
|
28
|
+
namespace_location = object_location(code_object_for_location, spec)
|
29
|
+
ns_name = code_object.namespace.to_s
|
30
|
+
if ns_name.empty?
|
31
|
+
Solargraph::Pin::ROOT_PIN
|
32
|
+
else
|
33
|
+
Solargraph::Pin::Namespace.new(
|
34
|
+
name: ns_name,
|
35
|
+
closure: Pin::ROOT_PIN,
|
36
|
+
gates: [code_object.namespace.to_s],
|
37
|
+
source: :yardoc,
|
38
|
+
location: namespace_location
|
39
|
+
)
|
40
|
+
end
|
41
|
+
end
|
14
42
|
end
|
15
43
|
end
|
16
44
|
end
|
@@ -7,17 +7,19 @@ module Solargraph
|
|
7
7
|
extend YardMap::Helpers
|
8
8
|
|
9
9
|
# @param code_object [YARD::CodeObjects::Base]
|
10
|
+
# @param closure [Pin::Closure, nil]
|
11
|
+
# @param spec [Gem::Specification, nil]
|
12
|
+
# @return [Pin::Constant]
|
10
13
|
def self.make code_object, closure = nil, spec = nil
|
11
|
-
closure ||=
|
12
|
-
|
13
|
-
gates: [code_object.namespace.to_s]
|
14
|
-
)
|
14
|
+
closure ||= create_closure_namespace_for(code_object, spec)
|
15
|
+
|
15
16
|
Pin::Constant.new(
|
16
17
|
location: object_location(code_object, spec),
|
17
18
|
closure: closure,
|
18
19
|
name: code_object.name.to_s,
|
19
20
|
comments: code_object.docstring ? code_object.docstring.all.to_s : '',
|
20
|
-
visibility: code_object.visibility
|
21
|
+
visibility: code_object.visibility,
|
22
|
+
source: :yardoc
|
21
23
|
)
|
22
24
|
end
|
23
25
|
end
|
@@ -6,6 +6,11 @@ module Solargraph
|
|
6
6
|
module ToMethod
|
7
7
|
extend YardMap::Helpers
|
8
8
|
|
9
|
+
VISIBILITY_OVERRIDE = {
|
10
|
+
# YARD pays attention to 'private' statements prior to class methods but shouldn't
|
11
|
+
["Rails::Engine", :class, "find_root_with_flag"] => :public
|
12
|
+
}
|
13
|
+
|
9
14
|
# @param code_object [YARD::CodeObjects::Base]
|
10
15
|
# @param name [String, nil]
|
11
16
|
# @param scope [Symbol, nil]
|
@@ -14,31 +19,60 @@ module Solargraph
|
|
14
19
|
# @param spec [Gem::Specification, nil]
|
15
20
|
# @return [Solargraph::Pin::Method]
|
16
21
|
def self.make code_object, name = nil, scope = nil, visibility = nil, closure = nil, spec = nil
|
17
|
-
closure ||=
|
18
|
-
name: code_object.namespace.to_s,
|
19
|
-
gates: [code_object.namespace.to_s]
|
20
|
-
)
|
22
|
+
closure ||= create_closure_namespace_for(code_object, spec)
|
21
23
|
location = object_location(code_object, spec)
|
22
24
|
name ||= code_object.name.to_s
|
23
25
|
return_type = ComplexType::SELF if name == 'new'
|
24
26
|
comments = code_object.docstring ? code_object.docstring.all.to_s : ''
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
27
|
+
final_scope = scope || code_object.scope
|
28
|
+
override_key = [closure.path, final_scope, name]
|
29
|
+
final_visibility = VISIBILITY_OVERRIDE[override_key]
|
30
|
+
final_visibility ||= VISIBILITY_OVERRIDE[[closure.path, final_scope]]
|
31
|
+
final_visibility ||= :private if closure.path == 'Kernel' && Kernel.private_instance_methods(false).include?(name.to_sym)
|
32
|
+
final_visibility ||= visibility
|
33
|
+
final_visibility ||= :private if code_object.module_function? && final_scope == :instance
|
34
|
+
final_visibility ||= :public if code_object.module_function? && final_scope == :class
|
35
|
+
final_visibility ||= code_object.visibility
|
36
|
+
if code_object.is_alias?
|
37
|
+
origin_code_object = code_object.namespace.aliases[code_object]
|
38
|
+
pin = Pin::MethodAlias.new(
|
39
|
+
name: name,
|
40
|
+
location: location,
|
41
|
+
original: origin_code_object.name.to_s,
|
42
|
+
closure: closure,
|
43
|
+
comments: comments,
|
44
|
+
scope: final_scope,
|
45
|
+
visibility: final_visibility,
|
46
|
+
explicit: code_object.is_explicit?,
|
47
|
+
return_type: return_type,
|
48
|
+
parameters: [],
|
49
|
+
source: :yardoc,
|
50
|
+
)
|
51
|
+
else
|
52
|
+
pin = Pin::Method.new(
|
53
|
+
location: location,
|
54
|
+
closure: closure,
|
55
|
+
name: name,
|
56
|
+
comments: comments,
|
57
|
+
scope: final_scope,
|
58
|
+
visibility: final_visibility,
|
59
|
+
# @todo Might need to convert overloads to signatures
|
60
|
+
explicit: code_object.is_explicit?,
|
61
|
+
return_type: return_type,
|
62
|
+
attribute: code_object.is_attribute?,
|
63
|
+
parameters: [],
|
64
|
+
source: :yardoc,
|
65
|
+
)
|
66
|
+
pin.parameters.concat get_parameters(code_object, location, comments, pin)
|
67
|
+
pin.parameters.freeze
|
68
|
+
end
|
69
|
+
logger.debug { "ToMethod.make: Just created method pin: #{pin.inspect}" }
|
38
70
|
pin
|
39
71
|
end
|
40
72
|
|
41
73
|
class << self
|
74
|
+
include Logging
|
75
|
+
|
42
76
|
private
|
43
77
|
|
44
78
|
# @param code_object [YARD::CodeObjects::Base]
|
@@ -59,7 +93,8 @@ module Solargraph
|
|
59
93
|
name: arg_name(a),
|
60
94
|
presence: nil,
|
61
95
|
decl: arg_type(a),
|
62
|
-
asgn_code: a[1]
|
96
|
+
asgn_code: a[1],
|
97
|
+
source: :yardoc,
|
63
98
|
)
|
64
99
|
end
|
65
100
|
end
|
@@ -7,19 +7,21 @@ module Solargraph
|
|
7
7
|
extend YardMap::Helpers
|
8
8
|
|
9
9
|
# @param code_object [YARD::CodeObjects::NamespaceObject]
|
10
|
+
# @param spec [Gem::Specification, nil]
|
11
|
+
# @param closure [Pin::Closure, nil]
|
12
|
+
# @return [Pin::Namespace]
|
10
13
|
def self.make code_object, spec, closure = nil
|
11
|
-
closure ||=
|
12
|
-
|
13
|
-
|
14
|
-
gates: [code_object.namespace.to_s]
|
15
|
-
)
|
14
|
+
closure ||= create_closure_namespace_for(code_object, spec)
|
15
|
+
location = object_location(code_object, spec)
|
16
|
+
|
16
17
|
Pin::Namespace.new(
|
17
|
-
location:
|
18
|
+
location: location,
|
18
19
|
name: code_object.name.to_s,
|
19
20
|
comments: code_object.docstring ? code_object.docstring.all.to_s : '',
|
20
21
|
type: code_object.is_a?(YARD::CodeObjects::ClassObject) ? :class : :module,
|
21
22
|
visibility: code_object.visibility,
|
22
|
-
closure: closure
|
23
|
+
closure: closure,
|
24
|
+
source: :yardoc,
|
23
25
|
)
|
24
26
|
end
|
25
27
|
end
|
@@ -47,15 +47,16 @@ module Solargraph
|
|
47
47
|
else
|
48
48
|
code_object.superclass.to_s
|
49
49
|
end
|
50
|
-
result.push Solargraph::Pin::Reference::Superclass.new(name: superclass, closure: nspin)
|
50
|
+
result.push Solargraph::Pin::Reference::Superclass.new(name: superclass, closure: nspin, source: :yard_map)
|
51
51
|
end
|
52
52
|
code_object.class_mixins.each do |m|
|
53
|
-
result.push Solargraph::Pin::Reference::Extend.new(closure: nspin, name: m.path)
|
53
|
+
result.push Solargraph::Pin::Reference::Extend.new(closure: nspin, name: m.path, source: :yard_map)
|
54
54
|
end
|
55
55
|
code_object.instance_mixins.each do |m|
|
56
56
|
result.push Solargraph::Pin::Reference::Include.new(
|
57
57
|
closure: nspin, # @todo Fix this
|
58
|
-
name: m.path
|
58
|
+
name: m.path,
|
59
|
+
source: :yard_map
|
59
60
|
)
|
60
61
|
end
|
61
62
|
elsif code_object.is_a?(YARD::CodeObjects::MethodObject)
|
@@ -23,7 +23,8 @@ module Solargraph
|
|
23
23
|
name: arg_name(a),
|
24
24
|
presence: nil,
|
25
25
|
decl: arg_type(a),
|
26
|
-
asgn_code: a[1]
|
26
|
+
asgn_code: a[1],
|
27
|
+
source: :yard_map
|
27
28
|
)
|
28
29
|
end
|
29
30
|
end
|
@@ -78,7 +79,8 @@ module Solargraph
|
|
78
79
|
scope: scope || code_object.scope,
|
79
80
|
visibility: visibility || code_object.visibility,
|
80
81
|
parameters: InnerMethods.get_parameters(code_object, location, comments),
|
81
|
-
explicit: code_object.is_explicit
|
82
|
+
explicit: code_object.is_explicit?,
|
83
|
+
source: :yard_map
|
82
84
|
)
|
83
85
|
end
|
84
86
|
end
|
data/lib/solargraph/yardoc.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'open3'
|
4
|
+
|
3
5
|
module Solargraph
|
4
6
|
# Methods for caching and loading YARD documentation for gems.
|
5
7
|
#
|
@@ -9,15 +11,25 @@ module Solargraph
|
|
9
11
|
# Build and cache a gem's yardoc and return the path. If the cache already
|
10
12
|
# exists, do nothing and return the path.
|
11
13
|
#
|
14
|
+
# @param yard_plugins [Array<String>] The names of YARD plugins to use.
|
12
15
|
# @param gemspec [Gem::Specification]
|
13
16
|
# @return [String] The path to the cached yardoc.
|
14
|
-
def cache(gemspec)
|
15
|
-
path =
|
17
|
+
def cache(yard_plugins, gemspec)
|
18
|
+
path = PinCache.yardoc_path gemspec
|
16
19
|
return path if cached?(gemspec)
|
17
20
|
|
18
21
|
Solargraph.logger.info "Caching yardoc for #{gemspec.name} #{gemspec.version}"
|
19
|
-
|
20
|
-
|
22
|
+
cmd = "yardoc --db #{path} --no-output --plugin solargraph"
|
23
|
+
yard_plugins.each { |plugin| cmd << " --plugin #{plugin}" }
|
24
|
+
Solargraph.logger.debug { "Running: #{cmd}" }
|
25
|
+
# @todo set these up to run in parallel
|
26
|
+
#
|
27
|
+
# @sg-ignore RBS gem doesn't reflect that Open3.* also include
|
28
|
+
# kwopts from Process.spawn()
|
29
|
+
stdout_and_stderr_str, status = Open3.capture2e(cmd, chdir: gemspec.gem_dir)
|
30
|
+
unless status.success?
|
31
|
+
Solargraph.logger.warn { "YARD failed running #{cmd.inspect} in #{gemspec.gem_dir}" }
|
32
|
+
Solargraph.logger.info stdout_and_stderr_str
|
21
33
|
end
|
22
34
|
path
|
23
35
|
end
|
@@ -26,16 +38,16 @@ module Solargraph
|
|
26
38
|
#
|
27
39
|
# @param gemspec [Gem::Specification]
|
28
40
|
def cached?(gemspec)
|
29
|
-
yardoc = File.join(
|
41
|
+
yardoc = File.join(PinCache.yardoc_path(gemspec), 'complete')
|
30
42
|
File.exist?(yardoc)
|
31
43
|
end
|
32
44
|
|
33
|
-
#
|
45
|
+
# True if another process is currently building the yardoc cache.
|
34
46
|
#
|
35
47
|
# @param gemspec [Gem::Specification]
|
36
|
-
|
37
|
-
|
38
|
-
File.
|
48
|
+
def processing?(gemspec)
|
49
|
+
yardoc = File.join(PinCache.yardoc_path(gemspec), 'processing')
|
50
|
+
File.exist?(yardoc)
|
39
51
|
end
|
40
52
|
|
41
53
|
# Load a gem's yardoc and return its code objects.
|
@@ -45,7 +57,7 @@ module Solargraph
|
|
45
57
|
# @param gemspec [Gem::Specification]
|
46
58
|
# @return [Array<YARD::CodeObjects::Base>]
|
47
59
|
def load!(gemspec)
|
48
|
-
YARD::Registry.load!
|
60
|
+
YARD::Registry.load! PinCache.yardoc_path gemspec
|
49
61
|
YARD::Registry.all
|
50
62
|
end
|
51
63
|
end
|
data/lib/solargraph.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
Encoding.default_external = 'UTF-8'
|
4
4
|
|
5
|
+
require 'bundler'
|
5
6
|
require 'set'
|
6
7
|
require 'yard-solargraph'
|
7
8
|
require 'solargraph/yard_tags'
|
@@ -47,11 +48,34 @@ module Solargraph
|
|
47
48
|
autoload :Parser, 'solargraph/parser'
|
48
49
|
autoload :RbsMap, 'solargraph/rbs_map'
|
49
50
|
autoload :GemPins, 'solargraph/gem_pins'
|
50
|
-
autoload :
|
51
|
+
autoload :PinCache, 'solargraph/pin_cache'
|
51
52
|
|
52
53
|
dir = File.dirname(__FILE__)
|
53
54
|
VIEWS_PATH = File.join(dir, 'solargraph', 'views')
|
54
55
|
|
56
|
+
CHDIR_MUTEX = Mutex.new
|
57
|
+
|
58
|
+
# @param type [Symbol] Type of assert.
|
59
|
+
def self.asserts_on?(type)
|
60
|
+
if ENV['SOLARGRAPH_ASSERTS'].nil? || ENV['SOLARGRAPH_ASSERTS'].empty?
|
61
|
+
false
|
62
|
+
elsif ENV['SOLARGRAPH_ASSERTS'] == 'on'
|
63
|
+
true
|
64
|
+
else
|
65
|
+
logger.warn "Unrecognized SOLARGRAPH_ASSERTS value: #{ENV['SOLARGRAPH_ASSERTS']}"
|
66
|
+
false
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# @param type [Symbol] The type of assertion to perform.
|
71
|
+
# @param msg [String, nil] An optional message to log
|
72
|
+
# @param block [Proc] A block that returns a message to log
|
73
|
+
# @return [void]
|
74
|
+
def self.assert_or_log(type, msg = nil, &block)
|
75
|
+
raise (msg || block.call) if asserts_on?(type) && ![:combine_with_visibility].include?(type)
|
76
|
+
logger.info msg, &block
|
77
|
+
end
|
78
|
+
|
55
79
|
# A convenience method for Solargraph::Logging.logger.
|
56
80
|
#
|
57
81
|
# @return [Logger]
|
@@ -61,6 +85,11 @@ module Solargraph
|
|
61
85
|
|
62
86
|
# A helper method that runs Bundler.with_unbundled_env or falls back to
|
63
87
|
# Bundler.with_clean_env for earlier versions of Bundler.
|
88
|
+
#
|
89
|
+
# @generic T
|
90
|
+
# @yieldreturn [generic<T>]
|
91
|
+
# @sg-ignore dynamic call, but both functions behave the same
|
92
|
+
# @return [generic<T>]
|
64
93
|
def self.with_clean_env &block
|
65
94
|
meth = if Bundler.respond_to?(:with_original_env)
|
66
95
|
:with_original_env
|
@@ -70,3 +99,7 @@ module Solargraph
|
|
70
99
|
Bundler.send meth, &block
|
71
100
|
end
|
72
101
|
end
|
102
|
+
|
103
|
+
# Ensure that ParserGem node processors are properly loaded to avoid conflicts
|
104
|
+
# with Convention node processors
|
105
|
+
require 'solargraph/parser/parser_gem/node_processors'
|