solargraph 0.56.2 → 0.58.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 +127 -0
- data/.github/workflows/plugins.yml +183 -7
- data/.github/workflows/rspec.yml +55 -5
- data/.github/workflows/typecheck.yml +6 -3
- data/.gitignore +5 -0
- data/.overcommit.yml +72 -0
- data/.rspec +1 -0
- data/.rubocop.yml +66 -0
- data/.rubocop_todo.yml +1279 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +69 -0
- data/README.md +8 -4
- data/Rakefile +125 -13
- data/bin/solargraph +8 -5
- data/lib/solargraph/api_map/cache.rb +3 -2
- data/lib/solargraph/api_map/constants.rb +279 -0
- data/lib/solargraph/api_map/index.rb +49 -31
- data/lib/solargraph/api_map/source_to_yard.rb +13 -4
- data/lib/solargraph/api_map/store.rb +144 -26
- data/lib/solargraph/api_map.rb +217 -245
- data/lib/solargraph/bench.rb +1 -0
- data/lib/solargraph/complex_type/type_methods.rb +6 -0
- data/lib/solargraph/complex_type/unique_type.rb +19 -12
- data/lib/solargraph/complex_type.rb +24 -3
- data/lib/solargraph/convention/active_support_concern.rb +111 -0
- data/lib/solargraph/convention/base.rb +17 -0
- data/lib/solargraph/convention/data_definition/data_assignment_node.rb +1 -0
- data/lib/solargraph/convention/data_definition/data_definition_node.rb +4 -2
- data/lib/solargraph/convention/data_definition.rb +2 -1
- data/lib/solargraph/convention/gemspec.rb +1 -1
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +1 -0
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +3 -1
- data/lib/solargraph/convention/struct_definition.rb +36 -13
- data/lib/solargraph/convention.rb +31 -2
- data/lib/solargraph/diagnostics/rubocop.rb +6 -1
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
- data/lib/solargraph/doc_map.rb +44 -13
- data/lib/solargraph/environ.rb +9 -2
- data/lib/solargraph/equality.rb +1 -0
- data/lib/solargraph/gem_pins.rb +21 -11
- data/lib/solargraph/language_server/host/dispatch.rb +2 -0
- data/lib/solargraph/language_server/host/message_worker.rb +3 -0
- data/lib/solargraph/language_server/host.rb +12 -5
- data/lib/solargraph/language_server/message/base.rb +2 -1
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +1 -1
- data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/formatting.rb +19 -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 +4 -1
- data/lib/solargraph/library.rb +11 -18
- data/lib/solargraph/location.rb +3 -0
- data/lib/solargraph/logging.rb +11 -2
- data/lib/solargraph/page.rb +3 -0
- data/lib/solargraph/parser/comment_ripper.rb +8 -1
- data/lib/solargraph/parser/flow_sensitive_typing.rb +33 -5
- data/lib/solargraph/parser/node_processor/base.rb +1 -1
- data/lib/solargraph/parser/node_processor.rb +6 -2
- data/lib/solargraph/parser/parser_gem/class_methods.rb +3 -13
- data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +3 -1
- data/lib/solargraph/parser/parser_gem/node_methods.rb +5 -16
- data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +3 -2
- data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +2 -0
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -0
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +64 -8
- data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +12 -3
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +36 -16
- data/lib/solargraph/parser/region.rb +3 -0
- data/lib/solargraph/parser/snippet.rb +2 -0
- data/lib/solargraph/pin/base.rb +77 -14
- data/lib/solargraph/pin/base_variable.rb +6 -5
- data/lib/solargraph/pin/block.rb +3 -2
- data/lib/solargraph/pin/callable.rb +14 -1
- data/lib/solargraph/pin/closure.rb +5 -7
- data/lib/solargraph/pin/common.rb +6 -2
- data/lib/solargraph/pin/constant.rb +2 -0
- data/lib/solargraph/pin/local_variable.rb +1 -2
- data/lib/solargraph/pin/method.rb +28 -9
- data/lib/solargraph/pin/method_alias.rb +3 -0
- data/lib/solargraph/pin/parameter.rb +24 -10
- data/lib/solargraph/pin/proxy_type.rb +5 -1
- data/lib/solargraph/pin/reference/override.rb +15 -1
- data/lib/solargraph/pin/reference/superclass.rb +5 -0
- data/lib/solargraph/pin/reference.rb +17 -0
- data/lib/solargraph/pin/search.rb +6 -1
- data/lib/solargraph/pin/signature.rb +2 -0
- data/lib/solargraph/pin/symbol.rb +5 -0
- data/lib/solargraph/pin_cache.rb +64 -4
- data/lib/solargraph/position.rb +3 -0
- data/lib/solargraph/range.rb +5 -0
- data/lib/solargraph/rbs_map/conversions.rb +29 -6
- data/lib/solargraph/rbs_map/core_fills.rb +18 -0
- data/lib/solargraph/rbs_map/core_map.rb +14 -7
- data/lib/solargraph/rbs_map.rb +14 -1
- data/lib/solargraph/shell.rb +85 -1
- data/lib/solargraph/source/chain/call.rb +7 -3
- data/lib/solargraph/source/chain/constant.rb +3 -66
- data/lib/solargraph/source/chain/if.rb +1 -1
- data/lib/solargraph/source/chain/link.rb +11 -2
- data/lib/solargraph/source/chain/or.rb +1 -1
- data/lib/solargraph/source/chain.rb +11 -2
- data/lib/solargraph/source/change.rb +2 -2
- data/lib/solargraph/source/cursor.rb +2 -3
- data/lib/solargraph/source/source_chainer.rb +1 -1
- data/lib/solargraph/source.rb +6 -3
- data/lib/solargraph/source_map/clip.rb +18 -26
- data/lib/solargraph/source_map/data.rb +4 -0
- data/lib/solargraph/source_map/mapper.rb +2 -2
- data/lib/solargraph/source_map.rb +28 -16
- data/lib/solargraph/type_checker/param_def.rb +2 -0
- data/lib/solargraph/type_checker/rules.rb +30 -8
- data/lib/solargraph/type_checker.rb +301 -186
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +21 -5
- data/lib/solargraph/workspace/require_paths.rb +97 -0
- data/lib/solargraph/workspace.rb +30 -67
- data/lib/solargraph/yard_map/mapper/to_method.rb +4 -3
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -0
- data/lib/solargraph/yard_map/to_method.rb +2 -1
- data/lib/solargraph/yardoc.rb +39 -3
- data/lib/solargraph.rb +2 -0
- data/rbs/fills/bundler/0/bundler.rbs +4271 -0
- data/rbs/fills/open3/0/open3.rbs +172 -0
- data/rbs/fills/rubygems/0/basic_specification.rbs +326 -0
- data/rbs/fills/rubygems/0/errors.rbs +364 -0
- data/rbs/fills/rubygems/0/spec_fetcher.rbs +107 -0
- data/rbs/fills/rubygems/0/specification.rbs +1753 -0
- data/rbs/fills/{tuple.rbs → tuple/tuple.rbs} +2 -3
- data/rbs_collection.yaml +4 -4
- data/sig/shims/ast/0/node.rbs +5 -0
- data/sig/shims/ast/2.4/.rbs_meta.yaml +9 -0
- data/sig/shims/ast/2.4/ast.rbs +73 -0
- data/sig/shims/parser/3.2.0.1/builders/default.rbs +195 -0
- data/sig/shims/parser/3.2.0.1/manifest.yaml +7 -0
- data/sig/shims/parser/3.2.0.1/parser.rbs +201 -0
- data/sig/shims/parser/3.2.0.1/polyfill.rbs +4 -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 +26 -5
- metadata +181 -13
- data/lib/.rubocop.yml +0 -22
- data/lib/solargraph/parser/node_methods.rb +0 -97
data/lib/solargraph/version.rb
CHANGED
|
@@ -14,8 +14,8 @@ module Solargraph
|
|
|
14
14
|
# @return [String]
|
|
15
15
|
attr_reader :directory
|
|
16
16
|
|
|
17
|
-
# @todo To make
|
|
18
|
-
# @return [Hash{String =>
|
|
17
|
+
# @todo To make JSON strongly typed we'll need a record syntax
|
|
18
|
+
# @return [Hash{String => undefined, nil}]
|
|
19
19
|
attr_reader :raw_data
|
|
20
20
|
|
|
21
21
|
# @param directory [String]
|
|
@@ -63,6 +63,7 @@ module Solargraph
|
|
|
63
63
|
# namespace. It's typically used to identify available DSLs.
|
|
64
64
|
#
|
|
65
65
|
# @return [Array<String>]
|
|
66
|
+
# @sg-ignore Need to validate config
|
|
66
67
|
def domains
|
|
67
68
|
raw_data['domains']
|
|
68
69
|
end
|
|
@@ -70,6 +71,7 @@ module Solargraph
|
|
|
70
71
|
# An array of required paths to add to the workspace.
|
|
71
72
|
#
|
|
72
73
|
# @return [Array<String>]
|
|
74
|
+
# @sg-ignore Need to validate config
|
|
73
75
|
def required
|
|
74
76
|
raw_data['require']
|
|
75
77
|
end
|
|
@@ -83,6 +85,7 @@ module Solargraph
|
|
|
83
85
|
|
|
84
86
|
# An array of reporters to use for diagnostics.
|
|
85
87
|
#
|
|
88
|
+
# @sg-ignore Need to validate config
|
|
86
89
|
# @return [Array<String>]
|
|
87
90
|
def reporters
|
|
88
91
|
raw_data['reporters']
|
|
@@ -90,7 +93,7 @@ module Solargraph
|
|
|
90
93
|
|
|
91
94
|
# A hash of options supported by the formatter
|
|
92
95
|
#
|
|
93
|
-
# @sg-ignore
|
|
96
|
+
# @sg-ignore Need to validate config
|
|
94
97
|
# @return [Hash]
|
|
95
98
|
def formatter
|
|
96
99
|
raw_data['formatter']
|
|
@@ -98,6 +101,7 @@ module Solargraph
|
|
|
98
101
|
|
|
99
102
|
# An array of plugins to require.
|
|
100
103
|
#
|
|
104
|
+
# @sg-ignore Need to validate config
|
|
101
105
|
# @return [Array<String>]
|
|
102
106
|
def plugins
|
|
103
107
|
raw_data['plugins']
|
|
@@ -105,12 +109,21 @@ module Solargraph
|
|
|
105
109
|
|
|
106
110
|
# The maximum number of files to parse from the workspace.
|
|
107
111
|
#
|
|
108
|
-
# @sg-ignore
|
|
112
|
+
# @sg-ignore Need to validate config
|
|
109
113
|
# @return [Integer]
|
|
110
114
|
def max_files
|
|
111
115
|
raw_data['max_files']
|
|
112
116
|
end
|
|
113
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
|
+
|
|
114
127
|
private
|
|
115
128
|
|
|
116
129
|
# @return [String]
|
|
@@ -125,7 +138,7 @@ module Solargraph
|
|
|
125
138
|
File.join(@directory, '.solargraph.yml')
|
|
126
139
|
end
|
|
127
140
|
|
|
128
|
-
# @return [Hash{String =>
|
|
141
|
+
# @return [Hash{String => undefined}]
|
|
129
142
|
def config_data
|
|
130
143
|
workspace_config = read_config(workspace_config_path)
|
|
131
144
|
global_config = read_config(global_config_path)
|
|
@@ -164,6 +177,9 @@ module Solargraph
|
|
|
164
177
|
'extra_args' =>[]
|
|
165
178
|
}
|
|
166
179
|
},
|
|
180
|
+
'type_checker' => {
|
|
181
|
+
'rules' => { }
|
|
182
|
+
},
|
|
167
183
|
'require_paths' => [],
|
|
168
184
|
'plugins' => [],
|
|
169
185
|
'max_files' => MAX_FILES
|
|
@@ -0,0 +1,97 @@
|
|
|
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
|
+
o, e, s = Open3.capture3(*cmd)
|
|
80
|
+
if s.success?
|
|
81
|
+
begin
|
|
82
|
+
hash = o && !o.empty? ? JSON.parse(o.split("\n").last) : {}
|
|
83
|
+
return [] if hash.empty?
|
|
84
|
+
hash['paths'].map { |path| File.join(base, path) }
|
|
85
|
+
rescue StandardError => e
|
|
86
|
+
Solargraph.logger.warn "Error reading #{gemspec_file_path}: [#{e.class}] #{e.message}"
|
|
87
|
+
[]
|
|
88
|
+
end
|
|
89
|
+
else
|
|
90
|
+
Solargraph.logger.warn "Error reading #{gemspec_file_path}"
|
|
91
|
+
Solargraph.logger.warn e
|
|
92
|
+
[]
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
data/lib/solargraph/workspace.rb
CHANGED
|
@@ -10,37 +10,52 @@ 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
|
|
25
21
|
|
|
26
|
-
# @param directory [String]
|
|
22
|
+
# @param directory [String] TODO: Remove '' and '*' special cases
|
|
27
23
|
# @param config [Config, nil]
|
|
28
24
|
# @param server [Hash]
|
|
29
25
|
def initialize directory = '', config = nil, server = {}
|
|
30
|
-
|
|
26
|
+
raise ArgumentError, 'directory must be a String' unless directory.is_a?(String)
|
|
27
|
+
|
|
28
|
+
@directory = if ['*', ''].include?(directory)
|
|
29
|
+
directory
|
|
30
|
+
else
|
|
31
|
+
File.absolute_path(directory)
|
|
32
|
+
end
|
|
31
33
|
@config = config
|
|
32
34
|
@server = server
|
|
33
35
|
load_sources
|
|
34
36
|
@gemnames = []
|
|
35
|
-
@require_paths = generate_require_paths
|
|
36
37
|
require_plugins
|
|
37
38
|
end
|
|
38
39
|
|
|
40
|
+
# The require paths associated with the workspace.
|
|
41
|
+
#
|
|
42
|
+
# @return [Array<String>]
|
|
43
|
+
def require_paths
|
|
44
|
+
# @todo are the semantics of '*' the same as '', meaning 'don't send back any require paths'?
|
|
45
|
+
@require_paths ||= RequirePaths.new(directory_or_nil, config).generate
|
|
46
|
+
end
|
|
47
|
+
|
|
39
48
|
# @return [Solargraph::Workspace::Config]
|
|
40
49
|
def config
|
|
41
50
|
@config ||= Solargraph::Workspace::Config.new(directory)
|
|
42
51
|
end
|
|
43
52
|
|
|
53
|
+
# @param level [Symbol]
|
|
54
|
+
# @return [TypeChecker::Rules]
|
|
55
|
+
def rules(level)
|
|
56
|
+
@rules ||= TypeChecker::Rules.new(level, config.type_checker_rules)
|
|
57
|
+
end
|
|
58
|
+
|
|
44
59
|
# Merge the source. A merge will update the existing source for the file
|
|
45
60
|
# or add it to the sources if the workspace is configured to include it.
|
|
46
61
|
# The source is ignored if the configuration excludes it.
|
|
@@ -111,28 +126,12 @@ module Solargraph
|
|
|
111
126
|
false
|
|
112
127
|
end
|
|
113
128
|
|
|
114
|
-
# True if the workspace contains at least one gemspec file.
|
|
115
|
-
#
|
|
116
|
-
# @return [Boolean]
|
|
117
|
-
def gemspec?
|
|
118
|
-
!gemspecs.empty?
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
# Get an array of all gemspec files in the workspace.
|
|
122
|
-
#
|
|
123
|
-
# @return [Array<String>]
|
|
124
|
-
def gemspecs
|
|
125
|
-
return [] if directory.empty? || directory == '*'
|
|
126
|
-
@gemspecs ||= Dir[File.join(directory, '**/*.gemspec')].select do |gs|
|
|
127
|
-
config.allow? gs
|
|
128
|
-
end
|
|
129
|
-
end
|
|
130
|
-
|
|
131
129
|
# @return [String, nil]
|
|
132
130
|
def rbs_collection_path
|
|
133
131
|
@gem_rbs_collection ||= read_rbs_collection_path
|
|
134
132
|
end
|
|
135
133
|
|
|
134
|
+
# @return [String, nil]
|
|
136
135
|
def rbs_collection_config_path
|
|
137
136
|
@rbs_collection_config_path ||= begin
|
|
138
137
|
unless directory.empty? || directory == '*'
|
|
@@ -155,6 +154,12 @@ module Solargraph
|
|
|
155
154
|
server['commandPath'] || 'solargraph'
|
|
156
155
|
end
|
|
157
156
|
|
|
157
|
+
# @return [String, nil]
|
|
158
|
+
def directory_or_nil
|
|
159
|
+
return nil if directory.empty? || directory == '*'
|
|
160
|
+
directory
|
|
161
|
+
end
|
|
162
|
+
|
|
158
163
|
# True if the workspace has a root Gemfile.
|
|
159
164
|
#
|
|
160
165
|
# @todo Handle projects with custom Bundler/Gemfile setups (see DocMap#gemspecs_required_from_bundler)
|
|
@@ -192,48 +197,6 @@ module Solargraph
|
|
|
192
197
|
end
|
|
193
198
|
end
|
|
194
199
|
|
|
195
|
-
# Generate require paths from gemspecs if they exist or assume the default
|
|
196
|
-
# lib directory.
|
|
197
|
-
#
|
|
198
|
-
# @return [Array<String>]
|
|
199
|
-
def generate_require_paths
|
|
200
|
-
return configured_require_paths unless gemspec?
|
|
201
|
-
result = []
|
|
202
|
-
gemspecs.each do |file|
|
|
203
|
-
base = File.dirname(file)
|
|
204
|
-
# HACK: Evaluating gemspec files violates the goal of not running
|
|
205
|
-
# workspace code, but this is how Gem::Specification.load does it
|
|
206
|
-
# anyway.
|
|
207
|
-
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)"]
|
|
208
|
-
o, e, s = Open3.capture3(*cmd)
|
|
209
|
-
if s.success?
|
|
210
|
-
begin
|
|
211
|
-
hash = o && !o.empty? ? JSON.parse(o.split("\n").last) : {}
|
|
212
|
-
next if hash.empty?
|
|
213
|
-
@gemnames.push hash['name']
|
|
214
|
-
result.concat(hash['paths'].map { |path| File.join(base, path) })
|
|
215
|
-
rescue StandardError => e
|
|
216
|
-
Solargraph.logger.warn "Error reading #{file}: [#{e.class}] #{e.message}"
|
|
217
|
-
end
|
|
218
|
-
else
|
|
219
|
-
Solargraph.logger.warn "Error reading #{file}"
|
|
220
|
-
Solargraph.logger.warn e
|
|
221
|
-
end
|
|
222
|
-
end
|
|
223
|
-
result.concat(config.require_paths.map { |p| File.join(directory, p) })
|
|
224
|
-
result.push File.join(directory, 'lib') if result.empty?
|
|
225
|
-
result
|
|
226
|
-
end
|
|
227
|
-
|
|
228
|
-
# Get additional require paths defined in the configuration.
|
|
229
|
-
#
|
|
230
|
-
# @return [Array<String>]
|
|
231
|
-
def configured_require_paths
|
|
232
|
-
return ['lib'] if directory.empty?
|
|
233
|
-
return [File.join(directory, 'lib')] if config.require_paths.empty?
|
|
234
|
-
config.require_paths.map { |p| File.join(directory, p) }
|
|
235
|
-
end
|
|
236
|
-
|
|
237
200
|
# @return [void]
|
|
238
201
|
def require_plugins
|
|
239
202
|
config.plugins.each do |plugin|
|
|
@@ -11,7 +11,7 @@ module Solargraph
|
|
|
11
11
|
["Rails::Engine", :class, "find_root_with_flag"] => :public
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
# @param code_object [YARD::CodeObjects::
|
|
14
|
+
# @param code_object [YARD::CodeObjects::MethodObject]
|
|
15
15
|
# @param name [String, nil]
|
|
16
16
|
# @param scope [Symbol, nil]
|
|
17
17
|
# @param visibility [Symbol, nil]
|
|
@@ -27,8 +27,8 @@ module Solargraph
|
|
|
27
27
|
final_scope = scope || code_object.scope
|
|
28
28
|
override_key = [closure.path, final_scope, name]
|
|
29
29
|
final_visibility = VISIBILITY_OVERRIDE[override_key]
|
|
30
|
-
final_visibility ||= VISIBILITY_OVERRIDE[
|
|
31
|
-
final_visibility ||= :private if closure.path == 'Kernel' && Kernel.private_instance_methods(false).include?(name)
|
|
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
32
|
final_visibility ||= visibility
|
|
33
33
|
final_visibility ||= :private if code_object.module_function? && final_scope == :instance
|
|
34
34
|
final_visibility ||= :public if code_object.module_function? && final_scope == :class
|
|
@@ -85,6 +85,7 @@ module Solargraph
|
|
|
85
85
|
# HACK: Skip `nil` and `self` parameters that are sometimes emitted
|
|
86
86
|
# for methods defined in C
|
|
87
87
|
# See https://github.com/castwide/solargraph/issues/345
|
|
88
|
+
# @sg-ignore https://github.com/castwide/solargraph/pull/1114
|
|
88
89
|
code_object.parameters.select { |a| a[0] && a[0] != 'self' }.map do |a|
|
|
89
90
|
Solargraph::Pin::Parameter.new(
|
|
90
91
|
location: location,
|
|
@@ -15,6 +15,7 @@ module Solargraph
|
|
|
15
15
|
# HACK: Skip `nil` and `self` parameters that are sometimes emitted
|
|
16
16
|
# for methods defined in C
|
|
17
17
|
# See https://github.com/castwide/solargraph/issues/345
|
|
18
|
+
# @sg-ignore https://github.com/castwide/solargraph/pull/1114
|
|
18
19
|
code_object.parameters.select { |a| a[0] && a[0] != 'self' }.map do |a|
|
|
19
20
|
Solargraph::Pin::Parameter.new(
|
|
20
21
|
location: location,
|
|
@@ -57,7 +58,7 @@ module Solargraph
|
|
|
57
58
|
|
|
58
59
|
include Helpers
|
|
59
60
|
|
|
60
|
-
# @param code_object [YARD::CodeObjects::
|
|
61
|
+
# @param code_object [YARD::CodeObjects::MethodObject]
|
|
61
62
|
# @param name [String, nil]
|
|
62
63
|
# @param scope [Symbol, nil]
|
|
63
64
|
# @param visibility [Symbol, nil]
|
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,31 @@ 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)
|
|
17
|
+
def cache(yard_plugins, gemspec)
|
|
15
18
|
path = PinCache.yardoc_path gemspec
|
|
16
19
|
return path if cached?(gemspec)
|
|
17
20
|
|
|
21
|
+
unless Dir.exist? gemspec.gem_dir
|
|
22
|
+
# Can happen in at least some (old?) RubyGems versions when we
|
|
23
|
+
# have a gemspec describing a standard library like bundler.
|
|
24
|
+
#
|
|
25
|
+
# https://github.com/apiology/solargraph/actions/runs/17650140201/job/50158676842?pr=10
|
|
26
|
+
Solargraph.logger.info { "Bad info from gemspec - #{gemspec.gem_dir} does not exist" }
|
|
27
|
+
return path
|
|
28
|
+
end
|
|
29
|
+
|
|
18
30
|
Solargraph.logger.info "Caching yardoc for #{gemspec.name} #{gemspec.version}"
|
|
19
|
-
|
|
20
|
-
|
|
31
|
+
cmd = "yardoc --db #{path} --no-output --plugin solargraph"
|
|
32
|
+
yard_plugins.each { |plugin| cmd << " --plugin #{plugin}" }
|
|
33
|
+
Solargraph.logger.debug { "Running: #{cmd}" }
|
|
34
|
+
# @todo set these up to run in parallel
|
|
35
|
+
stdout_and_stderr_str, status = Open3.capture2e(current_bundle_env_tweaks, cmd, chdir: gemspec.gem_dir)
|
|
36
|
+
unless status.success?
|
|
37
|
+
Solargraph.logger.warn { "YARD failed running #{cmd.inspect} in #{gemspec.gem_dir}" }
|
|
38
|
+
Solargraph.logger.info stdout_and_stderr_str
|
|
21
39
|
end
|
|
22
40
|
path
|
|
23
41
|
end
|
|
@@ -32,6 +50,7 @@ module Solargraph
|
|
|
32
50
|
|
|
33
51
|
# True if another process is currently building the yardoc cache.
|
|
34
52
|
#
|
|
53
|
+
# @param gemspec [Gem::Specification]
|
|
35
54
|
def processing?(gemspec)
|
|
36
55
|
yardoc = File.join(PinCache.yardoc_path(gemspec), 'processing')
|
|
37
56
|
File.exist?(yardoc)
|
|
@@ -47,5 +66,22 @@ module Solargraph
|
|
|
47
66
|
YARD::Registry.load! PinCache.yardoc_path gemspec
|
|
48
67
|
YARD::Registry.all
|
|
49
68
|
end
|
|
69
|
+
|
|
70
|
+
# If the BUNDLE_GEMFILE environment variable is set, we need to
|
|
71
|
+
# make sure it's an absolute path, as we'll be changing
|
|
72
|
+
# directories.
|
|
73
|
+
#
|
|
74
|
+
# 'bundle exec' sets an absolute path here, but at least the
|
|
75
|
+
# overcommit gem does not, breaking on-the-fly documention with a
|
|
76
|
+
# spawned yardoc command from our current bundle
|
|
77
|
+
#
|
|
78
|
+
# @return [Hash{String => String}] a hash of environment variables to override
|
|
79
|
+
def current_bundle_env_tweaks
|
|
80
|
+
tweaks = {}
|
|
81
|
+
if ENV['BUNDLE_GEMFILE'] && !ENV['BUNDLE_GEMFILE'].empty?
|
|
82
|
+
tweaks['BUNDLE_GEMFILE'] = File.expand_path(ENV['BUNDLE_GEMFILE'])
|
|
83
|
+
end
|
|
84
|
+
tweaks
|
|
85
|
+
end
|
|
50
86
|
end
|
|
51
87
|
end
|
data/lib/solargraph.rb
CHANGED
|
@@ -53,6 +53,8 @@ module Solargraph
|
|
|
53
53
|
dir = File.dirname(__FILE__)
|
|
54
54
|
VIEWS_PATH = File.join(dir, 'solargraph', 'views')
|
|
55
55
|
|
|
56
|
+
CHDIR_MUTEX = Mutex.new
|
|
57
|
+
|
|
56
58
|
# @param type [Symbol] Type of assert.
|
|
57
59
|
def self.asserts_on?(type)
|
|
58
60
|
if ENV['SOLARGRAPH_ASSERTS'].nil? || ENV['SOLARGRAPH_ASSERTS'].empty?
|