solargraph 0.56.0 → 0.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/linting.yml +125 -0
- data/.github/workflows/plugins.yml +148 -6
- data/.github/workflows/rspec.yml +39 -4
- data/.github/workflows/typecheck.yml +5 -2
- data/.gitignore +5 -0
- data/.overcommit.yml +72 -0
- data/.rspec +1 -0
- data/.rubocop.yml +66 -0
- data/.rubocop_todo.yml +2627 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +56 -1
- data/README.md +8 -4
- data/Rakefile +125 -13
- data/lib/solargraph/api_map/cache.rb +3 -2
- data/lib/solargraph/api_map/constants.rb +218 -0
- data/lib/solargraph/api_map/index.rb +20 -26
- data/lib/solargraph/api_map/source_to_yard.rb +10 -4
- data/lib/solargraph/api_map/store.rb +126 -18
- data/lib/solargraph/api_map.rb +212 -234
- data/lib/solargraph/bench.rb +1 -0
- data/lib/solargraph/complex_type/type_methods.rb +1 -0
- data/lib/solargraph/complex_type/unique_type.rb +7 -7
- data/lib/solargraph/complex_type.rb +5 -1
- 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 +61 -0
- data/lib/solargraph/convention/data_definition/data_definition_node.rb +91 -0
- data/lib/solargraph/convention/data_definition.rb +105 -0
- data/lib/solargraph/convention/gemspec.rb +3 -2
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +2 -1
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +4 -2
- data/lib/solargraph/convention/struct_definition.rb +87 -24
- data/lib/solargraph/convention.rb +32 -2
- data/lib/solargraph/diagnostics/rubocop.rb +6 -1
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +1 -1
- data/lib/solargraph/doc_map.rb +48 -17
- data/lib/solargraph/environ.rb +9 -2
- data/lib/solargraph/gem_pins.rb +17 -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 +2 -1
- 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 +16 -2
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +1 -0
- data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +2 -0
- data/lib/solargraph/language_server/progress.rb +8 -0
- data/lib/solargraph/language_server/request.rb +1 -0
- data/lib/solargraph/library.rb +47 -30
- data/lib/solargraph/location.rb +2 -0
- data/lib/solargraph/logging.rb +11 -2
- data/lib/solargraph/page.rb +4 -0
- data/lib/solargraph/parser/comment_ripper.rb +8 -1
- data/lib/solargraph/parser/flow_sensitive_typing.rb +32 -4
- data/lib/solargraph/parser/node_methods.rb +2 -2
- data/lib/solargraph/parser/node_processor/base.rb +10 -5
- data/lib/solargraph/parser/node_processor.rb +24 -8
- data/lib/solargraph/parser/parser_gem/class_methods.rb +1 -1
- 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 +4 -2
- data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +3 -2
- data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +1 -21
- data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +2 -0
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +7 -1
- data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +0 -22
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +35 -14
- data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
- data/lib/solargraph/parser/region.rb +3 -0
- data/lib/solargraph/parser/snippet.rb +2 -0
- data/lib/solargraph/pin/base.rb +65 -8
- data/lib/solargraph/pin/base_variable.rb +1 -2
- data/lib/solargraph/pin/callable.rb +9 -0
- data/lib/solargraph/pin/closure.rb +2 -0
- data/lib/solargraph/pin/common.rb +6 -2
- data/lib/solargraph/pin/constant.rb +2 -0
- data/lib/solargraph/pin/delegated_method.rb +1 -0
- data/lib/solargraph/pin/local_variable.rb +4 -1
- data/lib/solargraph/pin/method.rb +12 -7
- data/lib/solargraph/pin/method_alias.rb +3 -0
- data/lib/solargraph/pin/parameter.rb +18 -8
- data/lib/solargraph/pin/proxy_type.rb +1 -0
- data/lib/solargraph/pin/reference/override.rb +15 -1
- data/lib/solargraph/pin/reference/superclass.rb +5 -0
- data/lib/solargraph/pin/reference.rb +26 -0
- data/lib/solargraph/pin/search.rb +3 -1
- data/lib/solargraph/pin/signature.rb +2 -0
- data/lib/solargraph/pin/symbol.rb +5 -0
- data/lib/solargraph/pin_cache.rb +64 -4
- data/lib/solargraph/position.rb +2 -0
- data/lib/solargraph/range.rb +1 -0
- data/lib/solargraph/rbs_map/conversions.rb +47 -18
- data/lib/solargraph/rbs_map/core_map.rb +3 -0
- data/lib/solargraph/rbs_map.rb +15 -2
- data/lib/solargraph/shell.rb +3 -0
- data/lib/solargraph/source/chain/link.rb +10 -1
- data/lib/solargraph/source/chain.rb +9 -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 +5 -2
- data/lib/solargraph/source_map/clip.rb +1 -1
- data/lib/solargraph/source_map/data.rb +4 -0
- data/lib/solargraph/source_map/mapper.rb +4 -2
- data/lib/solargraph/source_map.rb +21 -14
- data/lib/solargraph/type_checker/param_def.rb +2 -0
- data/lib/solargraph/type_checker/rules.rb +8 -0
- data/lib/solargraph/type_checker.rb +173 -120
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +1 -3
- data/lib/solargraph/workspace/require_paths.rb +98 -0
- data/lib/solargraph/workspace.rb +24 -48
- data/lib/solargraph/yard_map/helpers.rb +29 -1
- data/lib/solargraph/yard_map/mapper/to_constant.rb +5 -5
- data/lib/solargraph/yard_map/mapper/to_method.rb +3 -8
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +7 -7
- data/lib/solargraph/yardoc.rb +18 -3
- data/lib/solargraph.rb +15 -0
- data/rbs/fills/tuple.rbs +2 -3
- data/sig/shims/parser/3.2.0.1/builders/default.rbs +195 -0
- data/sig/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
- data/sig/shims/thor/1.2.0.1/manifest.yaml +7 -0
- data/sig/shims/thor/1.2.0.1/thor.rbs +17 -0
- data/solargraph.gemspec +14 -4
- metadata +128 -11
- data/lib/.rubocop.yml +0 -22
@@ -8,8 +8,9 @@ module Solargraph
|
|
8
8
|
|
9
9
|
module NodeProcessors
|
10
10
|
class StructNode < Parser::NodeProcessor::Base
|
11
|
+
# @return [Boolean] continue processing the next processor of the same node.
|
11
12
|
def process
|
12
|
-
return if struct_definition_node.nil?
|
13
|
+
return true if struct_definition_node.nil?
|
13
14
|
|
14
15
|
loc = get_node_location(node)
|
15
16
|
nspin = Solargraph::Pin::Namespace.new(
|
@@ -17,9 +18,10 @@ module Solargraph
|
|
17
18
|
location: loc,
|
18
19
|
closure: region.closure,
|
19
20
|
name: struct_definition_node.class_name,
|
20
|
-
|
21
|
+
docstring: docstring,
|
21
22
|
visibility: :public,
|
22
|
-
gates: region.closure.gates.freeze
|
23
|
+
gates: region.closure.gates.freeze,
|
24
|
+
source: :struct_definition
|
23
25
|
)
|
24
26
|
pins.push nspin
|
25
27
|
|
@@ -31,7 +33,8 @@ module Solargraph
|
|
31
33
|
location: get_node_location(node),
|
32
34
|
closure: nspin,
|
33
35
|
visibility: :private,
|
34
|
-
|
36
|
+
docstring: docstring,
|
37
|
+
source: :struct_definition
|
35
38
|
)
|
36
39
|
|
37
40
|
pins.push initialize_method_pin
|
@@ -42,7 +45,8 @@ module Solargraph
|
|
42
45
|
name: attribute_name,
|
43
46
|
decl: struct_definition_node.keyword_init? ? :kwarg : :arg,
|
44
47
|
location: get_node_location(attribute_node),
|
45
|
-
closure: initialize_method_pin
|
48
|
+
closure: initialize_method_pin,
|
49
|
+
source: :struct_definition
|
46
50
|
)
|
47
51
|
)
|
48
52
|
end
|
@@ -50,49 +54,108 @@ module Solargraph
|
|
50
54
|
# define attribute accessors and instance variables
|
51
55
|
struct_definition_node.attributes.each do |attribute_node, attribute_name|
|
52
56
|
[attribute_name, "#{attribute_name}="].each do |name|
|
57
|
+
docs = docstring.tags.find { |t| t.tag_name == 'param' && t.name == attribute_name }
|
58
|
+
|
59
|
+
attribute_type = ComplexType.parse(tag_string(docs))
|
60
|
+
return_type_comment = attribute_comment(docs, false)
|
61
|
+
param_comment = attribute_comment(docs, true)
|
62
|
+
|
53
63
|
method_pin = Pin::Method.new(
|
54
64
|
name: name,
|
55
65
|
parameters: [],
|
56
66
|
scope: :instance,
|
57
67
|
location: get_node_location(attribute_node),
|
58
68
|
closure: nspin,
|
59
|
-
|
60
|
-
|
69
|
+
docstring: YARD::Docstring.new(return_type_comment),
|
70
|
+
# even assignments return the value
|
71
|
+
comments: return_type_comment,
|
72
|
+
return_type: attribute_type,
|
73
|
+
visibility: :public,
|
74
|
+
source: :struct_definition
|
61
75
|
)
|
62
76
|
|
63
|
-
|
77
|
+
if name.end_with?('=')
|
78
|
+
method_pin.parameters << Pin::Parameter.new(
|
79
|
+
name: attribute_name,
|
80
|
+
location: get_node_location(attribute_node),
|
81
|
+
closure: method_pin,
|
82
|
+
return_type: attribute_type,
|
83
|
+
comments: param_comment,
|
84
|
+
source: :struct_definition
|
85
|
+
)
|
64
86
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
87
|
+
pins.push Pin::InstanceVariable.new(name: "@#{attribute_name}",
|
88
|
+
closure: method_pin,
|
89
|
+
location: get_node_location(attribute_node),
|
90
|
+
return_type: attribute_type,
|
91
|
+
comments: "@type [#{attribute_type.rooted_tags}]",
|
92
|
+
source: :struct_definition)
|
93
|
+
end
|
94
|
+
|
95
|
+
pins.push method_pin
|
70
96
|
end
|
71
97
|
end
|
72
98
|
|
73
99
|
process_children region.update(closure: nspin, visibility: :public)
|
100
|
+
false
|
74
101
|
end
|
75
102
|
|
76
103
|
private
|
77
104
|
|
78
|
-
# @return [StructDefintionNode, nil]
|
105
|
+
# @return [StructDefintionNode, StructAssignmentNode, nil]
|
79
106
|
def struct_definition_node
|
80
|
-
@struct_definition_node ||= if StructDefintionNode.
|
107
|
+
@struct_definition_node ||= if StructDefintionNode.match?(node)
|
81
108
|
StructDefintionNode.new(node)
|
82
|
-
elsif StructAssignmentNode.
|
109
|
+
elsif StructAssignmentNode.match?(node)
|
83
110
|
StructAssignmentNode.new(node)
|
84
111
|
end
|
85
112
|
end
|
86
113
|
|
87
|
-
#
|
88
|
-
# @return [
|
89
|
-
def
|
90
|
-
|
91
|
-
|
114
|
+
# Gets/generates the relevant docstring for this struct & it's attributes
|
115
|
+
# @return [YARD::Docstring]
|
116
|
+
def docstring
|
117
|
+
@docstring ||= parse_comments
|
118
|
+
end
|
119
|
+
|
120
|
+
# Parses any relevant comments for a struct int a yard docstring
|
121
|
+
# @return [YARD::Docstring]
|
122
|
+
def parse_comments
|
123
|
+
struct_comments = comments_for(node) || ''
|
124
|
+
struct_definition_node.attributes.each do |attr_node, attr_name|
|
125
|
+
comment = comments_for(attr_node)
|
126
|
+
next if comment.nil?
|
92
127
|
|
93
|
-
|
94
|
-
|
95
|
-
|
128
|
+
# We should support specific comments for an attribute, and that can be either a @return on an @param
|
129
|
+
# But since we merge into the struct_comments, then we should interpret either as a param
|
130
|
+
comment = "@param #{attr_name}#{comment[7..]}" if comment.start_with?('@return')
|
131
|
+
|
132
|
+
struct_comments += "\n#{comment}"
|
133
|
+
end
|
134
|
+
|
135
|
+
Solargraph::Source.parse_docstring(struct_comments).to_docstring
|
136
|
+
end
|
137
|
+
|
138
|
+
# @param tag [YARD::Tags::Tag, nil] The param tag for this attribute.xtract_
|
139
|
+
#
|
140
|
+
# @return [String]
|
141
|
+
def tag_string(tag)
|
142
|
+
tag&.types&.join(',') || 'undefined'
|
143
|
+
end
|
144
|
+
|
145
|
+
# @param tag [YARD::Tags::Tag, nil] The param tag for this attribute. If nil, this method is a no-op
|
146
|
+
# @param for_setter [Boolean] If true, will return a @param tag instead of a @return tag
|
147
|
+
#
|
148
|
+
# @return [String] The formatted comment for the attribute
|
149
|
+
def attribute_comment(tag, for_setter)
|
150
|
+
return "" if tag.nil?
|
151
|
+
|
152
|
+
suffix = "[#{tag_string(tag)}] #{tag.text}"
|
153
|
+
|
154
|
+
if for_setter
|
155
|
+
"@param #{tag.name} #{suffix}"
|
156
|
+
else
|
157
|
+
"@return #{suffix}"
|
158
|
+
end
|
96
159
|
end
|
97
160
|
end
|
98
161
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
3
|
module Solargraph
|
5
4
|
# Conventions provide a way to modify an ApiMap based on expectations about
|
6
5
|
# one of its sources.
|
@@ -11,6 +10,8 @@ module Solargraph
|
|
11
10
|
autoload :Gemspec, 'solargraph/convention/gemspec'
|
12
11
|
autoload :Rakefile, 'solargraph/convention/rakefile'
|
13
12
|
autoload :StructDefinition, 'solargraph/convention/struct_definition'
|
13
|
+
autoload :DataDefinition, 'solargraph/convention/data_definition'
|
14
|
+
autoload :ActiveSupportConcern, 'solargraph/convention/active_support_concern'
|
14
15
|
|
15
16
|
# @type [Set<Convention::Base>]
|
16
17
|
@@conventions = Set.new
|
@@ -21,6 +22,12 @@ module Solargraph
|
|
21
22
|
@@conventions.add convention.new
|
22
23
|
end
|
23
24
|
|
25
|
+
# @param convention [Class<Convention::Base>]
|
26
|
+
# @return [void]
|
27
|
+
def self.unregister convention
|
28
|
+
@@conventions.delete_if { |c| c.is_a?(convention) }
|
29
|
+
end
|
30
|
+
|
24
31
|
# @param source_map [SourceMap]
|
25
32
|
# @return [Environ]
|
26
33
|
def self.for_local(source_map)
|
@@ -31,7 +38,7 @@ module Solargraph
|
|
31
38
|
result
|
32
39
|
end
|
33
40
|
|
34
|
-
# @param
|
41
|
+
# @param doc_map [DocMap]
|
35
42
|
# @return [Environ]
|
36
43
|
def self.for_global(doc_map)
|
37
44
|
result = Environ.new
|
@@ -41,8 +48,31 @@ module Solargraph
|
|
41
48
|
result
|
42
49
|
end
|
43
50
|
|
51
|
+
# Provides any additional method pins based on the described object.
|
52
|
+
#
|
53
|
+
# @param api_map [ApiMap]
|
54
|
+
# @param rooted_tag [String] A fully qualified namespace, with
|
55
|
+
# generic parameter values if applicable
|
56
|
+
# @param scope [Symbol] :class or :instance
|
57
|
+
# @param visibility [Array<Symbol>] :public, :protected, and/or :private
|
58
|
+
# @param deep [Boolean]
|
59
|
+
# @param skip [Set<String>]
|
60
|
+
# @param no_core [Boolean] Skip core classes if true
|
61
|
+
#
|
62
|
+
# @return [Environ]
|
63
|
+
def self.for_object api_map, rooted_tag, scope, visibility,
|
64
|
+
deep, skip, no_core
|
65
|
+
result = Environ.new
|
66
|
+
@@conventions.each do |conv|
|
67
|
+
result.merge conv.object(api_map, rooted_tag, scope, visibility,
|
68
|
+
deep, skip, no_core)
|
69
|
+
end
|
70
|
+
result
|
71
|
+
end
|
72
|
+
|
44
73
|
register Gemfile
|
45
74
|
register Gemspec
|
46
75
|
register Rakefile
|
76
|
+
register ActiveSupportConcern
|
47
77
|
end
|
48
78
|
end
|
@@ -28,7 +28,12 @@ module Solargraph
|
|
28
28
|
options, paths = generate_options(source.filename, source.code)
|
29
29
|
store = RuboCop::ConfigStore.new
|
30
30
|
runner = RuboCop::Runner.new(options, store)
|
31
|
-
|
31
|
+
# Ensure only one instance of RuboCop::Runner is running at
|
32
|
+
# a time - it uses 'chdir' to read config files with ERB,
|
33
|
+
# which can conflict with other chdirs.
|
34
|
+
result = Solargraph::CHDIR_MUTEX.synchronize do
|
35
|
+
redirect_stdout{ runner.run(paths) }
|
36
|
+
end
|
32
37
|
|
33
38
|
return [] if result.empty?
|
34
39
|
|
@@ -15,10 +15,10 @@ module Solargraph
|
|
15
15
|
# @return [void]
|
16
16
|
def require_rubocop(version = nil)
|
17
17
|
begin
|
18
|
+
# @type [String]
|
18
19
|
gem_path = Gem::Specification.find_by_name('rubocop', version).full_gem_path
|
19
20
|
gem_lib_path = File.join(gem_path, 'lib')
|
20
21
|
$LOAD_PATH.unshift(gem_lib_path) unless $LOAD_PATH.include?(gem_lib_path)
|
21
|
-
# @todo Gem::MissingSpecVersionError is undocumented for some reason
|
22
22
|
# @sg-ignore
|
23
23
|
rescue Gem::MissingSpecVersionError => e
|
24
24
|
raise InvalidRubocopVersionError,
|
data/lib/solargraph/doc_map.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'pathname'
|
4
4
|
require 'benchmark'
|
5
|
+
require 'open3'
|
5
6
|
|
6
7
|
module Solargraph
|
7
8
|
# A collection of pins generated from required gems.
|
@@ -21,8 +22,9 @@ module Solargraph
|
|
21
22
|
|
22
23
|
# @return [Array<Gem::Specification>]
|
23
24
|
def uncached_gemspecs
|
24
|
-
(
|
25
|
-
|
25
|
+
uncached_yard_gemspecs.concat(uncached_rbs_collection_gemspecs)
|
26
|
+
.sort
|
27
|
+
.uniq { |gemspec| "#{gemspec.name}:#{gemspec.version}" }
|
26
28
|
end
|
27
29
|
|
28
30
|
# @return [Array<Gem::Specification>]
|
@@ -31,8 +33,10 @@ module Solargraph
|
|
31
33
|
# @return [Array<Gem::Specification>]
|
32
34
|
attr_reader :uncached_rbs_collection_gemspecs
|
33
35
|
|
36
|
+
# @return [String, nil]
|
34
37
|
attr_reader :rbs_collection_path
|
35
38
|
|
39
|
+
# @return [String, nil]
|
36
40
|
attr_reader :rbs_collection_config_path
|
37
41
|
|
38
42
|
# @return [Workspace, nil]
|
@@ -51,10 +55,13 @@ module Solargraph
|
|
51
55
|
@rbs_collection_path = workspace&.rbs_collection_path
|
52
56
|
@rbs_collection_config_path = workspace&.rbs_collection_config_path
|
53
57
|
@environ = Convention.for_global(self)
|
58
|
+
@requires.concat @environ.requires if @environ
|
54
59
|
load_serialized_gem_pins
|
55
60
|
pins.concat @environ.pins
|
56
61
|
end
|
57
62
|
|
63
|
+
# @param out [IO]
|
64
|
+
# @return [void]
|
58
65
|
def cache_all!(out)
|
59
66
|
# if we log at debug level:
|
60
67
|
if logger.info?
|
@@ -72,12 +79,18 @@ module Solargraph
|
|
72
79
|
@uncached_yard_gemspecs = []
|
73
80
|
end
|
74
81
|
|
82
|
+
# @param gemspec [Gem::Specification]
|
83
|
+
# @param out [IO]
|
84
|
+
# @return [void]
|
75
85
|
def cache_yard_pins(gemspec, out)
|
76
|
-
pins = GemPins.build_yard_pins(gemspec)
|
86
|
+
pins = GemPins.build_yard_pins(yard_plugins, gemspec)
|
77
87
|
PinCache.serialize_yard_gem(gemspec, pins)
|
78
88
|
logger.info { "Cached #{pins.length} YARD pins for gem #{gemspec.name}:#{gemspec.version}" } unless pins.empty?
|
79
89
|
end
|
80
90
|
|
91
|
+
# @param gemspec [Gem::Specification]
|
92
|
+
# @param out [IO]
|
93
|
+
# @return [void]
|
81
94
|
def cache_rbs_collection_pins(gemspec, out)
|
82
95
|
rbs_map = RbsMap.from_gemspec(gemspec, rbs_collection_path, rbs_collection_config_path)
|
83
96
|
pins = rbs_map.pins
|
@@ -89,6 +102,9 @@ module Solargraph
|
|
89
102
|
end
|
90
103
|
|
91
104
|
# @param gemspec [Gem::Specification]
|
105
|
+
# @param rebuild [Boolean] whether to rebuild the pins even if they are cached
|
106
|
+
# @param out [IO, nil] output stream for logging
|
107
|
+
# @return [void]
|
92
108
|
def cache(gemspec, rebuild: false, out: nil)
|
93
109
|
build_yard = uncached_yard_gemspecs.include?(gemspec) || rebuild
|
94
110
|
build_rbs_collection = uncached_rbs_collection_gemspecs.include?(gemspec) || rebuild
|
@@ -112,30 +128,42 @@ module Solargraph
|
|
112
128
|
@unresolved_requires ||= required_gems_map.select { |_, gemspecs| gemspecs.nil? }.keys
|
113
129
|
end
|
114
130
|
|
131
|
+
# @return [Hash{Array(String, String) => Array<Gem::Specification>}] Indexed by gemspec name and version
|
115
132
|
def self.all_yard_gems_in_memory
|
116
133
|
@yard_gems_in_memory ||= {}
|
117
134
|
end
|
118
135
|
|
136
|
+
# @return [Hash{String => Hash{Array(String, String) => Array<Pin::Base>}}] stored by RBS collection path
|
119
137
|
def self.all_rbs_collection_gems_in_memory
|
120
138
|
@rbs_collection_gems_in_memory ||= {}
|
121
139
|
end
|
122
140
|
|
141
|
+
# @return [Hash{Array(String, String) => Array<Pin::Base>}] Indexed by gemspec name and version
|
123
142
|
def yard_pins_in_memory
|
124
143
|
self.class.all_yard_gems_in_memory
|
125
144
|
end
|
126
145
|
|
146
|
+
# @return [Hash{Array(String, String) => Array<Pin::Base>}] Indexed by gemspec name and version
|
127
147
|
def rbs_collection_pins_in_memory
|
128
148
|
self.class.all_rbs_collection_gems_in_memory[rbs_collection_path] ||= {}
|
129
149
|
end
|
130
150
|
|
151
|
+
# @return [Hash{Array(String, String) => Array<Pin::Base>}] Indexed by gemspec name and version
|
131
152
|
def self.all_combined_pins_in_memory
|
132
153
|
@combined_pins_in_memory ||= {}
|
133
154
|
end
|
134
155
|
|
156
|
+
# @todo this should also include an index by the hash of the RBS collection
|
157
|
+
# @return [Hash{Array(String, String) => Array<Pin::Base>}] Indexed by gemspec name and version
|
135
158
|
def combined_pins_in_memory
|
136
159
|
self.class.all_combined_pins_in_memory
|
137
160
|
end
|
138
161
|
|
162
|
+
# @return [Array<String>]
|
163
|
+
def yard_plugins
|
164
|
+
@environ.yard_plugins
|
165
|
+
end
|
166
|
+
|
139
167
|
# @return [Set<Gem::Specification>]
|
140
168
|
def dependencies
|
141
169
|
@dependencies ||= (gemspecs.flat_map { |spec| fetch_dependencies(spec) } - gemspecs).to_set
|
@@ -149,7 +177,11 @@ module Solargraph
|
|
149
177
|
@uncached_yard_gemspecs = []
|
150
178
|
@uncached_rbs_collection_gemspecs = []
|
151
179
|
with_gemspecs, without_gemspecs = required_gems_map.partition { |_, v| v }
|
180
|
+
# @sg-ignore Wrong argument type for Hash.[]: arg_0 expected _ToHash<Array(String, Array<Gem::Specification>), undefined>, received Array<Array(String, Array<Gem::Specification>)>
|
181
|
+
# @type [Array<String>]
|
152
182
|
paths = Hash[without_gemspecs].keys
|
183
|
+
# @sg-ignore Wrong argument type for Hash.[]: arg_0 expected _ToHash<Array(String, Array<Gem::Specification>), undefined>, received Array<Array(String, Array<Gem::Specification>)>
|
184
|
+
# @type [Array<Gem::Specification>]
|
153
185
|
gemspecs = Hash[with_gemspecs].values.flatten.compact + dependencies.to_a
|
154
186
|
|
155
187
|
paths.each do |path|
|
@@ -258,6 +290,8 @@ module Solargraph
|
|
258
290
|
end
|
259
291
|
end
|
260
292
|
|
293
|
+
# @param gemspec [Gem::Specification]
|
294
|
+
# @param rbs_version_cache_key [String]
|
261
295
|
# @return [Array<Pin::Base>, nil]
|
262
296
|
def deserialize_rbs_collection_cache gemspec, rbs_version_cache_key
|
263
297
|
return if rbs_collection_pins_in_memory.key?([gemspec, rbs_version_cache_key])
|
@@ -273,22 +307,13 @@ module Solargraph
|
|
273
307
|
end
|
274
308
|
end
|
275
309
|
|
276
|
-
# @param gemspec [Gem::Specification]
|
277
|
-
# @return [Boolean]
|
278
|
-
def try_gem_in_memory gemspec
|
279
|
-
gempins = DocMap.gems_in_memory[gemspec]
|
280
|
-
return false unless gempins
|
281
|
-
Solargraph.logger.debug "Found #{gemspec.name} #{gemspec.version} in memory"
|
282
|
-
@pins.concat gempins
|
283
|
-
true
|
284
|
-
end
|
285
|
-
|
286
310
|
# @param path [String]
|
287
311
|
# @return [::Array<Gem::Specification>, nil]
|
288
312
|
def resolve_path_to_gemspecs path
|
289
313
|
return nil if path.empty?
|
290
314
|
return gemspecs_required_from_bundler if path == 'bundler/require'
|
291
315
|
|
316
|
+
# @type [Gem::Specification, nil]
|
292
317
|
gemspec = Gem::Specification.find_by_path(path)
|
293
318
|
if gemspec.nil?
|
294
319
|
gem_name_guess = path.split('/').first
|
@@ -312,10 +337,12 @@ module Solargraph
|
|
312
337
|
# @param gemspec [Gem::Specification]
|
313
338
|
# @return [Gem::Specification]
|
314
339
|
def gemspec_or_preference gemspec
|
340
|
+
# :nocov: dormant feature
|
315
341
|
return gemspec unless preference_map.key?(gemspec.name)
|
316
342
|
return gemspec if gemspec.version == preference_map[gemspec.name].version
|
317
343
|
|
318
|
-
change_gemspec_version gemspec, preference_map[
|
344
|
+
change_gemspec_version gemspec, preference_map[gemspec.name].version
|
345
|
+
# :nocov:
|
319
346
|
end
|
320
347
|
|
321
348
|
# @param gemspec [Gem::Specification]
|
@@ -354,8 +381,12 @@ module Solargraph
|
|
354
381
|
self.class.inspect
|
355
382
|
end
|
356
383
|
|
384
|
+
# @return [Array<Gem::Specification>]
|
357
385
|
def gemspecs_required_from_bundler
|
358
|
-
|
386
|
+
# @todo Handle projects with custom Bundler/Gemfile setups
|
387
|
+
return unless workspace.gemfile?
|
388
|
+
|
389
|
+
if workspace.gemfile? && Bundler.definition&.lockfile&.to_s&.start_with?(workspace.directory)
|
359
390
|
# Find only the gems bundler is now using
|
360
391
|
Bundler.definition.locked_gems.specs.flat_map do |lazy_spec|
|
361
392
|
logger.info "Handling #{lazy_spec.name}:#{lazy_spec.version}"
|
@@ -373,6 +404,7 @@ module Solargraph
|
|
373
404
|
end
|
374
405
|
end
|
375
406
|
|
407
|
+
# @return [Array<Gem::Specification>]
|
376
408
|
def gemspecs_required_from_external_bundle
|
377
409
|
logger.info 'Fetching gemspecs required from external bundle'
|
378
410
|
return [] unless workspace&.directory
|
@@ -396,8 +428,7 @@ module Solargraph
|
|
396
428
|
next specs
|
397
429
|
end.compact
|
398
430
|
else
|
399
|
-
Solargraph.logger.warn e
|
400
|
-
raise BundleNotFoundError, "Failed to load gems from bundle at #{workspace&.directory}"
|
431
|
+
Solargraph.logger.warn "Failed to load gems from bundle at #{workspace&.directory}: #{e}"
|
401
432
|
end
|
402
433
|
end
|
403
434
|
end
|
data/lib/solargraph/environ.rb
CHANGED
@@ -13,16 +13,21 @@ module Solargraph
|
|
13
13
|
# @return [Array<String>]
|
14
14
|
attr_reader :domains
|
15
15
|
|
16
|
-
# @return [Array<Pin::
|
16
|
+
# @return [Array<Pin::Base>]
|
17
17
|
attr_reader :pins
|
18
18
|
|
19
|
+
# @return [Array<String>]
|
20
|
+
attr_reader :yard_plugins
|
21
|
+
|
19
22
|
# @param requires [Array<String>]
|
20
23
|
# @param domains [Array<String>]
|
21
24
|
# @param pins [Array<Pin::Base>]
|
22
|
-
|
25
|
+
# @param yard_plugins[Array<String>]
|
26
|
+
def initialize requires: [], domains: [], pins: [], yard_plugins: []
|
23
27
|
@requires = requires
|
24
28
|
@domains = domains
|
25
29
|
@pins = pins
|
30
|
+
@yard_plugins = yard_plugins
|
26
31
|
end
|
27
32
|
|
28
33
|
# @return [self]
|
@@ -30,6 +35,7 @@ module Solargraph
|
|
30
35
|
domains.clear
|
31
36
|
requires.clear
|
32
37
|
pins.clear
|
38
|
+
yard_plugins.clear
|
33
39
|
self
|
34
40
|
end
|
35
41
|
|
@@ -39,6 +45,7 @@ module Solargraph
|
|
39
45
|
domains.concat other.domains
|
40
46
|
requires.concat other.requires
|
41
47
|
pins.concat other.pins
|
48
|
+
yard_plugins.concat other.yard_plugins
|
42
49
|
self
|
43
50
|
end
|
44
51
|
end
|
data/lib/solargraph/gem_pins.rb
CHANGED
@@ -11,17 +11,9 @@ module Solargraph
|
|
11
11
|
include Logging
|
12
12
|
end
|
13
13
|
|
14
|
-
# @param gemspec [Gem::Specification]
|
15
|
-
# @return [Array<Pin::Base>]
|
16
|
-
def self.build_yard_pins(gemspec)
|
17
|
-
Yardoc.cache(gemspec) unless Yardoc.cached?(gemspec)
|
18
|
-
yardoc = Yardoc.load!(gemspec)
|
19
|
-
YardMap::Mapper.new(yardoc, gemspec).map
|
20
|
-
end
|
21
|
-
|
22
14
|
# @param pins [Array<Pin::Base>]
|
15
|
+
# @return [Array<Pin::Base>]
|
23
16
|
def self.combine_method_pins_by_path(pins)
|
24
|
-
# bad_pins = pins.select { |pin| pin.is_a?(Pin::Method) && pin.path == 'StringIO.open' && pin.source == :rbs }; raise "wtf: #{bad_pins}" if bad_pins.length > 1
|
25
17
|
method_pins, alias_pins = pins.partition { |pin| pin.class == Pin::Method }
|
26
18
|
by_path = method_pins.group_by(&:path)
|
27
19
|
by_path.transform_values! do |pins|
|
@@ -30,8 +22,12 @@ module Solargraph
|
|
30
22
|
by_path.values + alias_pins
|
31
23
|
end
|
32
24
|
|
25
|
+
# @param pins [Array<Pin::Method>]
|
26
|
+
# @return [Pin::Method, nil]
|
33
27
|
def self.combine_method_pins(*pins)
|
34
|
-
|
28
|
+
# @type [Pin::Method, nil]
|
29
|
+
combined_pin = nil
|
30
|
+
out = pins.reduce(combined_pin) do |memo, pin|
|
35
31
|
next pin if memo.nil?
|
36
32
|
if memo == pin && memo.source != :combined
|
37
33
|
# @todo we should track down situations where we are handled
|
@@ -45,8 +41,18 @@ module Solargraph
|
|
45
41
|
out
|
46
42
|
end
|
47
43
|
|
44
|
+
# @param yard_plugins [Array<String>] The names of YARD plugins to use.
|
45
|
+
# @param gemspec [Gem::Specification]
|
46
|
+
# @return [Array<Pin::Base>]
|
47
|
+
def self.build_yard_pins(yard_plugins, gemspec)
|
48
|
+
Yardoc.cache(yard_plugins, gemspec) unless Yardoc.cached?(gemspec)
|
49
|
+
yardoc = Yardoc.load!(gemspec)
|
50
|
+
YardMap::Mapper.new(yardoc, gemspec).map
|
51
|
+
end
|
52
|
+
|
48
53
|
# @param yard_pins [Array<Pin::Base>]
|
49
|
-
# @param
|
54
|
+
# @param rbs_pins [Array<Pin::Base>]
|
55
|
+
#
|
50
56
|
# @return [Array<Pin::Base>]
|
51
57
|
def self.combine(yard_pins, rbs_pins)
|
52
58
|
in_yard = Set.new
|
@@ -95,6 +95,7 @@ module Solargraph
|
|
95
95
|
nil
|
96
96
|
end
|
97
97
|
|
98
|
+
# @return [Hash{String => undefined}]
|
98
99
|
def options
|
99
100
|
@options ||= {}.freeze
|
100
101
|
end
|
@@ -118,6 +119,7 @@ module Solargraph
|
|
118
119
|
end
|
119
120
|
|
120
121
|
# @param library [Solargraph::Library]
|
122
|
+
# @param progress [Solargraph::LanguageServer::Progress, nil]
|
121
123
|
# @return [void]
|
122
124
|
def update progress
|
123
125
|
progress&.send(self)
|
@@ -72,10 +72,12 @@ module Solargraph
|
|
72
72
|
|
73
73
|
private
|
74
74
|
|
75
|
+
# @return [Hash, nil]
|
75
76
|
def next_message
|
76
77
|
cancel_message || next_priority
|
77
78
|
end
|
78
79
|
|
80
|
+
# @return [Hash, nil]
|
79
81
|
def cancel_message
|
80
82
|
# Handle cancellations first
|
81
83
|
idx = messages.find_index { |msg| msg['method'] == '$/cancelRequest' }
|
@@ -86,6 +88,7 @@ module Solargraph
|
|
86
88
|
msg
|
87
89
|
end
|
88
90
|
|
91
|
+
# @return [Hash, nil]
|
89
92
|
def next_priority
|
90
93
|
# Prioritize updates and version-dependent messages for performance
|
91
94
|
idx = messages.find_index do |msg|
|
@@ -299,6 +299,7 @@ module Solargraph
|
|
299
299
|
end
|
300
300
|
end
|
301
301
|
|
302
|
+
# @return [String]
|
302
303
|
def command_path
|
303
304
|
options['commandPath'] || 'solargraph'
|
304
305
|
end
|
@@ -716,7 +717,7 @@ module Solargraph
|
|
716
717
|
# A hash of client requests by ID. The host uses this to keep track of
|
717
718
|
# pending responses.
|
718
719
|
#
|
719
|
-
# @return [Hash{Integer => Solargraph::LanguageServer::
|
720
|
+
# @return [Hash{Integer => Solargraph::LanguageServer::Request}]
|
720
721
|
def requests
|
721
722
|
@requests ||= {}
|
722
723
|
end
|
@@ -16,7 +16,7 @@ module Solargraph
|
|
16
16
|
# @return [String]
|
17
17
|
attr_reader :method
|
18
18
|
|
19
|
-
# @return [Hash{String =>
|
19
|
+
# @return [Hash{String => undefined}]
|
20
20
|
attr_reader :params
|
21
21
|
|
22
22
|
# @return [Hash, Array, nil]
|
@@ -79,6 +79,7 @@ module Solargraph
|
|
79
79
|
|
80
80
|
private
|
81
81
|
|
82
|
+
# @return [void]
|
82
83
|
def accept_or_cancel
|
83
84
|
if host.cancel?(id)
|
84
85
|
# https://microsoft.github.io/language-server-protocol/specifications/specification-current/#cancelRequest
|
@@ -83,7 +83,7 @@ module Solargraph
|
|
83
83
|
@fetched = true
|
84
84
|
begin
|
85
85
|
@available ||= begin
|
86
|
-
# @sg-ignore
|
86
|
+
# @sg-ignore Variable type could not be inferred for tuple
|
87
87
|
# @type [Gem::Dependency, nil]
|
88
88
|
tuple = CheckGemVersion.fetcher.search_for_dependency(Gem::Dependency.new('solargraph')).flatten.first
|
89
89
|
if tuple.nil?
|
@@ -10,6 +10,7 @@ module Solargraph::LanguageServer::Message::TextDocument
|
|
10
10
|
|
11
11
|
private
|
12
12
|
|
13
|
+
# @return [Array<Hash>]
|
13
14
|
def code_location
|
14
15
|
suggestions = host.definitions_at(params['textDocument']['uri'], @line, @column)
|
15
16
|
return nil if suggestions.empty?
|
@@ -21,6 +22,7 @@ module Solargraph::LanguageServer::Message::TextDocument
|
|
21
22
|
end
|
22
23
|
end
|
23
24
|
|
25
|
+
# @return [Array<Hash>]
|
24
26
|
def require_location
|
25
27
|
# @todo Terrible hack
|
26
28
|
lib = host.library_for(params['textDocument']['uri'])
|