solargraph 0.47.2 → 0.53.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.
- checksums.yaml +4 -4
- data/.github/FUNDING.yml +1 -0
- data/.github/workflows/plugins.yml +40 -0
- data/.github/workflows/rspec.yml +4 -8
- data/.github/workflows/typecheck.yml +34 -0
- data/.yardopts +2 -2
- data/CHANGELOG.md +137 -3
- data/LICENSE +1 -1
- data/README.md +19 -16
- data/SPONSORS.md +2 -9
- data/lib/solargraph/api_map/cache.rb +60 -20
- data/lib/solargraph/api_map/source_to_yard.rb +17 -10
- data/lib/solargraph/api_map/store.rb +60 -12
- data/lib/solargraph/api_map.rb +171 -99
- data/lib/solargraph/bench.rb +3 -2
- data/lib/solargraph/cache.rb +77 -0
- data/lib/solargraph/complex_type/type_methods.rb +61 -12
- data/lib/solargraph/complex_type/unique_type.rb +193 -16
- data/lib/solargraph/complex_type.rb +113 -10
- data/lib/solargraph/convention/rakefile.rb +17 -0
- data/lib/solargraph/convention.rb +2 -3
- data/lib/solargraph/converters/dd.rb +5 -0
- data/lib/solargraph/converters/dl.rb +3 -0
- data/lib/solargraph/converters/dt.rb +3 -0
- data/lib/solargraph/diagnostics/rubocop.rb +23 -8
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +4 -1
- data/lib/solargraph/diagnostics/type_check.rb +1 -0
- data/lib/solargraph/diagnostics.rb +2 -2
- data/lib/solargraph/doc_map.rb +171 -0
- data/lib/solargraph/gem_pins.rb +64 -0
- data/lib/solargraph/language_server/host/cataloger.rb +2 -1
- data/lib/solargraph/language_server/host/diagnoser.rb +2 -2
- data/lib/solargraph/language_server/host/dispatch.rb +15 -5
- data/lib/solargraph/language_server/host/message_worker.rb +4 -0
- data/lib/solargraph/language_server/host/sources.rb +7 -4
- data/lib/solargraph/language_server/host.rb +50 -26
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +3 -1
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +13 -1
- data/lib/solargraph/language_server/message/extended/download_core.rb +1 -5
- data/lib/solargraph/language_server/message/initialize.rb +13 -0
- data/lib/solargraph/language_server/message/initialized.rb +1 -0
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +4 -1
- data/lib/solargraph/language_server/message/text_document/formatting.rb +4 -4
- data/lib/solargraph/language_server/message/text_document/hover.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/signature_help.rb +1 -6
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +24 -0
- data/lib/solargraph/language_server/message/text_document.rb +1 -1
- data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +5 -0
- data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +10 -3
- data/lib/solargraph/language_server/message.rb +1 -0
- data/lib/solargraph/language_server/transport/adapter.rb +16 -1
- data/lib/solargraph/language_server/transport/data_reader.rb +2 -0
- data/lib/solargraph/library.rb +124 -37
- data/lib/solargraph/location.rb +1 -0
- data/lib/solargraph/page.rb +6 -0
- data/lib/solargraph/parser/comment_ripper.rb +4 -0
- data/lib/solargraph/parser/node_methods.rb +47 -7
- data/lib/solargraph/parser/node_processor/base.rb +9 -0
- data/lib/solargraph/parser/{legacy → parser_gem}/class_methods.rb +31 -5
- data/lib/solargraph/parser/{legacy → parser_gem}/flawed_builder.rb +3 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_chainer.rb +57 -41
- data/lib/solargraph/parser/parser_gem/node_methods.rb +499 -0
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/alias_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +53 -0
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/begin_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/block_node.rb +3 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/casgn_node.rb +14 -4
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/cvasgn_node.rb +1 -1
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/def_node.rb +7 -20
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/defs_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/gvasgn_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/ivasgn_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/lvasgn_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/namespace_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/orasgn_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/resbody_node.rb +3 -3
- data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +42 -0
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/send_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/sym_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors.rb +54 -0
- data/lib/solargraph/parser/parser_gem.rb +12 -0
- data/lib/solargraph/parser/region.rb +1 -1
- data/lib/solargraph/parser/snippet.rb +2 -0
- data/lib/solargraph/parser.rb +9 -10
- data/lib/solargraph/pin/base.rb +69 -11
- data/lib/solargraph/pin/base_variable.rb +8 -4
- data/lib/solargraph/pin/block.rb +21 -28
- data/lib/solargraph/pin/closure.rb +17 -2
- data/lib/solargraph/pin/common.rb +7 -3
- data/lib/solargraph/pin/conversions.rb +34 -8
- data/lib/solargraph/pin/delegated_method.rb +97 -0
- data/lib/solargraph/pin/documenting.rb +25 -34
- data/lib/solargraph/pin/instance_variable.rb +4 -0
- data/lib/solargraph/pin/local_variable.rb +13 -1
- data/lib/solargraph/pin/method.rb +270 -16
- data/lib/solargraph/pin/namespace.rb +17 -1
- data/lib/solargraph/pin/parameter.rb +52 -17
- data/lib/solargraph/pin/reference/override.rb +2 -2
- data/lib/solargraph/pin/reference.rb +8 -0
- data/lib/solargraph/pin/search.rb +4 -4
- data/lib/solargraph/pin/signature.rb +143 -0
- data/lib/solargraph/pin.rb +2 -1
- data/lib/solargraph/range.rb +4 -6
- data/lib/solargraph/rbs_map/conversions.rb +601 -0
- data/lib/solargraph/rbs_map/core_fills.rb +47 -0
- data/lib/solargraph/rbs_map/core_map.rb +28 -0
- data/lib/solargraph/rbs_map/stdlib_map.rb +33 -0
- data/lib/solargraph/rbs_map.rb +84 -0
- data/lib/solargraph/shell.rb +69 -48
- data/lib/solargraph/source/chain/array.rb +32 -0
- data/lib/solargraph/source/chain/block_symbol.rb +13 -0
- data/lib/solargraph/source/chain/call.rb +125 -61
- data/lib/solargraph/source/chain/constant.rb +15 -1
- data/lib/solargraph/source/chain/if.rb +23 -0
- data/lib/solargraph/source/chain/link.rb +8 -2
- data/lib/solargraph/source/chain/or.rb +1 -1
- data/lib/solargraph/source/chain/z_super.rb +3 -3
- data/lib/solargraph/source/chain.rb +44 -14
- data/lib/solargraph/source/change.rb +3 -0
- data/lib/solargraph/source/cursor.rb +2 -0
- data/lib/solargraph/source/source_chainer.rb +8 -5
- data/lib/solargraph/source.rb +18 -19
- data/lib/solargraph/source_map/clip.rb +30 -23
- data/lib/solargraph/source_map/mapper.rb +20 -5
- data/lib/solargraph/source_map.rb +28 -13
- data/lib/solargraph/type_checker/checks.rb +10 -2
- data/lib/solargraph/type_checker.rb +201 -98
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/views/environment.erb +2 -2
- data/lib/solargraph/workspace/config.rb +14 -11
- data/lib/solargraph/workspace.rb +28 -17
- data/lib/solargraph/yard_map/cache.rb +6 -0
- data/lib/solargraph/yard_map/helpers.rb +1 -1
- data/lib/solargraph/yard_map/mapper/to_method.rb +18 -5
- data/lib/solargraph/yard_map/mapper.rb +1 -1
- data/lib/solargraph/yard_map/to_method.rb +11 -4
- data/lib/solargraph/yard_map.rb +1 -443
- data/lib/solargraph/yard_tags.rb +20 -0
- data/lib/solargraph/yardoc.rb +52 -0
- data/lib/solargraph.rb +8 -6
- data/solargraph.gemspec +19 -8
- metadata +162 -98
- data/.travis.yml +0 -19
- data/lib/solargraph/api_map/bundler_methods.rb +0 -22
- data/lib/solargraph/compat.rb +0 -37
- data/lib/solargraph/convention/rspec.rb +0 -30
- data/lib/solargraph/documentor.rb +0 -76
- data/lib/solargraph/parser/legacy/node_methods.rb +0 -325
- data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +0 -23
- data/lib/solargraph/parser/legacy/node_processors/args_node.rb +0 -35
- data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +0 -15
- data/lib/solargraph/parser/legacy/node_processors/def_node.rb +0 -63
- data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +0 -21
- data/lib/solargraph/parser/legacy/node_processors.rb +0 -54
- data/lib/solargraph/parser/legacy.rb +0 -12
- data/lib/solargraph/parser/rubyvm/class_methods.rb +0 -144
- data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -160
- data/lib/solargraph/parser/rubyvm/node_methods.rb +0 -315
- data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +0 -85
- data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +0 -42
- data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +0 -22
- data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +0 -23
- data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +0 -57
- data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +0 -23
- data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +0 -38
- data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +0 -39
- data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +0 -20
- data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +0 -27
- data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +0 -39
- data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +0 -26
- data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +0 -15
- data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +0 -45
- data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +0 -21
- data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +0 -15
- data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +0 -277
- data/lib/solargraph/parser/rubyvm/node_processors/sym_node.rb +0 -18
- data/lib/solargraph/parser/rubyvm/node_processors.rb +0 -63
- data/lib/solargraph/parser/rubyvm.rb +0 -40
- data/lib/solargraph/yard_map/core_docs.rb +0 -170
- data/lib/solargraph/yard_map/core_fills.rb +0 -208
- data/lib/solargraph/yard_map/core_gen.rb +0 -76
- data/lib/solargraph/yard_map/rdoc_to_yard.rb +0 -140
- data/lib/solargraph/yard_map/stdlib_fills.rb +0 -43
- data/lib/yard-solargraph.rb +0 -33
- data/yardoc/2.2.2.tar.gz +0 -0
@@ -11,6 +11,7 @@ module Solargraph
|
|
11
11
|
|
12
12
|
# Conversion of RuboCop severity names to LSP constants
|
13
13
|
SEVERITIES = {
|
14
|
+
'info' => Severities::HINT,
|
14
15
|
'refactor' => Severities::HINT,
|
15
16
|
'convention' => Severities::INFORMATION,
|
16
17
|
'warning' => Severities::WARNING,
|
@@ -22,16 +23,20 @@ module Solargraph
|
|
22
23
|
# @param _api_map [Solargraph::ApiMap]
|
23
24
|
# @return [Array<Hash>]
|
24
25
|
def diagnose source, _api_map
|
26
|
+
@source = source
|
25
27
|
require_rubocop(rubocop_version)
|
26
28
|
options, paths = generate_options(source.filename, source.code)
|
27
29
|
store = RuboCop::ConfigStore.new
|
28
30
|
runner = RuboCop::Runner.new(options, store)
|
29
31
|
result = redirect_stdout{ runner.run(paths) }
|
32
|
+
|
33
|
+
return [] if result.empty?
|
34
|
+
|
30
35
|
make_array JSON.parse(result)
|
31
36
|
rescue RuboCop::ValidationError, RuboCop::ConfigNotFoundError => e
|
32
37
|
raise DiagnosticsError, "Error in RuboCop configuration: #{e.message}"
|
33
|
-
rescue JSON::ParserError
|
34
|
-
raise DiagnosticsError,
|
38
|
+
rescue JSON::ParserError => e
|
39
|
+
raise DiagnosticsError, "RuboCop returned invalid data: #{e.message}"
|
35
40
|
end
|
36
41
|
|
37
42
|
private
|
@@ -43,7 +48,7 @@ module Solargraph
|
|
43
48
|
args.find { |a| a =~ /version=/ }.to_s.split('=').last
|
44
49
|
end
|
45
50
|
|
46
|
-
# @param resp [Hash]
|
51
|
+
# @param resp [Hash{String => Array<Hash{String => Array<Hash{String => undefined}>}>}]
|
47
52
|
# @return [Array<Hash>]
|
48
53
|
def make_array resp
|
49
54
|
diagnostics = []
|
@@ -57,8 +62,8 @@ module Solargraph
|
|
57
62
|
|
58
63
|
# Convert a RuboCop offense to an LSP diagnostic
|
59
64
|
#
|
60
|
-
# @param off [Hash] Offense received from Rubocop
|
61
|
-
# @return [Hash] LSP diagnostic
|
65
|
+
# @param off [Hash{String => unknown}] Offense received from Rubocop
|
66
|
+
# @return [Hash{Symbol => Hash, String, Integer}] LSP diagnostic
|
62
67
|
def offense_to_diagnostic off
|
63
68
|
{
|
64
69
|
range: offense_range(off).to_hash,
|
@@ -76,20 +81,30 @@ module Solargraph
|
|
76
81
|
Range.new(offense_start_position(off), offense_ending_position(off))
|
77
82
|
end
|
78
83
|
|
79
|
-
# @param off [Hash]
|
84
|
+
# @param off [Hash{String => Hash{String => Integer}}]
|
80
85
|
# @return [Position]
|
81
86
|
def offense_start_position off
|
82
87
|
Position.new(off['location']['start_line'] - 1, off['location']['start_column'] - 1)
|
83
88
|
end
|
84
89
|
|
85
|
-
# @param off [Hash]
|
90
|
+
# @param off [Hash{String => Hash{String => Integer}}]
|
86
91
|
# @return [Position]
|
87
92
|
def offense_ending_position off
|
88
93
|
if off['location']['start_line'] != off['location']['last_line']
|
89
94
|
Position.new(off['location']['start_line'], 0)
|
90
95
|
else
|
96
|
+
start_line = off['location']['start_line'] - 1
|
97
|
+
# @type [Integer]
|
98
|
+
last_column = off['location']['last_column']
|
99
|
+
line = @source.code.lines[start_line]
|
100
|
+
col_off = if line.nil? || line.empty?
|
101
|
+
1
|
102
|
+
else
|
103
|
+
0
|
104
|
+
end
|
105
|
+
|
91
106
|
Position.new(
|
92
|
-
|
107
|
+
start_line, last_column - col_off
|
93
108
|
)
|
94
109
|
end
|
95
110
|
end
|
@@ -10,13 +10,16 @@ module Solargraph
|
|
10
10
|
# Requires a specific version of rubocop, or the latest installed version
|
11
11
|
# if _version_ is `nil`.
|
12
12
|
#
|
13
|
-
# @param version [String]
|
13
|
+
# @param version [String, nil]
|
14
14
|
# @raise [InvalidRubocopVersionError] if _version_ is not installed
|
15
|
+
# @return [void]
|
15
16
|
def require_rubocop(version = nil)
|
16
17
|
begin
|
17
18
|
gem_path = Gem::Specification.find_by_name('rubocop', version).full_gem_path
|
18
19
|
gem_lib_path = File.join(gem_path, 'lib')
|
19
20
|
$LOAD_PATH.unshift(gem_lib_path) unless $LOAD_PATH.include?(gem_lib_path)
|
21
|
+
# @todo Gem::MissingSpecVersionError is undocumented for some reason
|
22
|
+
# @sg-ignore
|
20
23
|
rescue Gem::MissingSpecVersionError => e
|
21
24
|
raise InvalidRubocopVersionError,
|
22
25
|
"could not find '#{e.name}' (#{e.requirement}) - "\
|
@@ -6,6 +6,7 @@ module Solargraph
|
|
6
6
|
# parameters, and invalid param tags.
|
7
7
|
#
|
8
8
|
class TypeCheck < Base
|
9
|
+
# @return [Array<Hash>]
|
9
10
|
def diagnose source, api_map
|
10
11
|
# return [] unless args.include?('always') || api_map.workspaced?(source.filename)
|
11
12
|
severity = Diagnostics::Severities::ERROR
|
@@ -33,14 +33,14 @@ module Solargraph
|
|
33
33
|
# Find a reporter by name.
|
34
34
|
#
|
35
35
|
# @param name [String] The name with which the reporter was registered
|
36
|
-
# @return [Class<Solargraph::Diagnostics::Base
|
36
|
+
# @return [Class<Solargraph::Diagnostics::Base>, nil]
|
37
37
|
def reporter name
|
38
38
|
reporter_hash[name]
|
39
39
|
end
|
40
40
|
|
41
41
|
private
|
42
42
|
|
43
|
-
# @return [Hash]
|
43
|
+
# @return [Hash{String => Class<Solargraph::Diagnostics::Base>}]
|
44
44
|
def reporter_hash
|
45
45
|
@reporter_hash ||= {}
|
46
46
|
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Solargraph
|
4
|
+
# A collection of pins generated from required gems.
|
5
|
+
#
|
6
|
+
class DocMap
|
7
|
+
# @return [Array<String>]
|
8
|
+
attr_reader :requires
|
9
|
+
|
10
|
+
# @return [Array<Gem::Specification>]
|
11
|
+
attr_reader :preferences
|
12
|
+
|
13
|
+
# @return [Array<Pin::Base>]
|
14
|
+
attr_reader :pins
|
15
|
+
|
16
|
+
# @return [Array<Gem::Specification>]
|
17
|
+
attr_reader :uncached_gemspecs
|
18
|
+
|
19
|
+
# @param requires [Array<String>]
|
20
|
+
# @param preferences [Array<Gem::Specification>]
|
21
|
+
def initialize(requires, preferences)
|
22
|
+
@requires = requires.compact
|
23
|
+
@preferences = preferences.compact
|
24
|
+
generate
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Array<Gem::Specification>]
|
28
|
+
def gemspecs
|
29
|
+
@gemspecs ||= required_gem_map.values.compact
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [Array<String>]
|
33
|
+
def unresolved_requires
|
34
|
+
@unresolved_requires ||= required_gem_map.select { |_, gemspec| gemspec.nil? }.keys
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return [Hash{Gem::Specification => Array[Pin::Base]}]
|
38
|
+
def self.gems_in_memory
|
39
|
+
@gems_in_memory ||= {}
|
40
|
+
end
|
41
|
+
|
42
|
+
def dependencies
|
43
|
+
@dependencies ||= (gemspecs.flat_map { |spec| fetch_dependencies(spec) } - gemspecs).to_set
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
# @return [void]
|
49
|
+
def generate
|
50
|
+
@pins = []
|
51
|
+
@uncached_gemspecs = []
|
52
|
+
required_gem_map.each do |path, gemspec|
|
53
|
+
if gemspec
|
54
|
+
try_cache gemspec
|
55
|
+
else
|
56
|
+
try_stdlib_map path
|
57
|
+
end
|
58
|
+
end
|
59
|
+
dependencies.each { |dep| try_cache dep }
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return [Hash{String => Gem::Specification, nil}]
|
63
|
+
def required_gem_map
|
64
|
+
@required_gem_map ||= requires.to_h { |path| [path, resolve_path_to_gemspec(path)] }
|
65
|
+
end
|
66
|
+
|
67
|
+
# @return [Hash{String => Gem::Specification}]
|
68
|
+
def preference_map
|
69
|
+
@preference_map ||= preferences.to_h { |gemspec| [gemspec.name, gemspec] }
|
70
|
+
end
|
71
|
+
|
72
|
+
# @param gemspec [Gem::Specification]
|
73
|
+
# @return [void]
|
74
|
+
def try_cache gemspec
|
75
|
+
return if try_gem_in_memory(gemspec)
|
76
|
+
cache_file = File.join('gems', "#{gemspec.name}-#{gemspec.version}.ser")
|
77
|
+
if Cache.exist?(cache_file)
|
78
|
+
gempins = Cache.load(cache_file)
|
79
|
+
self.class.gems_in_memory[gemspec] = gempins
|
80
|
+
@pins.concat gempins
|
81
|
+
else
|
82
|
+
Solargraph.logger.debug "No pin cache for #{gemspec.name} #{gemspec.version}"
|
83
|
+
@uncached_gemspecs.push gemspec
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# @param path [String] require path that might be in the RBS stdlib collection
|
88
|
+
# @return [void]
|
89
|
+
def try_stdlib_map path
|
90
|
+
map = RbsMap::StdlibMap.load(path)
|
91
|
+
if map.resolved?
|
92
|
+
Solargraph.logger.debug "Loading stdlib pins for #{path}"
|
93
|
+
@pins.concat map.pins
|
94
|
+
else
|
95
|
+
# @todo Temporarily ignoring unresolved `require 'set'`
|
96
|
+
Solargraph.logger.warn "Require path #{path} could not be resolved" unless path == 'set'
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# @param gemspec [Gem::Specification]
|
101
|
+
# @return [Boolean]
|
102
|
+
def try_gem_in_memory gemspec
|
103
|
+
gempins = DocMap.gems_in_memory[gemspec]
|
104
|
+
return false unless gempins
|
105
|
+
Solargraph.logger.debug "Found #{gemspec.name} #{gemspec.version} in memory"
|
106
|
+
@pins.concat gempins
|
107
|
+
true
|
108
|
+
end
|
109
|
+
|
110
|
+
# @param path [String]
|
111
|
+
# @return [Gem::Specification, nil]
|
112
|
+
def resolve_path_to_gemspec path
|
113
|
+
return nil if path.empty?
|
114
|
+
|
115
|
+
gemspec = Gem::Specification.find_by_path(path)
|
116
|
+
if gemspec.nil?
|
117
|
+
gem_name_guess = path.split('/').first
|
118
|
+
begin
|
119
|
+
# this can happen when the gem is included via a local path in
|
120
|
+
# a Gemfile; Gem doesn't try to index the paths in that case.
|
121
|
+
#
|
122
|
+
# See if we can make a good guess:
|
123
|
+
potential_gemspec = Gem::Specification.find_by_name(gem_name_guess)
|
124
|
+
file = "lib/#{path}.rb"
|
125
|
+
gemspec = potential_gemspec if potential_gemspec.files.any? { |gemspec_file| file == gemspec_file }
|
126
|
+
rescue Gem::MissingSpecError
|
127
|
+
Solargraph.logger.debug "Require path #{path} could not be resolved to a gem via find_by_path or guess of #{gem_name_guess}"
|
128
|
+
nil
|
129
|
+
end
|
130
|
+
end
|
131
|
+
gemspec_or_preference gemspec
|
132
|
+
end
|
133
|
+
|
134
|
+
# @param gemspec [Gem::Specification, nil]
|
135
|
+
# @return [Gem::Specification, nil]
|
136
|
+
def gemspec_or_preference gemspec
|
137
|
+
return gemspec unless gemspec && preference_map.key?(gemspec.name)
|
138
|
+
return gemspec if gemspec.version == preference_map[gemspec.name].version
|
139
|
+
|
140
|
+
change_gemspec_version gemspec, preference_map[by_path.name].version
|
141
|
+
end
|
142
|
+
|
143
|
+
# @param gemspec [Gem::Specification]
|
144
|
+
# @param version [Gem::Version]
|
145
|
+
# @return [Gem::Specification]
|
146
|
+
def change_gemspec_version gemspec, version
|
147
|
+
Gem::Specification.find_by_name(gemspec.name, "= #{version}")
|
148
|
+
rescue Gem::MissingSpecError
|
149
|
+
Solargraph.logger.info "Gem #{gemspec.name} version #{version} not found. Using #{gemspec.version} instead"
|
150
|
+
gemspec
|
151
|
+
end
|
152
|
+
|
153
|
+
# @param gemspec [Gem::Specification]
|
154
|
+
# @return [Array<Gem::Specification>]
|
155
|
+
def fetch_dependencies gemspec
|
156
|
+
only_runtime_dependencies(gemspec).each_with_object(Set.new) do |spec, deps|
|
157
|
+
Solargraph.logger.info "Adding #{spec.name} dependency for #{gemspec.name}"
|
158
|
+
dep = Gem::Specification.find_by_name(spec.name, spec.requirement)
|
159
|
+
deps.merge fetch_dependencies(dep) if deps.add?(dep)
|
160
|
+
rescue Gem::MissingSpecError
|
161
|
+
Solargraph.logger.warn "Gem dependency #{spec.name} #{spec.requirements} for #{gemspec.name} not found."
|
162
|
+
end.to_a
|
163
|
+
end
|
164
|
+
|
165
|
+
# @param gemspec [Gem::Specification]
|
166
|
+
# @return [Array<Gem::Dependency>]
|
167
|
+
def only_runtime_dependencies gemspec
|
168
|
+
gemspec.dependencies - gemspec.development_dependencies
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rbs'
|
4
|
+
|
5
|
+
module Solargraph
|
6
|
+
# A utility for building gem pins from a combination of YARD and RBS
|
7
|
+
# documentation.
|
8
|
+
#
|
9
|
+
module GemPins
|
10
|
+
# Build an array of pins from a gem specification. The process starts with
|
11
|
+
# YARD, enhances the resulting pins with RBS definitions, and appends RBS
|
12
|
+
# pins that don't exist in the YARD mapping.
|
13
|
+
#
|
14
|
+
# @param gemspec [Gem::Specification]
|
15
|
+
# @return [Array<Pin::Base>]
|
16
|
+
def self.build(gemspec)
|
17
|
+
yard_pins = build_yard_pins(gemspec)
|
18
|
+
rbs_map = RbsMap.from_gemspec(gemspec)
|
19
|
+
in_yard = Set.new
|
20
|
+
combined = yard_pins.map do |yard|
|
21
|
+
in_yard.add yard.path
|
22
|
+
next yard unless yard.is_a?(Pin::Method)
|
23
|
+
rbs = rbs_map.path_pin(yard.path, Pin::Method)
|
24
|
+
next yard unless rbs
|
25
|
+
# @todo Could not include: attribute and anon_splat
|
26
|
+
# @sg-ignore
|
27
|
+
yard.class.new(
|
28
|
+
location: yard.location,
|
29
|
+
closure: yard.closure,
|
30
|
+
name: yard.name,
|
31
|
+
comments: yard.comments,
|
32
|
+
scope: yard.scope,
|
33
|
+
parameters: rbs.parameters,
|
34
|
+
generics: rbs.generics,
|
35
|
+
node: yard.node,
|
36
|
+
signatures: yard.signatures,
|
37
|
+
return_type: best_return_type(rbs.return_type, yard.return_type)
|
38
|
+
)
|
39
|
+
end
|
40
|
+
in_rbs = rbs_map.pins.reject { |pin| in_yard.include?(pin.path) }
|
41
|
+
combined + in_rbs
|
42
|
+
end
|
43
|
+
|
44
|
+
class << self
|
45
|
+
private
|
46
|
+
|
47
|
+
# @param gemspec [Gem::Specification]
|
48
|
+
# @return [Array<Pin::Base>]
|
49
|
+
def build_yard_pins(gemspec)
|
50
|
+
Yardoc.cache(gemspec) unless Yardoc.cached?(gemspec)
|
51
|
+
yardoc = Yardoc.load!(gemspec)
|
52
|
+
YardMap::Mapper.new(yardoc, gemspec).map
|
53
|
+
end
|
54
|
+
|
55
|
+
# Select the first defined type.
|
56
|
+
#
|
57
|
+
# @param choices [Array<ComplexType>]
|
58
|
+
# @return [ComplexType]
|
59
|
+
def best_return_type *choices
|
60
|
+
choices.find { |pin| pin.defined? } || choices.first || ComplexType::UNDEFINED
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -6,6 +6,7 @@ module Solargraph
|
|
6
6
|
# An asynchronous library cataloging handler.
|
7
7
|
#
|
8
8
|
class Cataloger
|
9
|
+
# @param host [Host]
|
9
10
|
def initialize host
|
10
11
|
@host = host
|
11
12
|
@stopped = true
|
@@ -34,7 +35,7 @@ module Solargraph
|
|
34
35
|
Thread.new do
|
35
36
|
until stopped?
|
36
37
|
tick
|
37
|
-
sleep 0.
|
38
|
+
sleep 0.1
|
38
39
|
end
|
39
40
|
end
|
40
41
|
end
|
@@ -38,7 +38,7 @@ module Solargraph
|
|
38
38
|
|
39
39
|
# Start the diagnosis thread.
|
40
40
|
#
|
41
|
-
# @return [self]
|
41
|
+
# @return [self, nil]
|
42
42
|
def start
|
43
43
|
return unless @stopped
|
44
44
|
@stopped = false
|
@@ -81,7 +81,7 @@ module Solargraph
|
|
81
81
|
# @return [Mutex]
|
82
82
|
attr_reader :mutex
|
83
83
|
|
84
|
-
# @return [Array]
|
84
|
+
# @return [::Array]
|
85
85
|
attr_reader :queue
|
86
86
|
end
|
87
87
|
end
|
@@ -6,6 +6,12 @@ module Solargraph
|
|
6
6
|
# Methods for associating sources with libraries via URIs.
|
7
7
|
#
|
8
8
|
module Dispatch
|
9
|
+
# @abstract
|
10
|
+
# @return [Host::Diagnoser]
|
11
|
+
def diagnoser
|
12
|
+
raise NotImplementedError, 'Host::Dispatch requires a diagnoser method'
|
13
|
+
end
|
14
|
+
|
9
15
|
# @return [Sources]
|
10
16
|
def sources
|
11
17
|
@sources ||= begin
|
@@ -15,7 +21,7 @@ module Solargraph
|
|
15
21
|
end
|
16
22
|
end
|
17
23
|
|
18
|
-
# @return [Array<Library>]
|
24
|
+
# @return [::Array<Library>]
|
19
25
|
def libraries
|
20
26
|
@libraries ||= []
|
21
27
|
end
|
@@ -27,9 +33,9 @@ module Solargraph
|
|
27
33
|
# @return [void]
|
28
34
|
def update_libraries uri
|
29
35
|
src = sources.find(uri)
|
30
|
-
libraries.
|
31
|
-
|
32
|
-
|
36
|
+
using = libraries.select { |lib| lib.contain?(src.filename) }
|
37
|
+
using.push generic_library_for(uri) if using.empty?
|
38
|
+
using.each { |lib| lib.merge src }
|
33
39
|
diagnoser.schedule uri
|
34
40
|
end
|
35
41
|
|
@@ -89,6 +95,10 @@ module Solargraph
|
|
89
95
|
nil
|
90
96
|
end
|
91
97
|
|
98
|
+
def options
|
99
|
+
@options ||= {}.freeze
|
100
|
+
end
|
101
|
+
|
92
102
|
# Get a generic library for the given URI and attach the corresponding
|
93
103
|
# source.
|
94
104
|
#
|
@@ -103,7 +113,7 @@ module Solargraph
|
|
103
113
|
|
104
114
|
# @return [Library]
|
105
115
|
def generic_library
|
106
|
-
@generic_library ||= Solargraph::Library.new
|
116
|
+
@generic_library ||= Solargraph::Library.new(Solargraph::Workspace.new('', nil, options), nil)
|
107
117
|
end
|
108
118
|
end
|
109
119
|
end
|
@@ -16,6 +16,7 @@ module Solargraph
|
|
16
16
|
end
|
17
17
|
|
18
18
|
# pending handle messages
|
19
|
+
# @return [Array<Hash>]
|
19
20
|
def messages
|
20
21
|
@messages ||= []
|
21
22
|
end
|
@@ -24,6 +25,7 @@ module Solargraph
|
|
24
25
|
@stopped
|
25
26
|
end
|
26
27
|
|
28
|
+
# @return [void]
|
27
29
|
def stop
|
28
30
|
@stopped = true
|
29
31
|
end
|
@@ -37,6 +39,7 @@ module Solargraph
|
|
37
39
|
end
|
38
40
|
end
|
39
41
|
|
42
|
+
# @return [void]
|
40
43
|
def start
|
41
44
|
return unless @stopped
|
42
45
|
@stopped = false
|
@@ -45,6 +48,7 @@ module Solargraph
|
|
45
48
|
end
|
46
49
|
end
|
47
50
|
|
51
|
+
# @return [void]
|
48
52
|
def tick
|
49
53
|
message = @mutex.synchronize do
|
50
54
|
@resource.wait(@mutex) if messages.empty?
|
@@ -43,6 +43,7 @@ module Solargraph
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
+
# @param uri [String]
|
46
47
|
# @return [void]
|
47
48
|
def add_uri(uri)
|
48
49
|
queue.push(uri)
|
@@ -72,6 +73,8 @@ module Solargraph
|
|
72
73
|
open_source_hash[uri] = source
|
73
74
|
end
|
74
75
|
|
76
|
+
# @param uri [String]
|
77
|
+
# @return [void]
|
75
78
|
def open_from_disk uri
|
76
79
|
source = Solargraph::Source.load(UriHelpers.uri_to_file(uri))
|
77
80
|
open_source_hash[uri] = source
|
@@ -83,7 +86,7 @@ module Solargraph
|
|
83
86
|
#
|
84
87
|
# @param uri [String]
|
85
88
|
# @param updater [Source::Updater]
|
86
|
-
# @return [
|
89
|
+
# @return [void]
|
87
90
|
def update uri, updater
|
88
91
|
src = find(uri)
|
89
92
|
mutex.synchronize { open_source_hash[uri] = src.synchronize(updater) }
|
@@ -109,7 +112,7 @@ module Solargraph
|
|
109
112
|
# @raise [FileNotFoundError] if the URI does not match an open source.
|
110
113
|
#
|
111
114
|
# @param uri [String]
|
112
|
-
# @return [Source]
|
115
|
+
# @return [Solargraph::Source]
|
113
116
|
def find uri
|
114
117
|
open_source_hash[uri] || raise(Solargraph::FileNotFoundError, "Host could not find #{uri}")
|
115
118
|
end
|
@@ -136,7 +139,7 @@ module Solargraph
|
|
136
139
|
|
137
140
|
private
|
138
141
|
|
139
|
-
# @return [Hash]
|
142
|
+
# @return [Hash{String => Solargraph::Source}]
|
140
143
|
def open_source_hash
|
141
144
|
@open_source_hash ||= {}
|
142
145
|
end
|
@@ -146,7 +149,7 @@ module Solargraph
|
|
146
149
|
|
147
150
|
# An array of source URIs that are waiting to finish synchronizing.
|
148
151
|
#
|
149
|
-
# @return [Array<String>]
|
152
|
+
# @return [::Array<String>]
|
150
153
|
def queue
|
151
154
|
@queue ||= []
|
152
155
|
end
|