solargraph 0.50.0 → 0.53.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/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 +81 -3
- data/README.md +13 -16
- data/SPONSORS.md +2 -9
- data/lib/solargraph/api_map/cache.rb +60 -20
- data/lib/solargraph/api_map/store.rb +47 -11
- data/lib/solargraph/api_map.rb +161 -95
- data/lib/solargraph/bench.rb +2 -2
- data/lib/solargraph/cache.rb +30 -6
- data/lib/solargraph/complex_type/type_methods.rb +54 -9
- data/lib/solargraph/complex_type/unique_type.rb +154 -57
- data/lib/solargraph/complex_type.rb +91 -17
- data/lib/solargraph/convention.rb +0 -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 +8 -7
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +1 -0
- data/lib/solargraph/diagnostics/type_check.rb +1 -0
- data/lib/solargraph/diagnostics.rb +2 -2
- data/lib/solargraph/doc_map.rb +146 -0
- data/lib/solargraph/gem_pins.rb +64 -0
- data/lib/solargraph/language_server/host/cataloger.rb +1 -0
- data/lib/solargraph/language_server/host/diagnoser.rb +2 -2
- data/lib/solargraph/language_server/host/dispatch.rb +10 -4
- 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 +26 -7
- 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/initialize.rb +11 -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/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.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 +86 -16
- data/lib/solargraph/location.rb +1 -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 +2 -2
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/cvasgn_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/def_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/defs_node.rb +2 -2
- data/lib/solargraph/parser/{rubyvm → 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/{legacy → parser_gem}/node_processors/sclass_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/send_node.rb +2 -2
- data/lib/solargraph/parser/{rubyvm → 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 +64 -9
- data/lib/solargraph/pin/base_variable.rb +6 -2
- data/lib/solargraph/pin/block.rb +19 -9
- data/lib/solargraph/pin/closure.rb +17 -2
- data/lib/solargraph/pin/common.rb +7 -3
- data/lib/solargraph/pin/conversions.rb +33 -3
- 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 +182 -18
- data/lib/solargraph/pin/namespace.rb +18 -5
- data/lib/solargraph/pin/parameter.rb +44 -14
- 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 +123 -3
- data/lib/solargraph/pin.rb +1 -1
- data/lib/solargraph/range.rb +4 -6
- data/lib/solargraph/rbs_map/conversions.rb +294 -50
- data/lib/solargraph/rbs_map/core_fills.rb +7 -24
- data/lib/solargraph/rbs_map/core_map.rb +3 -2
- data/lib/solargraph/rbs_map/core_signs.rb +2 -0
- data/lib/solargraph/rbs_map/stdlib_map.rb +2 -5
- data/lib/solargraph/rbs_map.rb +20 -11
- data/lib/solargraph/shell.rb +62 -59
- 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 +99 -46
- 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 +29 -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 +25 -23
- data/lib/solargraph/source_map/mapper.rb +12 -1
- data/lib/solargraph/source_map.rb +30 -7
- data/lib/solargraph/type_checker/checks.rb +10 -2
- data/lib/solargraph/type_checker.rb +123 -45
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +14 -11
- data/lib/solargraph/workspace.rb +3 -2
- 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 +11 -1
- 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 -284
- data/lib/solargraph/yard_tags.rb +20 -0
- data/lib/solargraph/yardoc.rb +52 -0
- data/lib/solargraph.rb +6 -4
- data/solargraph.gemspec +11 -5
- metadata +131 -75
- data/lib/solargraph/api_map/bundler_methods.rb +0 -22
- 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/cvasgn_node.rb +0 -23
- data/lib/solargraph/parser/legacy/node_processors/gvasgn_node.rb +0 -23
- data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +0 -18
- 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 -149
- 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 -33
- data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +0 -75
- data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +0 -68
- 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 -32
- data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +0 -15
- data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +0 -279
- data/lib/solargraph/parser/rubyvm/node_processors.rb +0 -63
- data/lib/solargraph/parser/rubyvm/node_wrapper.rb +0 -47
- data/lib/solargraph/parser/rubyvm.rb +0 -40
- data/lib/yard-solargraph.rb +0 -33
|
@@ -29,9 +29,9 @@ module Solargraph
|
|
|
29
29
|
store = RuboCop::ConfigStore.new
|
|
30
30
|
runner = RuboCop::Runner.new(options, store)
|
|
31
31
|
result = redirect_stdout{ runner.run(paths) }
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
return [] if result.empty?
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
make_array JSON.parse(result)
|
|
36
36
|
rescue RuboCop::ValidationError, RuboCop::ConfigNotFoundError => e
|
|
37
37
|
raise DiagnosticsError, "Error in RuboCop configuration: #{e.message}"
|
|
@@ -48,7 +48,7 @@ module Solargraph
|
|
|
48
48
|
args.find { |a| a =~ /version=/ }.to_s.split('=').last
|
|
49
49
|
end
|
|
50
50
|
|
|
51
|
-
# @param resp [Hash]
|
|
51
|
+
# @param resp [Hash{String => Array<Hash{String => Array<Hash{String => undefined}>}>}]
|
|
52
52
|
# @return [Array<Hash>]
|
|
53
53
|
def make_array resp
|
|
54
54
|
diagnostics = []
|
|
@@ -62,8 +62,8 @@ module Solargraph
|
|
|
62
62
|
|
|
63
63
|
# Convert a RuboCop offense to an LSP diagnostic
|
|
64
64
|
#
|
|
65
|
-
# @param off [Hash] Offense received from Rubocop
|
|
66
|
-
# @return [Hash] LSP diagnostic
|
|
65
|
+
# @param off [Hash{String => unknown}] Offense received from Rubocop
|
|
66
|
+
# @return [Hash{Symbol => Hash, String, Integer}] LSP diagnostic
|
|
67
67
|
def offense_to_diagnostic off
|
|
68
68
|
{
|
|
69
69
|
range: offense_range(off).to_hash,
|
|
@@ -81,19 +81,20 @@ module Solargraph
|
|
|
81
81
|
Range.new(offense_start_position(off), offense_ending_position(off))
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
-
# @param off [Hash]
|
|
84
|
+
# @param off [Hash{String => Hash{String => Integer}}]
|
|
85
85
|
# @return [Position]
|
|
86
86
|
def offense_start_position off
|
|
87
87
|
Position.new(off['location']['start_line'] - 1, off['location']['start_column'] - 1)
|
|
88
88
|
end
|
|
89
89
|
|
|
90
|
-
# @param off [Hash]
|
|
90
|
+
# @param off [Hash{String => Hash{String => Integer}}]
|
|
91
91
|
# @return [Position]
|
|
92
92
|
def offense_ending_position off
|
|
93
93
|
if off['location']['start_line'] != off['location']['last_line']
|
|
94
94
|
Position.new(off['location']['start_line'], 0)
|
|
95
95
|
else
|
|
96
96
|
start_line = off['location']['start_line'] - 1
|
|
97
|
+
# @type [Integer]
|
|
97
98
|
last_column = off['location']['last_column']
|
|
98
99
|
line = @source.code.lines[start_line]
|
|
99
100
|
col_off = if line.nil? || line.empty?
|
|
@@ -12,6 +12,7 @@ module Solargraph
|
|
|
12
12
|
#
|
|
13
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
|
|
@@ -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,146 @@
|
|
|
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 :dependencies
|
|
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 dependencies [Array<Gem::Specification>]
|
|
21
|
+
def initialize(requires, dependencies)
|
|
22
|
+
@requires = requires
|
|
23
|
+
@dependencies = dependencies
|
|
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
|
+
private
|
|
43
|
+
|
|
44
|
+
# @return [Hash{String => Gem::Specification, nil}]
|
|
45
|
+
def required_gem_map
|
|
46
|
+
@required_gem_map ||= requires.to_h { |path| [path, resolve_path_to_gemspec(path)] }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# @return [Hash{String => Gem::Specification}]
|
|
50
|
+
def dependency_map
|
|
51
|
+
@dependency_map ||= dependencies.to_h { |gemspec| [gemspec.name, gemspec] }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# @return [void]
|
|
55
|
+
def generate
|
|
56
|
+
@pins = []
|
|
57
|
+
@uncached_gemspecs = []
|
|
58
|
+
required_gem_map.each do |path, gemspec|
|
|
59
|
+
if gemspec
|
|
60
|
+
try_cache gemspec
|
|
61
|
+
else
|
|
62
|
+
try_stdlib_map path
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# @param gemspec [Gem::Specification]
|
|
68
|
+
# @return [void]
|
|
69
|
+
def try_cache gemspec
|
|
70
|
+
return if try_gem_in_memory(gemspec)
|
|
71
|
+
cache_file = File.join('gems', "#{gemspec.name}-#{gemspec.version}.ser")
|
|
72
|
+
if Cache.exist?(cache_file)
|
|
73
|
+
gempins = Cache.load(cache_file)
|
|
74
|
+
self.class.gems_in_memory[gemspec] = gempins
|
|
75
|
+
@pins.concat gempins
|
|
76
|
+
else
|
|
77
|
+
Solargraph.logger.debug "No pin cache for #{gemspec.name} #{gemspec.version}"
|
|
78
|
+
@uncached_gemspecs.push gemspec
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# @param path [String] require path that might be in the RBS stdlib collection
|
|
83
|
+
# @return [void]
|
|
84
|
+
def try_stdlib_map path
|
|
85
|
+
map = RbsMap::StdlibMap.load(path)
|
|
86
|
+
if map.resolved?
|
|
87
|
+
Solargraph.logger.debug "Loading stdlib pins for #{path}"
|
|
88
|
+
@pins.concat map.pins
|
|
89
|
+
else
|
|
90
|
+
# @todo Temporarily ignoring unresolved `require 'set'`
|
|
91
|
+
Solargraph.logger.warn "Require path #{path} could not be resolved" unless path == 'set'
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# @param gemspec [Gem::Specification]
|
|
96
|
+
# @return [Boolean]
|
|
97
|
+
def try_gem_in_memory gemspec
|
|
98
|
+
gempins = DocMap.gems_in_memory[gemspec]
|
|
99
|
+
return false unless gempins
|
|
100
|
+
Solargraph.logger.debug "Found #{gemspec.name} #{gemspec.version} in memory"
|
|
101
|
+
@pins.concat gempins
|
|
102
|
+
true
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# @param path [String]
|
|
106
|
+
# @return [Gem::Specification, nil]
|
|
107
|
+
def resolve_path_to_gemspec path
|
|
108
|
+
gemspec = Gem::Specification.find_by_path(path)
|
|
109
|
+
if gemspec.nil?
|
|
110
|
+
gem_name_guess = path.split('/').first
|
|
111
|
+
begin
|
|
112
|
+
# this can happen when the gem is included via a local path in
|
|
113
|
+
# a Gemfile; Gem doesn't try to index the paths in that case.
|
|
114
|
+
#
|
|
115
|
+
# See if we can make a good guess:
|
|
116
|
+
potential_gemspec = Gem::Specification.find_by_name(gem_name_guess)
|
|
117
|
+
file = "lib/#{path}.rb"
|
|
118
|
+
gemspec = potential_gemspec if potential_gemspec.files.any? { |gemspec_file| file == gemspec_file }
|
|
119
|
+
rescue Gem::MissingSpecError
|
|
120
|
+
Solargraph.logger.debug "Require path #{path} could not be resolved to a gem via find_by_path or guess of #{gem_name_guess}"
|
|
121
|
+
nil
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
return gemspec if dependencies.empty? || gemspec.nil?
|
|
125
|
+
|
|
126
|
+
if dependency_map.key?(gemspec.name)
|
|
127
|
+
return gemspec if gemspec.version == dependency_map[gemspec.name].version
|
|
128
|
+
|
|
129
|
+
change_gemspec_version gemspec, dependency_map[by_path.name].version
|
|
130
|
+
else
|
|
131
|
+
Solargraph.logger.warn "Gem #{gemspec.name} is not an expected dependency"
|
|
132
|
+
gemspec
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# @param gemspec [Gem::Specification]
|
|
137
|
+
# @param version [Gem::Version]
|
|
138
|
+
# @return [Gem::Specification]
|
|
139
|
+
def change_gemspec_version gemspec, version
|
|
140
|
+
Gem::Specification.find_by_name(gemspec.name, "= #{version}")
|
|
141
|
+
rescue Gem::MissingSpecError
|
|
142
|
+
Solargraph.logger.info "Gem #{gemspec.name} version #{version} not found. Using #{gemspec.version} instead"
|
|
143
|
+
gemspec
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
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)
|
|
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
|
|
@@ -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
|
|
|
@@ -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
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
require 'diff/lcs'
|
|
4
4
|
require 'observer'
|
|
5
5
|
require 'securerandom'
|
|
6
|
-
require 'set'
|
|
7
6
|
|
|
8
7
|
module Solargraph
|
|
9
8
|
module LanguageServer
|
|
@@ -59,7 +58,7 @@ module Solargraph
|
|
|
59
58
|
logger.level = LOG_LEVELS[options['logLevel']] || DEFAULT_LOG_LEVEL
|
|
60
59
|
end
|
|
61
60
|
|
|
62
|
-
# @return [Hash]
|
|
61
|
+
# @return [Hash{String => [Boolean, String]}]
|
|
63
62
|
def options
|
|
64
63
|
@options ||= default_configuration
|
|
65
64
|
end
|
|
@@ -101,8 +100,8 @@ module Solargraph
|
|
|
101
100
|
# Start processing a request from the client. After the message is
|
|
102
101
|
# processed, caller is responsible for sending the response.
|
|
103
102
|
#
|
|
104
|
-
# @param request [Hash] The contents of the message.
|
|
105
|
-
# @return [Solargraph::LanguageServer::Message::Base] The message handler.
|
|
103
|
+
# @param request [Hash{String => unspecified}] The contents of the message.
|
|
104
|
+
# @return [Solargraph::LanguageServer::Message::Base, nil] The message handler.
|
|
106
105
|
def receive request
|
|
107
106
|
if request['method']
|
|
108
107
|
logger.info "Server received #{request['method']}"
|
|
@@ -127,6 +126,7 @@ module Solargraph
|
|
|
127
126
|
else
|
|
128
127
|
logger.warn "Invalid message received."
|
|
129
128
|
logger.debug request
|
|
129
|
+
nil
|
|
130
130
|
end
|
|
131
131
|
end
|
|
132
132
|
|
|
@@ -505,6 +505,8 @@ module Solargraph
|
|
|
505
505
|
library.read_text(filename)
|
|
506
506
|
end
|
|
507
507
|
|
|
508
|
+
# @param uri [String]
|
|
509
|
+
# @return [Hash]
|
|
508
510
|
def formatter_config uri
|
|
509
511
|
library = library_for(uri)
|
|
510
512
|
library.workspace.config.formatter
|
|
@@ -533,6 +535,15 @@ module Solargraph
|
|
|
533
535
|
library.definitions_at(uri_to_file(uri), line, column)
|
|
534
536
|
end
|
|
535
537
|
|
|
538
|
+
# @param uri [String]
|
|
539
|
+
# @param line [Integer]
|
|
540
|
+
# @param column [Integer]
|
|
541
|
+
# @return [Array<Solargraph::Pin::Base>]
|
|
542
|
+
def type_definitions_at uri, line, column
|
|
543
|
+
library = library_for(uri)
|
|
544
|
+
library.type_definitions_at(uri_to_file(uri), line, column)
|
|
545
|
+
end
|
|
546
|
+
|
|
536
547
|
# @param uri [String]
|
|
537
548
|
# @param line [Integer]
|
|
538
549
|
# @param column [Integer]
|
|
@@ -623,17 +634,18 @@ module Solargraph
|
|
|
623
634
|
requests.keys
|
|
624
635
|
end
|
|
625
636
|
|
|
626
|
-
# @return [Hash{String =>
|
|
637
|
+
# @return [Hash{String => [Boolean,String]}]
|
|
627
638
|
def default_configuration
|
|
628
639
|
{
|
|
629
640
|
'completion' => true,
|
|
630
641
|
'hover' => true,
|
|
631
642
|
'symbols' => true,
|
|
632
643
|
'definitions' => true,
|
|
644
|
+
'typeDefinitions' => true,
|
|
633
645
|
'rename' => true,
|
|
634
646
|
'references' => true,
|
|
635
647
|
'autoformat' => false,
|
|
636
|
-
'diagnostics' =>
|
|
648
|
+
'diagnostics' => true,
|
|
637
649
|
'formatting' => false,
|
|
638
650
|
'folding' => true,
|
|
639
651
|
'highlights' => true,
|
|
@@ -653,6 +665,7 @@ module Solargraph
|
|
|
653
665
|
libraries.each(&:catalog)
|
|
654
666
|
end
|
|
655
667
|
|
|
668
|
+
# @return [Hash{String => BasicObject}]
|
|
656
669
|
def client_capabilities
|
|
657
670
|
@client_capabilities ||= {}
|
|
658
671
|
end
|
|
@@ -677,7 +690,7 @@ module Solargraph
|
|
|
677
690
|
# A hash of client requests by ID. The host uses this to keep track of
|
|
678
691
|
# pending responses.
|
|
679
692
|
#
|
|
680
|
-
# @return [Hash{Integer =>
|
|
693
|
+
# @return [Hash{Integer => Solargraph::LanguageServer::Host}]
|
|
681
694
|
def requests
|
|
682
695
|
@requests ||= {}
|
|
683
696
|
end
|
|
@@ -769,6 +782,9 @@ module Solargraph
|
|
|
769
782
|
'textDocument/definition' => {
|
|
770
783
|
definitionProvider: true
|
|
771
784
|
},
|
|
785
|
+
'textDocument/typeDefinition' => {
|
|
786
|
+
typeDefinitionProvider: true
|
|
787
|
+
},
|
|
772
788
|
'textDocument/references' => {
|
|
773
789
|
referencesProvider: true
|
|
774
790
|
},
|
|
@@ -822,6 +838,9 @@ module Solargraph
|
|
|
822
838
|
end
|
|
823
839
|
end
|
|
824
840
|
|
|
841
|
+
# @param library [Library]
|
|
842
|
+
# @param uuid [String, nil]
|
|
843
|
+
# @return [void]
|
|
825
844
|
def do_async_library_map library, uuid = nil
|
|
826
845
|
total = library.workspace.sources.length
|
|
827
846
|
if uuid
|
|
@@ -29,7 +29,7 @@ module Solargraph
|
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
# @param text [String]
|
|
32
|
-
# @return [Hash{Symbol => String}]
|
|
32
|
+
# @return [Hash{Symbol => String}, nil]
|
|
33
33
|
def markup_content text
|
|
34
34
|
return nil if text.strip.empty?
|
|
35
35
|
{
|
|
@@ -38,6 +38,8 @@ module Solargraph
|
|
|
38
38
|
}
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
+
# @param pins [Array<Pin::Base>]
|
|
42
|
+
# @return [String]
|
|
41
43
|
def join_docs pins
|
|
42
44
|
result = []
|
|
43
45
|
last_link = nil
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
# @todo PR the RBS gem to add this
|
|
5
|
+
# @!parse
|
|
6
|
+
# module ::Gem
|
|
7
|
+
# class SpecFetcher; end
|
|
8
|
+
# end
|
|
4
9
|
|
|
5
10
|
module Solargraph
|
|
6
11
|
module LanguageServer
|
|
@@ -11,16 +16,23 @@ module Solargraph
|
|
|
11
16
|
# is true, notify the client when the gem is up to date.
|
|
12
17
|
#
|
|
13
18
|
class CheckGemVersion < Base
|
|
19
|
+
# @return [Gem::SpecFetcher]
|
|
14
20
|
def self.fetcher
|
|
15
21
|
@fetcher ||= Gem::SpecFetcher.new
|
|
16
22
|
end
|
|
17
23
|
|
|
24
|
+
# @param obj [Gem::SpecFetcher]
|
|
25
|
+
# @return [Gem::SpecFetcher]
|
|
18
26
|
def self.fetcher= obj
|
|
19
27
|
@fetcher = obj
|
|
20
28
|
end
|
|
21
29
|
|
|
22
30
|
GEM_ZERO = Gem::Version.new('0.0.0')
|
|
23
31
|
|
|
32
|
+
# @param host [Solargraph::LanguageServer::Host]
|
|
33
|
+
# @param request [Hash]
|
|
34
|
+
# @param current [Gem::Version]
|
|
35
|
+
# @param available [Gem::Version, nil]
|
|
24
36
|
def initialize host, request, current: Gem::Version.new(Solargraph::VERSION), available: nil
|
|
25
37
|
super(host, request)
|
|
26
38
|
@current = current
|
|
@@ -34,6 +34,7 @@ module Solargraph
|
|
|
34
34
|
result[:capabilities].merge! static_document_formatting unless dynamic_registration_for?('textDocument', 'formatting')
|
|
35
35
|
result[:capabilities].merge! static_document_symbols unless dynamic_registration_for?('textDocument', 'documentSymbol')
|
|
36
36
|
result[:capabilities].merge! static_definitions unless dynamic_registration_for?('textDocument', 'definition')
|
|
37
|
+
result[:capabilities].merge! static_type_definitions unless dynamic_registration_for?('textDocument', 'typeDefinition')
|
|
37
38
|
result[:capabilities].merge! static_rename unless dynamic_registration_for?('textDocument', 'rename')
|
|
38
39
|
result[:capabilities].merge! static_references unless dynamic_registration_for?('textDocument', 'references')
|
|
39
40
|
result[:capabilities].merge! static_workspace_symbols unless dynamic_registration_for?('workspace', 'symbol')
|
|
@@ -53,6 +54,7 @@ module Solargraph
|
|
|
53
54
|
params['workspaceFolders']
|
|
54
55
|
end
|
|
55
56
|
|
|
57
|
+
# @return [Hash{Symbol => undefined}]
|
|
56
58
|
def static_completion
|
|
57
59
|
return {} unless host.options['completion']
|
|
58
60
|
{
|
|
@@ -63,6 +65,7 @@ module Solargraph
|
|
|
63
65
|
}
|
|
64
66
|
end
|
|
65
67
|
|
|
68
|
+
# @return [Hash{Symbol => BasicObject}]
|
|
66
69
|
def static_code_action
|
|
67
70
|
{
|
|
68
71
|
codeActionProvider: true,
|
|
@@ -70,6 +73,7 @@ module Solargraph
|
|
|
70
73
|
}
|
|
71
74
|
end
|
|
72
75
|
|
|
76
|
+
# @return [Hash{Symbol => BasicObject}]
|
|
73
77
|
def static_signature_help
|
|
74
78
|
{
|
|
75
79
|
signatureHelpProvider: {
|
|
@@ -121,6 +125,13 @@ module Solargraph
|
|
|
121
125
|
}
|
|
122
126
|
end
|
|
123
127
|
|
|
128
|
+
def static_type_definitions
|
|
129
|
+
return {} unless host.options['typeDefinitions']
|
|
130
|
+
{
|
|
131
|
+
typeDefinitionProvider: true
|
|
132
|
+
}
|
|
133
|
+
end
|
|
134
|
+
|
|
124
135
|
def static_rename
|
|
125
136
|
{
|
|
126
137
|
renameProvider: {prepareProvider: true}
|