solargraph 0.54.5 → 0.55.4
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/typecheck.yml +1 -1
- data/CHANGELOG.md +27 -0
- data/lib/solargraph/api_map/store.rb +9 -4
- data/lib/solargraph/api_map.rb +116 -39
- data/lib/solargraph/complex_type/type_methods.rb +1 -0
- data/lib/solargraph/complex_type/unique_type.rb +91 -9
- data/lib/solargraph/complex_type.rb +35 -6
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +60 -0
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +100 -0
- data/lib/solargraph/convention/struct_definition.rb +101 -0
- data/lib/solargraph/convention.rb +1 -0
- data/lib/solargraph/doc_map.rb +83 -23
- data/lib/solargraph/gem_pins.rb +2 -1
- data/lib/solargraph/language_server/host/message_worker.rb +10 -7
- data/lib/solargraph/language_server/host.rb +3 -1
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +1 -0
- data/lib/solargraph/location.rb +8 -0
- data/lib/solargraph/logging.rb +1 -0
- data/lib/solargraph/parser/comment_ripper.rb +12 -6
- data/lib/solargraph/parser/flow_sensitive_typing.rb +227 -0
- data/lib/solargraph/parser/node_methods.rb +14 -0
- data/lib/solargraph/parser/node_processor.rb +3 -2
- data/lib/solargraph/parser/parser_gem/class_methods.rb +9 -0
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +10 -10
- data/lib/solargraph/parser/parser_gem/node_methods.rb +4 -2
- 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 +4 -2
- data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +23 -2
- 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 +21 -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/namespace_node.rb +29 -6
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +41 -0
- data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -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 +28 -16
- data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +2 -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 +10 -0
- data/lib/solargraph/parser/region.rb +1 -1
- data/lib/solargraph/parser.rb +1 -0
- data/lib/solargraph/pin/base.rb +34 -5
- data/lib/solargraph/pin/base_variable.rb +7 -1
- data/lib/solargraph/pin/block.rb +2 -0
- data/lib/solargraph/pin/breakable.rb +9 -0
- data/lib/solargraph/pin/callable.rb +5 -3
- data/lib/solargraph/pin/closure.rb +6 -1
- data/lib/solargraph/pin/common.rb +5 -0
- data/lib/solargraph/pin/delegated_method.rb +20 -1
- data/lib/solargraph/pin/documenting.rb +16 -0
- data/lib/solargraph/pin/keyword.rb +7 -2
- data/lib/solargraph/pin/local_variable.rb +7 -1
- data/lib/solargraph/pin/method.rb +34 -27
- data/lib/solargraph/pin/namespace.rb +17 -9
- data/lib/solargraph/pin/parameter.rb +17 -5
- data/lib/solargraph/pin/proxy_type.rb +12 -6
- data/lib/solargraph/pin/reference/override.rb +10 -6
- data/lib/solargraph/pin/reference/require.rb +2 -2
- data/lib/solargraph/pin/signature.rb +4 -0
- data/lib/solargraph/pin/singleton.rb +1 -1
- data/lib/solargraph/pin/symbol.rb +3 -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/rbs_map/conversions.rb +172 -56
- data/lib/solargraph/rbs_map/core_fills.rb +32 -16
- data/lib/solargraph/rbs_map/core_map.rb +3 -2
- data/lib/solargraph/shell.rb +1 -0
- 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 +2 -0
- 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 +78 -48
- data/lib/solargraph/source/source_chainer.rb +2 -2
- data/lib/solargraph/source_map/clip.rb +3 -1
- data/lib/solargraph/source_map/mapper.rb +9 -5
- data/lib/solargraph/type_checker/checks.rb +4 -0
- data/lib/solargraph/type_checker.rb +35 -8
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/yard_map/mapper/to_constant.rb +4 -2
- data/lib/solargraph/yard_map/mapper/to_method.rb +55 -15
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +4 -2
- data/lib/solargraph/yard_map/mapper.rb +4 -3
- data/lib/solargraph/yard_map/to_method.rb +4 -2
- data/lib/solargraph.rb +20 -0
- data/rbs/fills/tuple.rbs +150 -0
- metadata +15 -2
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Solargraph
|
4
|
+
module Convention
|
5
|
+
module StructDefinition
|
6
|
+
# A node wrapper for a Struct definition via inheritance.
|
7
|
+
# @example
|
8
|
+
# class MyStruct < Struct.new(:bar, :baz)
|
9
|
+
# def foo
|
10
|
+
# end
|
11
|
+
# end
|
12
|
+
class StructDefintionNode
|
13
|
+
class << self
|
14
|
+
# @example
|
15
|
+
# s(:class,
|
16
|
+
# s(:const, nil, :Foo),
|
17
|
+
# s(:send,
|
18
|
+
# s(:const, nil, :Struct), :new,
|
19
|
+
# s(:sym, :bar),
|
20
|
+
# s(:sym, :baz)),
|
21
|
+
# s(:hash,
|
22
|
+
# s(:pair,
|
23
|
+
# s(:sym, :keyword_init),
|
24
|
+
# s(:true)))),
|
25
|
+
# s(:def, :foo,
|
26
|
+
# s(:args),
|
27
|
+
# s(:send, nil, :bar)))
|
28
|
+
def valid?(node)
|
29
|
+
return false unless node&.type == :class
|
30
|
+
|
31
|
+
struct_definition_node?(node.children[1])
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# @param struct_node [Parser::AST::Node]
|
37
|
+
# @return [Boolean]
|
38
|
+
def struct_definition_node?(struct_node)
|
39
|
+
return false unless struct_node.is_a?(::Parser::AST::Node)
|
40
|
+
return false unless struct_node&.type == :send
|
41
|
+
return false unless struct_node.children[0]&.type == :const
|
42
|
+
return false unless struct_node.children[0].children[1] == :Struct
|
43
|
+
return false unless struct_node.children[1] == :new
|
44
|
+
|
45
|
+
true
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# @return [Parser::AST::Node]
|
50
|
+
def initialize(node)
|
51
|
+
@node = node
|
52
|
+
end
|
53
|
+
|
54
|
+
# @return [String]
|
55
|
+
def class_name
|
56
|
+
Parser::NodeMethods.unpack_name(node)
|
57
|
+
end
|
58
|
+
|
59
|
+
# @return [Array<Array(Parser::AST::Node, String)>]
|
60
|
+
def attributes
|
61
|
+
struct_attribute_nodes.map do |struct_def_param|
|
62
|
+
next unless struct_def_param.type == :sym
|
63
|
+
[struct_def_param, struct_def_param.children[0].to_s]
|
64
|
+
end.compact
|
65
|
+
end
|
66
|
+
|
67
|
+
def keyword_init?
|
68
|
+
keyword_init_param = struct_attribute_nodes.find do |struct_def_param|
|
69
|
+
struct_def_param.type == :hash && struct_def_param.children[0].type == :pair &&
|
70
|
+
struct_def_param.children[0].children[0].children[0] == :keyword_init
|
71
|
+
end
|
72
|
+
|
73
|
+
return false if keyword_init_param.nil?
|
74
|
+
|
75
|
+
keyword_init_param.children[0].children[1].type == :true
|
76
|
+
end
|
77
|
+
|
78
|
+
# @return [Parser::AST::Node]
|
79
|
+
def body_node
|
80
|
+
node.children[2]
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
# @return [Parser::AST::Node]
|
86
|
+
attr_reader :node
|
87
|
+
|
88
|
+
# @return [Parser::AST::Node]
|
89
|
+
def struct_node
|
90
|
+
node.children[1]
|
91
|
+
end
|
92
|
+
|
93
|
+
# @return [Array<Parser::AST::Node>]
|
94
|
+
def struct_attribute_nodes
|
95
|
+
struct_node.children[2..-1]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Solargraph
|
4
|
+
module Convention
|
5
|
+
module StructDefinition
|
6
|
+
autoload :StructDefintionNode, 'solargraph/convention/struct_definition/struct_definition_node'
|
7
|
+
autoload :StructAssignmentNode, 'solargraph/convention/struct_definition/struct_assignment_node'
|
8
|
+
|
9
|
+
module NodeProcessors
|
10
|
+
class StructNode < Parser::NodeProcessor::Base
|
11
|
+
def process
|
12
|
+
return if struct_definition_node.nil?
|
13
|
+
|
14
|
+
loc = get_node_location(node)
|
15
|
+
nspin = Solargraph::Pin::Namespace.new(
|
16
|
+
type: :class,
|
17
|
+
location: loc,
|
18
|
+
closure: region.closure,
|
19
|
+
name: struct_definition_node.class_name,
|
20
|
+
comments: comments_for(node),
|
21
|
+
visibility: :public,
|
22
|
+
gates: region.closure.gates.freeze
|
23
|
+
)
|
24
|
+
pins.push nspin
|
25
|
+
|
26
|
+
# define initialize method
|
27
|
+
initialize_method_pin = Pin::Method.new(
|
28
|
+
name: 'initialize',
|
29
|
+
parameters: [],
|
30
|
+
scope: :instance,
|
31
|
+
location: get_node_location(node),
|
32
|
+
closure: nspin,
|
33
|
+
visibility: :private,
|
34
|
+
comments: comments_for(node)
|
35
|
+
)
|
36
|
+
|
37
|
+
pins.push initialize_method_pin
|
38
|
+
|
39
|
+
struct_definition_node.attributes.map do |attribute_node, attribute_name|
|
40
|
+
initialize_method_pin.parameters.push(
|
41
|
+
Pin::Parameter.new(
|
42
|
+
name: attribute_name,
|
43
|
+
decl: struct_definition_node.keyword_init? ? :kwarg : :arg,
|
44
|
+
location: get_node_location(attribute_node),
|
45
|
+
closure: initialize_method_pin
|
46
|
+
)
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
# define attribute accessors and instance variables
|
51
|
+
struct_definition_node.attributes.each do |attribute_node, attribute_name|
|
52
|
+
[attribute_name, "#{attribute_name}="].each do |name|
|
53
|
+
method_pin = Pin::Method.new(
|
54
|
+
name: name,
|
55
|
+
parameters: [],
|
56
|
+
scope: :instance,
|
57
|
+
location: get_node_location(attribute_node),
|
58
|
+
closure: nspin,
|
59
|
+
comments: attribute_comments(attribute_node, attribute_name),
|
60
|
+
visibility: :public
|
61
|
+
)
|
62
|
+
|
63
|
+
pins.push method_pin
|
64
|
+
|
65
|
+
next unless name.include?('=') # setter
|
66
|
+
pins.push Pin::InstanceVariable.new(name: "@#{attribute_name}",
|
67
|
+
closure: method_pin,
|
68
|
+
location: get_node_location(attribute_node),
|
69
|
+
comments: attribute_comments(attribute_node, attribute_name))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
process_children region.update(closure: nspin, visibility: :public)
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
# @return [StructDefintionNode, nil]
|
79
|
+
def struct_definition_node
|
80
|
+
@struct_definition_node ||= if StructDefintionNode.valid?(node)
|
81
|
+
StructDefintionNode.new(node)
|
82
|
+
elsif StructAssignmentNode.valid?(node)
|
83
|
+
StructAssignmentNode.new(node)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# @param attribute_node [Parser::AST::Node]
|
88
|
+
# @return [String, nil]
|
89
|
+
def attribute_comments(attribute_node, attribute_name)
|
90
|
+
struct_comments = comments_for(attribute_node)
|
91
|
+
return if struct_comments.nil? || struct_comments.empty?
|
92
|
+
|
93
|
+
struct_comments.split("\n").find do |row|
|
94
|
+
row.include?(attribute_name)
|
95
|
+
end&.gsub('@param', '@return')&.gsub(attribute_name, '')
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -10,6 +10,7 @@ module Solargraph
|
|
10
10
|
autoload :Gemfile, 'solargraph/convention/gemfile'
|
11
11
|
autoload :Gemspec, 'solargraph/convention/gemspec'
|
12
12
|
autoload :Rakefile, 'solargraph/convention/rakefile'
|
13
|
+
autoload :StructDefinition, 'solargraph/convention/struct_definition'
|
13
14
|
|
14
15
|
# @type [Set<Convention::Base>]
|
15
16
|
@@conventions = Set.new
|
data/lib/solargraph/doc_map.rb
CHANGED
@@ -4,6 +4,8 @@ module Solargraph
|
|
4
4
|
# A collection of pins generated from required gems.
|
5
5
|
#
|
6
6
|
class DocMap
|
7
|
+
include Logging
|
8
|
+
|
7
9
|
# @return [Array<String>]
|
8
10
|
attr_reader :requires
|
9
11
|
|
@@ -16,24 +18,27 @@ module Solargraph
|
|
16
18
|
# @return [Array<Gem::Specification>]
|
17
19
|
attr_reader :uncached_gemspecs
|
18
20
|
|
21
|
+
# @return [Workspace, nil]
|
22
|
+
attr_reader :workspace
|
23
|
+
|
19
24
|
# @param requires [Array<String>]
|
20
25
|
# @param preferences [Array<Gem::Specification>]
|
21
|
-
# @param
|
22
|
-
def initialize(requires, preferences,
|
26
|
+
# @param workspace [Workspace, nil]
|
27
|
+
def initialize(requires, preferences, workspace = nil)
|
23
28
|
@requires = requires.compact
|
24
29
|
@preferences = preferences.compact
|
25
|
-
@
|
30
|
+
@workspace = workspace
|
26
31
|
generate
|
27
32
|
end
|
28
33
|
|
29
34
|
# @return [Array<Gem::Specification>]
|
30
35
|
def gemspecs
|
31
|
-
@gemspecs ||=
|
36
|
+
@gemspecs ||= required_gems_map.values.compact.flatten
|
32
37
|
end
|
33
38
|
|
34
39
|
# @return [Array<String>]
|
35
40
|
def unresolved_requires
|
36
|
-
@unresolved_requires ||=
|
41
|
+
@unresolved_requires ||= required_gems_map.select { |_, gemspecs| gemspecs.nil? }.keys
|
37
42
|
end
|
38
43
|
|
39
44
|
# @return [Hash{Gem::Specification => Array[Pin::Base]}]
|
@@ -52,20 +57,22 @@ module Solargraph
|
|
52
57
|
def generate
|
53
58
|
@pins = []
|
54
59
|
@uncached_gemspecs = []
|
55
|
-
|
56
|
-
if
|
57
|
-
try_cache gemspec
|
58
|
-
else
|
60
|
+
required_gems_map.each do |path, gemspecs|
|
61
|
+
if gemspecs.nil?
|
59
62
|
try_stdlib_map path
|
63
|
+
else
|
64
|
+
gemspecs.each do |gemspec|
|
65
|
+
try_cache gemspec
|
66
|
+
end
|
60
67
|
end
|
61
68
|
end
|
62
69
|
dependencies.each { |dep| try_cache dep }
|
63
70
|
@uncached_gemspecs.uniq!
|
64
71
|
end
|
65
72
|
|
66
|
-
# @return [Hash{String => Gem::Specification
|
67
|
-
def
|
68
|
-
@
|
73
|
+
# @return [Hash{String => Array<Gem::Specification>}]
|
74
|
+
def required_gems_map
|
75
|
+
@required_gems_map ||= requires.to_h { |path| [path, resolve_path_to_gemspecs(path)] }
|
69
76
|
end
|
70
77
|
|
71
78
|
# @return [Hash{String => Gem::Specification}]
|
@@ -114,10 +121,10 @@ module Solargraph
|
|
114
121
|
|
115
122
|
# @param gemspec [Gem::Specification]
|
116
123
|
def update_from_collection gemspec, gempins
|
117
|
-
return gempins unless
|
124
|
+
return gempins unless workspace&.rbs_collection_path && File.directory?(workspace&.rbs_collection_path)
|
118
125
|
return gempins if RbsMap.new(gemspec.name, gemspec.version).resolved?
|
119
126
|
|
120
|
-
rbs_map = RbsMap.new(gemspec.name, gemspec.version, directories: [
|
127
|
+
rbs_map = RbsMap.new(gemspec.name, gemspec.version, directories: [workspace&.rbs_collection_path])
|
121
128
|
return gempins unless rbs_map.resolved?
|
122
129
|
|
123
130
|
Solargraph.logger.info "Updating #{gemspec.name} #{gemspec.version} from collection"
|
@@ -125,9 +132,10 @@ module Solargraph
|
|
125
132
|
end
|
126
133
|
|
127
134
|
# @param path [String]
|
128
|
-
# @return [Gem::Specification
|
129
|
-
def
|
135
|
+
# @return [::Array<Gem::Specification>, nil]
|
136
|
+
def resolve_path_to_gemspecs path
|
130
137
|
return nil if path.empty?
|
138
|
+
return gemspecs_required_from_bundler if path == 'bundler/require'
|
131
139
|
|
132
140
|
gemspec = Gem::Specification.find_by_path(path)
|
133
141
|
if gemspec.nil?
|
@@ -142,16 +150,17 @@ module Solargraph
|
|
142
150
|
gemspec = potential_gemspec if potential_gemspec.files.any? { |gemspec_file| file == gemspec_file }
|
143
151
|
rescue Gem::MissingSpecError
|
144
152
|
Solargraph.logger.debug "Require path #{path} could not be resolved to a gem via find_by_path or guess of #{gem_name_guess}"
|
145
|
-
|
153
|
+
[]
|
146
154
|
end
|
147
155
|
end
|
148
|
-
|
156
|
+
return nil if gemspec.nil?
|
157
|
+
[gemspec_or_preference(gemspec)]
|
149
158
|
end
|
150
159
|
|
151
|
-
# @param gemspec [Gem::Specification
|
152
|
-
# @return [Gem::Specification
|
160
|
+
# @param gemspec [Gem::Specification]
|
161
|
+
# @return [Gem::Specification]
|
153
162
|
def gemspec_or_preference gemspec
|
154
|
-
return gemspec unless
|
163
|
+
return gemspec unless preference_map.key?(gemspec.name)
|
155
164
|
return gemspec if gemspec.version == preference_map[gemspec.name].version
|
156
165
|
|
157
166
|
change_gemspec_version gemspec, preference_map[by_path.name].version
|
@@ -170,12 +179,15 @@ module Solargraph
|
|
170
179
|
# @param gemspec [Gem::Specification]
|
171
180
|
# @return [Array<Gem::Specification>]
|
172
181
|
def fetch_dependencies gemspec
|
182
|
+
# @param spec [Gem::Dependency]
|
173
183
|
only_runtime_dependencies(gemspec).each_with_object(Set.new) do |spec, deps|
|
174
184
|
Solargraph.logger.info "Adding #{spec.name} dependency for #{gemspec.name}"
|
175
|
-
dep = Gem
|
185
|
+
dep = Gem.loaded_specs[spec.name]
|
186
|
+
# @todo is next line necessary?
|
187
|
+
dep ||= Gem::Specification.find_by_name(spec.name, spec.requirement)
|
176
188
|
deps.merge fetch_dependencies(dep) if deps.add?(dep)
|
177
189
|
rescue Gem::MissingSpecError
|
178
|
-
Solargraph.logger.warn "Gem dependency #{spec.name} #{spec.
|
190
|
+
Solargraph.logger.warn "Gem dependency #{spec.name} #{spec.requirement} for #{gemspec.name} not found."
|
179
191
|
end.to_a
|
180
192
|
end
|
181
193
|
|
@@ -184,5 +196,53 @@ module Solargraph
|
|
184
196
|
def only_runtime_dependencies gemspec
|
185
197
|
gemspec.dependencies - gemspec.development_dependencies
|
186
198
|
end
|
199
|
+
|
200
|
+
def gemspecs_required_from_bundler
|
201
|
+
if workspace&.directory && Bundler.definition&.lockfile&.to_s&.start_with?(workspace.directory)
|
202
|
+
# Find only the gems bundler is now using
|
203
|
+
Bundler.definition.locked_gems.specs.flat_map do |lazy_spec|
|
204
|
+
logger.info "Handling #{lazy_spec.name}:#{lazy_spec.version}"
|
205
|
+
[Gem::Specification.find_by_name(lazy_spec.name, lazy_spec.version)]
|
206
|
+
rescue Gem::MissingSpecError => e
|
207
|
+
logger.info("Could not find #{lazy_spec.name}:#{lazy_spec.version} with find_by_name, falling back to guess")
|
208
|
+
# can happen in local filesystem references
|
209
|
+
specs = resolve_path_to_gemspecs lazy_spec.name
|
210
|
+
logger.warn "Gem #{lazy_spec.name} #{lazy_spec.version} from bundle not found: #{e}" if specs.nil?
|
211
|
+
next specs
|
212
|
+
end.compact
|
213
|
+
else
|
214
|
+
logger.info 'Fetching gemspecs required from Bundler (bundler/require)'
|
215
|
+
gemspecs_required_from_external_bundle
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def gemspecs_required_from_external_bundle
|
220
|
+
logger.info 'Fetching gemspecs required from external bundle'
|
221
|
+
return [] unless workspace&.directory
|
222
|
+
|
223
|
+
Solargraph.with_clean_env do
|
224
|
+
cmd = [
|
225
|
+
'ruby', '-e',
|
226
|
+
"require 'bundler'; require 'json'; Dir.chdir('#{workspace&.directory}') { puts Bundler.definition.locked_gems.specs.map { |spec| [spec.name, spec.version] }.to_h.to_json }"
|
227
|
+
]
|
228
|
+
o, e, s = Open3.capture3(*cmd)
|
229
|
+
if s.success?
|
230
|
+
Solargraph.logger.debug "External bundle: #{o}"
|
231
|
+
hash = o && !o.empty? ? JSON.parse(o.split("\n").last) : {}
|
232
|
+
hash.flat_map do |name, version|
|
233
|
+
Gem::Specification.find_by_name(name, version)
|
234
|
+
rescue Gem::MissingSpecError => e
|
235
|
+
logger.info("Could not find #{name}:#{version} with find_by_name, falling back to guess")
|
236
|
+
# can happen in local filesystem references
|
237
|
+
specs = resolve_path_to_gemspecs name
|
238
|
+
logger.warn "Gem #{name} #{version} from bundle not found: #{e}" if specs.nil?
|
239
|
+
next specs
|
240
|
+
end.compact
|
241
|
+
else
|
242
|
+
Solargraph.logger.warn e
|
243
|
+
raise BundleNotFoundError, "Failed to load gems from bundle at #{workspace&.directory}"
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
187
247
|
end
|
188
248
|
end
|
data/lib/solargraph/gem_pins.rb
CHANGED
@@ -42,7 +42,8 @@ module Solargraph
|
|
42
42
|
generics: rbs.generics,
|
43
43
|
node: yard.node,
|
44
44
|
signatures: yard.signatures,
|
45
|
-
return_type: best_return_type(rbs.return_type, yard.return_type)
|
45
|
+
return_type: best_return_type(rbs.return_type, yard.return_type),
|
46
|
+
source: :gem_pins
|
46
47
|
)
|
47
48
|
end
|
48
49
|
in_rbs = rbs_map.pins.reject { |pin| in_yard.include?(pin.path) }
|
@@ -7,9 +7,16 @@ module Solargraph
|
|
7
7
|
#
|
8
8
|
class MessageWorker
|
9
9
|
UPDATE_METHODS = [
|
10
|
-
'textDocument/didOpen',
|
11
10
|
'textDocument/didChange',
|
12
|
-
'
|
11
|
+
'textDocument/didClose',
|
12
|
+
'textDocument/didOpen',
|
13
|
+
'textDocument/didSave',
|
14
|
+
'workspace/didChangeConfiguration',
|
15
|
+
'workspace/didChangeWatchedFiles',
|
16
|
+
'workspace/didCreateFiles',
|
17
|
+
'workspace/didChangeWorkspaceFolders',
|
18
|
+
'workspace/didDeleteFiles',
|
19
|
+
'workspace/didRenameFiles'
|
13
20
|
].freeze
|
14
21
|
|
15
22
|
# @param host [Host]
|
@@ -84,11 +91,7 @@ module Solargraph
|
|
84
91
|
idx = messages.find_index do |msg|
|
85
92
|
UPDATE_METHODS.include?(msg['method']) || version_dependent?(msg)
|
86
93
|
end
|
87
|
-
|
88
|
-
|
89
|
-
msg = messages[idx]
|
90
|
-
messages.delete_at idx
|
91
|
-
msg
|
94
|
+
idx ? messages.delete_at(idx) : messages.shift
|
92
95
|
end
|
93
96
|
|
94
97
|
# True if the message requires a previous update to have executed in
|
@@ -501,7 +501,8 @@ module Solargraph
|
|
501
501
|
parameters: pin.parameters,
|
502
502
|
return_type: ComplexType.try_parse(params['data']['path']),
|
503
503
|
comments: pin.comments,
|
504
|
-
closure: pin.closure
|
504
|
+
closure: pin.closure,
|
505
|
+
source: :solargraph
|
505
506
|
)
|
506
507
|
end)
|
507
508
|
end
|
@@ -749,6 +750,7 @@ module Solargraph
|
|
749
750
|
return change if source.code.length + 1 != change['text'].length
|
750
751
|
diffs = Diff::LCS.diff(source.code, change['text'])
|
751
752
|
return change if diffs.length.zero? || diffs.length > 1 || diffs.first.length > 1
|
753
|
+
# @sg-ignore push this upstream
|
752
754
|
# @type [Diff::LCS::Change]
|
753
755
|
diff = diffs.first.first
|
754
756
|
return change unless diff.adding? && ['.', ':', '(', ',', ' '].include?(diff.element)
|
@@ -83,6 +83,7 @@ module Solargraph
|
|
83
83
|
@fetched = true
|
84
84
|
begin
|
85
85
|
@available ||= begin
|
86
|
+
# @type [Gem::Dependency, nil]
|
86
87
|
tuple = CheckGemVersion.fetcher.search_for_dependency(Gem::Dependency.new('solargraph')).flatten.first
|
87
88
|
if tuple.nil?
|
88
89
|
@error = 'An error occurred fetching the gem data'
|
data/lib/solargraph/location.rb
CHANGED
@@ -30,6 +30,14 @@ module Solargraph
|
|
30
30
|
range.contain?(location.range.start) && range.contain?(location.range.ending) && filename == location.filename
|
31
31
|
end
|
32
32
|
|
33
|
+
def inspect
|
34
|
+
"<#{self.class.name}: filename=#{filename}, range=#{range.inspect}>"
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_s
|
38
|
+
inspect
|
39
|
+
end
|
40
|
+
|
33
41
|
# @return [Hash]
|
34
42
|
def to_hash
|
35
43
|
{
|
data/lib/solargraph/logging.rb
CHANGED
@@ -13,6 +13,8 @@ module Solargraph
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def on_comment *args
|
16
|
+
# @sg-ignore
|
17
|
+
# @type [Array(Symbol, String, Array([Integer, nil], [Integer, nil]))]
|
16
18
|
result = super
|
17
19
|
if @buffer_lines[result[2][0]][0..result[2][1]].strip =~ /^#/
|
18
20
|
chomped = result[1].chomp
|
@@ -24,24 +26,28 @@ module Solargraph
|
|
24
26
|
result
|
25
27
|
end
|
26
28
|
|
29
|
+
# @param result [Array(Symbol, String, Array([Integer, nil], [Integer, nil]))]
|
30
|
+
# @return [void]
|
31
|
+
def create_snippet(result)
|
32
|
+
chomped = result[1].chomp
|
33
|
+
@comments[result[2][0]] = Snippet.new(Range.from_to(result[2][0] || 0, result[2][1] || 0, result[2][0] || 0, (result[2][1] || 0) + chomped.length), chomped)
|
34
|
+
end
|
35
|
+
|
27
36
|
def on_embdoc_beg *args
|
28
37
|
result = super
|
29
|
-
|
30
|
-
@comments[result[2][0]] = Snippet.new(Range.from_to(result[2][0], result[2][1], result[2][0], result[2][1] + chomped.length), chomped)
|
38
|
+
create_snippet(result)
|
31
39
|
result
|
32
40
|
end
|
33
41
|
|
34
42
|
def on_embdoc *args
|
35
43
|
result = super
|
36
|
-
|
37
|
-
@comments[result[2][0]] = Snippet.new(Range.from_to(result[2][0], result[2][1], result[2][0], result[2][1] + chomped.length), chomped)
|
44
|
+
create_snippet(result)
|
38
45
|
result
|
39
46
|
end
|
40
47
|
|
41
48
|
def on_embdoc_end *args
|
42
49
|
result = super
|
43
|
-
|
44
|
-
@comments[result[2][0]] = Snippet.new(Range.from_to(result[2][0], result[2][1], result[2][0], result[2][1] + chomped.length), chomped)
|
50
|
+
create_snippet(result)
|
45
51
|
result
|
46
52
|
end
|
47
53
|
|