solargraph 0.59.0.dev.1 → 0.59.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 +3 -1
- data/.github/workflows/plugins.yml +12 -3
- data/.github/workflows/rspec.yml +9 -54
- data/.github/workflows/typecheck.yml +2 -1
- data/.gitignore +1 -0
- data/.rubocop.yml +38 -6
- data/.rubocop_todo.yml +40 -931
- data/CHANGELOG.md +22 -1
- data/Gemfile +3 -1
- data/Rakefile +25 -23
- data/bin/solargraph +2 -1
- data/lib/solargraph/api_map/constants.rb +0 -1
- data/lib/solargraph/api_map/index.rb +11 -11
- data/lib/solargraph/api_map/source_to_yard.rb +9 -8
- data/lib/solargraph/api_map/store.rb +28 -20
- data/lib/solargraph/api_map.rb +70 -41
- data/lib/solargraph/bench.rb +44 -45
- data/lib/solargraph/complex_type/type_methods.rb +14 -16
- data/lib/solargraph/complex_type/unique_type.rb +56 -47
- data/lib/solargraph/complex_type.rb +70 -62
- data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -61
- data/lib/solargraph/convention/data_definition/data_definition_node.rb +4 -4
- data/lib/solargraph/convention/data_definition.rb +1 -1
- data/lib/solargraph/convention/gemfile.rb +15 -15
- data/lib/solargraph/convention/gemspec.rb +23 -23
- data/lib/solargraph/convention/rakefile.rb +17 -17
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +1 -1
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +3 -3
- data/lib/solargraph/convention/struct_definition.rb +3 -3
- data/lib/solargraph/convention.rb +78 -78
- data/lib/solargraph/converters/dd.rb +19 -17
- data/lib/solargraph/converters/dl.rb +17 -15
- data/lib/solargraph/converters/dt.rb +17 -15
- data/lib/solargraph/converters/misc.rb +3 -1
- data/lib/solargraph/diagnostics/rubocop.rb +10 -10
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +3 -3
- data/lib/solargraph/diagnostics/type_check.rb +10 -10
- data/lib/solargraph/diagnostics/update_errors.rb +37 -41
- data/lib/solargraph/doc_map.rb +370 -132
- data/lib/solargraph/equality.rb +3 -3
- data/lib/solargraph/gem_pins.rb +19 -18
- data/lib/solargraph/language_server/error_codes.rb +20 -20
- data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
- data/lib/solargraph/language_server/host/dispatch.rb +2 -3
- data/lib/solargraph/language_server/host/message_worker.rb +2 -2
- data/lib/solargraph/language_server/host/sources.rb +1 -1
- data/lib/solargraph/language_server/host.rb +24 -21
- data/lib/solargraph/language_server/message/base.rb +97 -97
- data/lib/solargraph/language_server/message/client/register_capability.rb +13 -15
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +58 -60
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +10 -11
- data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -32
- data/lib/solargraph/language_server/message/extended/download_core.rb +20 -19
- data/lib/solargraph/language_server/message/extended/search.rb +20 -20
- data/lib/solargraph/language_server/message/initialize.rb +197 -191
- data/lib/solargraph/language_server/message/text_document/completion.rb +8 -8
- data/lib/solargraph/language_server/message/text_document/definition.rb +41 -34
- data/lib/solargraph/language_server/message/text_document/document_highlight.rb +23 -16
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +29 -21
- data/lib/solargraph/language_server/message/text_document/formatting.rb +6 -6
- data/lib/solargraph/language_server/message/text_document/hover.rb +3 -5
- data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +18 -11
- data/lib/solargraph/language_server/message/text_document/references.rb +23 -16
- data/lib/solargraph/language_server/message/text_document/rename.rb +26 -19
- data/lib/solargraph/language_server/message/text_document/signature_help.rb +2 -2
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +25 -19
- data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +41 -35
- data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +48 -40
- data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +32 -26
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +27 -19
- data/lib/solargraph/language_server/message.rb +94 -94
- data/lib/solargraph/language_server/request.rb +29 -27
- data/lib/solargraph/language_server/transport/data_reader.rb +72 -74
- data/lib/solargraph/language_server/uri_helpers.rb +49 -49
- data/lib/solargraph/library.rb +68 -95
- data/lib/solargraph/location.rb +10 -12
- data/lib/solargraph/logging.rb +4 -6
- data/lib/solargraph/page.rb +92 -92
- data/lib/solargraph/parser/comment_ripper.rb +12 -4
- data/lib/solargraph/parser/flow_sensitive_typing.rb +32 -44
- data/lib/solargraph/parser/node_processor/base.rb +4 -4
- data/lib/solargraph/parser/node_processor.rb +1 -1
- data/lib/solargraph/parser/parser_gem/class_methods.rb +4 -6
- data/lib/solargraph/parser/parser_gem/flawed_builder.rb +19 -19
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +20 -20
- data/lib/solargraph/parser/parser_gem/node_methods.rb +66 -65
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +12 -12
- data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +1 -2
- data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +3 -3
- data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +38 -37
- data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +3 -3
- data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +3 -5
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +118 -112
- data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -29
- data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem.rb +14 -12
- data/lib/solargraph/parser/snippet.rb +2 -0
- data/lib/solargraph/parser.rb +25 -23
- data/lib/solargraph/pin/base.rb +76 -64
- data/lib/solargraph/pin/base_variable.rb +28 -71
- data/lib/solargraph/pin/block.rb +3 -2
- data/lib/solargraph/pin/breakable.rb +2 -0
- data/lib/solargraph/pin/callable.rb +23 -26
- data/lib/solargraph/pin/closure.rb +5 -4
- data/lib/solargraph/pin/common.rb +5 -2
- data/lib/solargraph/pin/compound_statement.rb +3 -3
- data/lib/solargraph/pin/constant.rb +43 -45
- data/lib/solargraph/pin/conversions.rb +9 -4
- data/lib/solargraph/pin/delegated_method.rb +4 -4
- data/lib/solargraph/pin/documenting.rb +3 -2
- data/lib/solargraph/pin/local_variable.rb +4 -4
- data/lib/solargraph/pin/method.rb +74 -70
- data/lib/solargraph/pin/namespace.rb +13 -12
- data/lib/solargraph/pin/parameter.rb +28 -27
- data/lib/solargraph/pin/proxy_type.rb +2 -0
- data/lib/solargraph/pin/reference/type_alias.rb +16 -0
- data/lib/solargraph/pin/reference.rb +18 -0
- data/lib/solargraph/pin/search.rb +2 -2
- data/lib/solargraph/pin/signature.rb +9 -14
- data/lib/solargraph/pin/symbol.rb +1 -0
- data/lib/solargraph/pin/until.rb +1 -3
- data/lib/solargraph/pin/while.rb +1 -3
- data/lib/solargraph/pin_cache.rb +71 -488
- data/lib/solargraph/position.rb +38 -17
- data/lib/solargraph/range.rb +10 -9
- data/lib/solargraph/rbs_map/conversions.rb +327 -221
- data/lib/solargraph/rbs_map/core_fills.rb +91 -84
- data/lib/solargraph/rbs_map/stdlib_map.rb +0 -1
- data/lib/solargraph/rbs_map.rb +5 -15
- data/lib/solargraph/server_methods.rb +16 -16
- data/lib/solargraph/shell.rb +224 -66
- data/lib/solargraph/source/chain/array.rb +39 -37
- data/lib/solargraph/source/chain/call.rb +49 -44
- data/lib/solargraph/source/chain/class_variable.rb +13 -13
- data/lib/solargraph/source/chain/constant.rb +3 -1
- data/lib/solargraph/source/chain/global_variable.rb +13 -13
- data/lib/solargraph/source/chain/hash.rb +8 -6
- data/lib/solargraph/source/chain/if.rb +11 -10
- data/lib/solargraph/source/chain/instance_variable.rb +3 -1
- data/lib/solargraph/source/chain/link.rb +99 -109
- data/lib/solargraph/source/chain/literal.rb +4 -6
- data/lib/solargraph/source/chain/or.rb +2 -4
- data/lib/solargraph/source/chain/q_call.rb +13 -11
- data/lib/solargraph/source/chain/variable.rb +15 -13
- data/lib/solargraph/source/chain/z_super.rb +28 -30
- data/lib/solargraph/source/chain.rb +26 -16
- data/lib/solargraph/source/change.rb +3 -3
- data/lib/solargraph/source/cursor.rb +18 -18
- data/lib/solargraph/source/encoding_fixes.rb +6 -7
- data/lib/solargraph/source/source_chainer.rb +46 -32
- data/lib/solargraph/source/updater.rb +1 -1
- data/lib/solargraph/source.rb +27 -29
- data/lib/solargraph/source_map/clip.rb +38 -30
- data/lib/solargraph/source_map/mapper.rb +51 -47
- data/lib/solargraph/source_map.rb +8 -4
- data/lib/solargraph/type_checker/rules.rb +8 -8
- data/lib/solargraph/type_checker.rb +95 -102
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +11 -10
- data/lib/solargraph/workspace/gemspecs.rb +3 -3
- data/lib/solargraph/workspace.rb +45 -165
- data/lib/solargraph/yard_map/helpers.rb +6 -2
- data/lib/solargraph/yard_map/mapper/to_method.rb +8 -6
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -1
- data/lib/solargraph/yard_map/mapper.rb +12 -12
- data/lib/solargraph/yard_map.rb +17 -18
- data/lib/solargraph/yard_tags.rb +20 -20
- data/lib/solargraph/yardoc.rb +26 -33
- data/lib/solargraph.rb +7 -5
- data/solargraph.gemspec +36 -35
- metadata +33 -38
data/lib/solargraph/shell.rb
CHANGED
|
@@ -16,7 +16,7 @@ module Solargraph
|
|
|
16
16
|
|
|
17
17
|
map %w[--version -v] => :version
|
|
18
18
|
|
|
19
|
-
desc
|
|
19
|
+
desc '--version, -v', 'Print the version'
|
|
20
20
|
# @return [void]
|
|
21
21
|
def version
|
|
22
22
|
puts Solargraph::VERSION
|
|
@@ -31,15 +31,15 @@ module Solargraph
|
|
|
31
31
|
port = options[:port]
|
|
32
32
|
port = available_port if port.zero?
|
|
33
33
|
Backport.run do
|
|
34
|
-
Signal.trap(
|
|
34
|
+
Signal.trap('INT') do
|
|
35
35
|
Backport.stop
|
|
36
36
|
end
|
|
37
|
-
Signal.trap(
|
|
37
|
+
Signal.trap('TERM') do
|
|
38
38
|
Backport.stop
|
|
39
39
|
end
|
|
40
40
|
# @sg-ignore Wrong argument type for Backport.prepare_tcp_server: adapter expected Backport::Adapter, received Module<Solargraph::LanguageServer::Transport::Adapter>
|
|
41
41
|
Backport.prepare_tcp_server host: options[:host], port: port, adapter: Solargraph::LanguageServer::Transport::Adapter
|
|
42
|
-
|
|
42
|
+
$stderr.puts "Solargraph is listening PORT=#{port} PID=#{Process.pid}"
|
|
43
43
|
end
|
|
44
44
|
end
|
|
45
45
|
|
|
@@ -48,15 +48,15 @@ module Solargraph
|
|
|
48
48
|
def stdio
|
|
49
49
|
require 'backport'
|
|
50
50
|
Backport.run do
|
|
51
|
-
Signal.trap(
|
|
51
|
+
Signal.trap('INT') do
|
|
52
52
|
Backport.stop
|
|
53
53
|
end
|
|
54
|
-
Signal.trap(
|
|
54
|
+
Signal.trap('TERM') do
|
|
55
55
|
Backport.stop
|
|
56
56
|
end
|
|
57
57
|
# @sg-ignore Wrong argument type for Backport.prepare_stdio_server: adapter expected Backport::Adapter, received Module<Solargraph::LanguageServer::Transport::Adapter>
|
|
58
58
|
Backport.prepare_stdio_server adapter: Solargraph::LanguageServer::Transport::Adapter
|
|
59
|
-
|
|
59
|
+
$stderr.puts "Solargraph is listening on stdio PID=#{Process.pid}"
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
62
|
|
|
@@ -64,11 +64,11 @@ module Solargraph
|
|
|
64
64
|
option :extensions, type: :boolean, aliases: :e, desc: 'Add installed extensions', default: true
|
|
65
65
|
# @param directory [String]
|
|
66
66
|
# @return [void]
|
|
67
|
-
def config
|
|
67
|
+
def config directory = '.'
|
|
68
68
|
matches = []
|
|
69
69
|
if options[:extensions]
|
|
70
70
|
Gem::Specification.each do |g|
|
|
71
|
-
if g.name.match(/^solargraph
|
|
71
|
+
if g.name.match(/^solargraph-[A-Za-z0-9_-]*?-ext/)
|
|
72
72
|
require g.name
|
|
73
73
|
matches.push g.name
|
|
74
74
|
end
|
|
@@ -84,7 +84,7 @@ module Solargraph
|
|
|
84
84
|
File.open(File.join(directory, '.solargraph.yml'), 'w') do |file|
|
|
85
85
|
file.puts conf.to_yaml
|
|
86
86
|
end
|
|
87
|
-
|
|
87
|
+
$stdout.puts 'Configuration file initialized.'
|
|
88
88
|
end
|
|
89
89
|
|
|
90
90
|
desc 'clear', 'Delete all cached documentation'
|
|
@@ -93,7 +93,7 @@ module Solargraph
|
|
|
93
93
|
)
|
|
94
94
|
# @return [void]
|
|
95
95
|
def clear
|
|
96
|
-
puts
|
|
96
|
+
puts 'Deleting all cached documentation (gems, core and stdlib)'
|
|
97
97
|
Solargraph::PinCache.clear
|
|
98
98
|
end
|
|
99
99
|
map 'clear-cache' => :clear
|
|
@@ -105,11 +105,25 @@ module Solargraph
|
|
|
105
105
|
# @param gem [String]
|
|
106
106
|
# @param version [String, nil]
|
|
107
107
|
def cache gem, version = nil
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
gemspec = Gem::Specification.find_by_name(gem, version)
|
|
109
|
+
|
|
110
|
+
if options[:rebuild] || !PinCache.has_yard?(gemspec)
|
|
111
|
+
pins = GemPins.build_yard_pins(['yard-activesupport-concern'], gemspec)
|
|
112
|
+
PinCache.serialize_yard_gem(gemspec, pins)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
workspace = Solargraph::Workspace.new(Dir.pwd)
|
|
116
|
+
rbs_map = RbsMap.from_gemspec(gemspec, workspace.rbs_collection_path, workspace.rbs_collection_config_path)
|
|
117
|
+
if options[:rebuild] || !PinCache.has_rbs_collection?(gemspec, rbs_map.cache_key)
|
|
118
|
+
# cache pins even if result is zero, so we don't retry building pins
|
|
119
|
+
pins = rbs_map.pins || []
|
|
120
|
+
PinCache.serialize_rbs_collection_gem(gemspec, rbs_map.cache_key, pins)
|
|
121
|
+
end
|
|
122
|
+
rescue Gem::MissingSpecError
|
|
123
|
+
warn "Gem '#{gem}' not found"
|
|
110
124
|
end
|
|
111
125
|
|
|
112
|
-
desc 'uncache GEM [...GEM]',
|
|
126
|
+
desc 'uncache GEM [...GEM]', 'Delete specific cached gem documentation'
|
|
113
127
|
long_desc %(
|
|
114
128
|
Specify one or more gem names to clear. 'core' or 'stdlib' may
|
|
115
129
|
also be specified to clear cached system documentation.
|
|
@@ -119,24 +133,19 @@ module Solargraph
|
|
|
119
133
|
# @return [void]
|
|
120
134
|
def uncache *gems
|
|
121
135
|
raise ArgumentError, 'No gems specified.' if gems.empty?
|
|
122
|
-
workspace = Solargraph::Workspace.new(Dir.pwd)
|
|
123
|
-
|
|
124
136
|
gems.each do |gem|
|
|
125
137
|
if gem == 'core'
|
|
126
|
-
PinCache.uncache_core
|
|
138
|
+
PinCache.uncache_core
|
|
127
139
|
next
|
|
128
140
|
end
|
|
129
141
|
|
|
130
142
|
if gem == 'stdlib'
|
|
131
|
-
PinCache.uncache_stdlib
|
|
143
|
+
PinCache.uncache_stdlib
|
|
132
144
|
next
|
|
133
145
|
end
|
|
134
146
|
|
|
135
|
-
spec =
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
# @sg-ignore flow sensitive typing needs to handle 'raise if'
|
|
139
|
-
workspace.uncache_gem(spec, out: $stdout)
|
|
147
|
+
spec = Gem::Specification.find_by_name(gem)
|
|
148
|
+
PinCache.uncache_gem(spec, out: $stdout)
|
|
140
149
|
end
|
|
141
150
|
end
|
|
142
151
|
|
|
@@ -172,11 +181,13 @@ module Solargraph
|
|
|
172
181
|
workspace = Solargraph::Workspace.new('.')
|
|
173
182
|
|
|
174
183
|
if names.empty?
|
|
175
|
-
|
|
184
|
+
Gem::Specification.to_a.each { |spec| do_cache spec, rebuild: options[:rebuild] }
|
|
185
|
+
$stderr.puts "Documentation cached for all #{Gem::Specification.count} gems."
|
|
176
186
|
else
|
|
177
|
-
|
|
187
|
+
warn("Caching these gems: #{names}")
|
|
178
188
|
names.each do |name|
|
|
179
189
|
if name == 'core'
|
|
190
|
+
# @sg-ignore cache_core and core? are dynamically defined
|
|
180
191
|
PinCache.cache_core(out: $stdout) if !PinCache.core? || options[:rebuild]
|
|
181
192
|
next
|
|
182
193
|
end
|
|
@@ -185,7 +196,18 @@ module Solargraph
|
|
|
185
196
|
if gemspec.nil?
|
|
186
197
|
warn "Gem '#{name}' not found"
|
|
187
198
|
else
|
|
188
|
-
|
|
199
|
+
if options[:rebuild] || !PinCache.has_yard?(gemspec)
|
|
200
|
+
pins = GemPins.build_yard_pins(['yard-activesupport-concern'], gemspec)
|
|
201
|
+
PinCache.serialize_yard_gem(gemspec, pins)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
workspace = Solargraph::Workspace.new(Dir.pwd)
|
|
205
|
+
rbs_map = RbsMap.from_gemspec(gemspec, workspace.rbs_collection_path, workspace.rbs_collection_config_path)
|
|
206
|
+
if options[:rebuild] || !PinCache.has_rbs_collection?(gemspec, rbs_map.cache_key)
|
|
207
|
+
# cache pins even if result is zero, so we don't retry building pins
|
|
208
|
+
pins = rbs_map.pins || []
|
|
209
|
+
PinCache.serialize_rbs_collection_gem(gemspec, rbs_map.cache_key, pins)
|
|
210
|
+
end
|
|
189
211
|
end
|
|
190
212
|
rescue Gem::MissingSpecError
|
|
191
213
|
warn "Gem '#{name}' not found"
|
|
@@ -195,7 +217,7 @@ module Solargraph
|
|
|
195
217
|
# @sg-ignore Need to add nil check here
|
|
196
218
|
warn e.backtrace.join("\n")
|
|
197
219
|
end
|
|
198
|
-
|
|
220
|
+
warn "Documentation cached for #{names.count} gems."
|
|
199
221
|
end
|
|
200
222
|
end
|
|
201
223
|
|
|
@@ -212,7 +234,7 @@ module Solargraph
|
|
|
212
234
|
|
|
213
235
|
Type checking levels are normal, typed, strict, and strong.
|
|
214
236
|
)
|
|
215
|
-
option :level, type: :string, aliases: [
|
|
237
|
+
option :level, type: :string, aliases: %i[mode m l], desc: 'Type checking level', default: 'normal'
|
|
216
238
|
option :directory, type: :string, aliases: :d, desc: 'The workspace directory', default: '.'
|
|
217
239
|
# @return [void]
|
|
218
240
|
def typecheck *files
|
|
@@ -231,21 +253,28 @@ module Solargraph
|
|
|
231
253
|
files.map! { |file| File.realpath(file) }
|
|
232
254
|
end
|
|
233
255
|
filecount = 0
|
|
234
|
-
time = Benchmark.measure
|
|
256
|
+
time = Benchmark.measure do
|
|
235
257
|
files.each do |file|
|
|
236
|
-
checker = TypeChecker.new(file, api_map: api_map, rules: rules, level: options[:level].to_sym,
|
|
258
|
+
checker = TypeChecker.new(file, api_map: api_map, rules: rules, level: options[:level].to_sym,
|
|
259
|
+
workspace: workspace)
|
|
237
260
|
problems = checker.problems
|
|
238
261
|
next if problems.empty?
|
|
239
262
|
problems.sort! { |a, b| a.location.range.start.line <=> b.location.range.start.line }
|
|
240
|
-
puts problems.map { |prob|
|
|
263
|
+
puts problems.map { |prob|
|
|
264
|
+
"#{prob.location.filename}:#{prob.location.range.start.line + 1} - #{prob.message}"
|
|
265
|
+
}.join("\n")
|
|
241
266
|
filecount += 1
|
|
242
267
|
probcount += problems.length
|
|
243
268
|
end
|
|
244
|
-
|
|
269
|
+
end
|
|
245
270
|
puts "Typecheck finished in #{time.real} seconds."
|
|
246
|
-
puts "#{probcount} problem#{probcount != 1
|
|
271
|
+
puts "#{probcount} problem#{if probcount != 1
|
|
272
|
+
's'
|
|
273
|
+
end} found#{if files.length != 1
|
|
274
|
+
" in #{filecount} of #{files.length} files"
|
|
275
|
+
end}."
|
|
247
276
|
# "
|
|
248
|
-
exit 1 if probcount
|
|
277
|
+
exit 1 if probcount.positive?
|
|
249
278
|
end
|
|
250
279
|
|
|
251
280
|
desc 'scan', 'Test the workspace for problems'
|
|
@@ -262,26 +291,26 @@ module Solargraph
|
|
|
262
291
|
directory = File.realpath(options[:directory])
|
|
263
292
|
# @type [Solargraph::ApiMap, nil]
|
|
264
293
|
api_map = nil
|
|
265
|
-
time = Benchmark.measure
|
|
294
|
+
time = Benchmark.measure do
|
|
266
295
|
api_map = Solargraph::ApiMap.load_with_cache(directory, $stdout)
|
|
267
296
|
# @sg-ignore flow sensitive typing should be able to handle redefinition
|
|
268
297
|
api_map.pins.each do |pin|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
298
|
+
puts pin_description(pin) if options[:verbose]
|
|
299
|
+
pin.typify api_map
|
|
300
|
+
pin.probe api_map
|
|
301
|
+
rescue StandardError => e
|
|
302
|
+
# @todo to add nil check here
|
|
303
|
+
# @todo should warn on nil dereference below
|
|
304
|
+
warn "Error testing #{pin_description(pin)} #{if pin.location
|
|
305
|
+
"at #{pin.location.filename}:#{pin.location.range.start.line + 1}"
|
|
306
|
+
end}"
|
|
307
|
+
warn "[#{e.class}]: #{e.message}"
|
|
308
|
+
# @todo Need to add nil check here
|
|
309
|
+
# @todo flow sensitive typing should be able to handle redefinition
|
|
310
|
+
warn e.backtrace.join("\n")
|
|
311
|
+
exit 1
|
|
283
312
|
end
|
|
284
|
-
|
|
313
|
+
end
|
|
285
314
|
# @sg-ignore Need to add nil check here
|
|
286
315
|
puts "Scanned #{directory} (#{api_map.pins.length} pins) in #{time.real} seconds."
|
|
287
316
|
end
|
|
@@ -296,12 +325,15 @@ module Solargraph
|
|
|
296
325
|
puts "#{workspace.filenames.length} files total."
|
|
297
326
|
end
|
|
298
327
|
|
|
299
|
-
desc 'pin [PATH]', 'Describe a pin'
|
|
328
|
+
desc 'pin [PATH]', 'Describe a pin'
|
|
300
329
|
option :rbs, type: :boolean, desc: 'Output the pin as RBS', default: false
|
|
301
|
-
option :typify, type: :boolean, desc: 'Output the calculated return type of the pin from annotations',
|
|
330
|
+
option :typify, type: :boolean, desc: 'Output the calculated return type of the pin from annotations',
|
|
331
|
+
default: false
|
|
302
332
|
option :references, type: :boolean, desc: 'Show references', default: false
|
|
303
|
-
option :probe, type: :boolean, desc: 'Output the calculated return type of the pin from annotations and inference',
|
|
304
|
-
|
|
333
|
+
option :probe, type: :boolean, desc: 'Output the calculated return type of the pin from annotations and inference',
|
|
334
|
+
default: false
|
|
335
|
+
option :stack, type: :boolean, desc: 'Show entire stack of a method pin by including definitions in superclasses',
|
|
336
|
+
default: false
|
|
305
337
|
# @param path [String] The path to the method pin, e.g. 'Class#method' or 'Class.method'
|
|
306
338
|
# @return [void]
|
|
307
339
|
def pin path
|
|
@@ -326,7 +358,7 @@ module Solargraph
|
|
|
326
358
|
pin = pins.first
|
|
327
359
|
case pin
|
|
328
360
|
when nil
|
|
329
|
-
|
|
361
|
+
warn "Pin not found for path '#{path}'"
|
|
330
362
|
exit 1
|
|
331
363
|
when Pin::Namespace
|
|
332
364
|
if options[:references]
|
|
@@ -354,21 +386,125 @@ module Solargraph
|
|
|
354
386
|
end
|
|
355
387
|
end
|
|
356
388
|
|
|
389
|
+
desc 'profile [FILE]', 'Profile go-to-definition performance using vernier'
|
|
390
|
+
option :directory, type: :string, aliases: :d, desc: 'The workspace directory', default: '.'
|
|
391
|
+
option :output_dir, type: :string, aliases: :o, desc: 'The output directory for profiles', default: './tmp/profiles'
|
|
392
|
+
option :line, type: :numeric, aliases: :l, desc: 'Line number (0-based)', default: 4
|
|
393
|
+
option :column, type: :numeric, aliases: :c, desc: 'Column number', default: 10
|
|
394
|
+
option :memory, type: :boolean, aliases: :m, desc: 'Include memory usage counter', default: true
|
|
395
|
+
# @param file [String, nil]
|
|
396
|
+
# @return [void]
|
|
397
|
+
def profile file = nil
|
|
398
|
+
begin
|
|
399
|
+
require 'vernier'
|
|
400
|
+
rescue LoadError
|
|
401
|
+
$stderr.puts 'vernier gem not found. Please install this dependency:'
|
|
402
|
+
$stderr.puts
|
|
403
|
+
$stderr.puts " gem 'vernier', '>1.0', '<2'"
|
|
404
|
+
|
|
405
|
+
return
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
hooks = []
|
|
409
|
+
hooks << :memory_usage if options[:memory]
|
|
410
|
+
|
|
411
|
+
directory = File.realpath(options[:directory])
|
|
412
|
+
FileUtils.mkdir_p(options[:output_dir])
|
|
413
|
+
|
|
414
|
+
host = Solargraph::LanguageServer::Host.new
|
|
415
|
+
host.client_capabilities.merge!({ 'window' => { 'workDoneProgress' => true } })
|
|
416
|
+
# @param method [String] The message method
|
|
417
|
+
# @param params [Hash] The method parameters
|
|
418
|
+
# @return [void]
|
|
419
|
+
def host.send_notification method, params
|
|
420
|
+
puts "Notification: #{method} - #{params}"
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
puts 'Parsing and mapping source files...'
|
|
424
|
+
prepare_start = Time.now
|
|
425
|
+
Vernier.profile(out: "#{options[:output_dir]}/parse_benchmark.json.gz", hooks: hooks) do
|
|
426
|
+
puts 'Mapping libraries'
|
|
427
|
+
host.prepare(directory)
|
|
428
|
+
sleep 0.2 until host.libraries.all?(&:mapped?)
|
|
429
|
+
end
|
|
430
|
+
prepare_time = Time.now - prepare_start
|
|
431
|
+
|
|
432
|
+
puts 'Building the catalog...'
|
|
433
|
+
catalog_start = Time.now
|
|
434
|
+
Vernier.profile(out: "#{options[:output_dir]}/catalog_benchmark.json.gz", hooks: hooks) do
|
|
435
|
+
host.catalog
|
|
436
|
+
end
|
|
437
|
+
catalog_time = Time.now - catalog_start
|
|
438
|
+
|
|
439
|
+
# Determine test file
|
|
440
|
+
if file
|
|
441
|
+
test_file = File.join(directory, file)
|
|
442
|
+
else
|
|
443
|
+
test_file = File.join(directory, 'lib', 'other.rb')
|
|
444
|
+
unless File.exist?(test_file)
|
|
445
|
+
# Fallback to any Ruby file in the workspace
|
|
446
|
+
workspace = Solargraph::Workspace.new(directory)
|
|
447
|
+
test_file = workspace.filenames.find { |f| f.end_with?('.rb') }
|
|
448
|
+
unless test_file
|
|
449
|
+
warn 'No Ruby files found in workspace'
|
|
450
|
+
return
|
|
451
|
+
end
|
|
452
|
+
end
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
file_uri = Solargraph::LanguageServer::UriHelpers.file_to_uri(File.absolute_path(test_file))
|
|
456
|
+
|
|
457
|
+
puts "Profiling go-to-definition for #{test_file}"
|
|
458
|
+
puts "Position: line #{options[:line]}, column #{options[:column]}"
|
|
459
|
+
|
|
460
|
+
definition_start = Time.now
|
|
461
|
+
Vernier.profile(out: "#{options[:output_dir]}/definition_benchmark.json.gz", hooks: hooks) do
|
|
462
|
+
message = Solargraph::LanguageServer::Message::TextDocument::Definition.new(
|
|
463
|
+
host, {
|
|
464
|
+
'params' => {
|
|
465
|
+
'textDocument' => { 'uri' => file_uri },
|
|
466
|
+
'position' => { 'line' => options[:line], 'character' => options[:column] }
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
)
|
|
470
|
+
puts 'Processing go-to-definition request...'
|
|
471
|
+
result = message.process
|
|
472
|
+
|
|
473
|
+
puts "Result: #{result.inspect}"
|
|
474
|
+
end
|
|
475
|
+
definition_time = Time.now - definition_start
|
|
476
|
+
|
|
477
|
+
puts "\n=== Timing Results ==="
|
|
478
|
+
puts "Parsing & mapping: #{(prepare_time * 1000).round(2)}ms"
|
|
479
|
+
puts "Catalog building: #{(catalog_time * 1000).round(2)}ms"
|
|
480
|
+
puts "Go-to-definition: #{(definition_time * 1000).round(2)}ms"
|
|
481
|
+
total_time = prepare_time + catalog_time + definition_time
|
|
482
|
+
puts "Total time: #{(total_time * 1000).round(2)}ms"
|
|
483
|
+
|
|
484
|
+
puts "\nProfiles saved to:"
|
|
485
|
+
puts " - #{File.expand_path('parse_benchmark.json.gz', options[:output_dir])}"
|
|
486
|
+
puts " - #{File.expand_path('catalog_benchmark.json.gz', options[:output_dir])}"
|
|
487
|
+
puts " - #{File.expand_path('definition_benchmark.json.gz', options[:output_dir])}"
|
|
488
|
+
|
|
489
|
+
puts "\nUpload the JSON files to https://vernier.prof/ to view the profiles."
|
|
490
|
+
puts 'Or use https://rubygems.org/gems/profile-viewer to view them locally.'
|
|
491
|
+
end
|
|
492
|
+
|
|
357
493
|
private
|
|
358
494
|
|
|
359
495
|
# @param pin [Solargraph::Pin::Base]
|
|
360
496
|
# @return [String]
|
|
361
497
|
def pin_description pin
|
|
362
498
|
desc = if pin.path.nil? || pin.path.empty?
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
499
|
+
if pin.closure
|
|
500
|
+
# @sg-ignore Need to add nil check here
|
|
501
|
+
"#{pin.closure.path} | #{pin.name}"
|
|
502
|
+
else
|
|
503
|
+
"#{pin.context.namespace} | #{pin.name}"
|
|
504
|
+
end
|
|
505
|
+
else
|
|
506
|
+
pin.path
|
|
507
|
+
end
|
|
372
508
|
# @sg-ignore Need to add nil check here
|
|
373
509
|
desc += " (#{pin.location.filename} #{pin.location.range.start.line})" if pin.location
|
|
374
510
|
desc
|
|
@@ -376,7 +512,7 @@ module Solargraph
|
|
|
376
512
|
|
|
377
513
|
# @param type [ComplexType, ComplexType::UniqueType]
|
|
378
514
|
# @return [void]
|
|
379
|
-
def print_type
|
|
515
|
+
def print_type type
|
|
380
516
|
if options[:rbs]
|
|
381
517
|
puts type.to_rbs
|
|
382
518
|
else
|
|
@@ -386,12 +522,34 @@ module Solargraph
|
|
|
386
522
|
|
|
387
523
|
# @param pin [Solargraph::Pin::Base]
|
|
388
524
|
# @return [void]
|
|
389
|
-
def print_pin
|
|
525
|
+
def print_pin pin
|
|
390
526
|
if options[:rbs]
|
|
391
527
|
puts pin.to_rbs
|
|
392
528
|
else
|
|
393
529
|
puts pin.inspect
|
|
394
530
|
end
|
|
395
531
|
end
|
|
532
|
+
|
|
533
|
+
# @param gemspec [Gem::Specification, nil]
|
|
534
|
+
# @param rebuild [Boolean]
|
|
535
|
+
# @return [void]
|
|
536
|
+
def do_cache gemspec, rebuild: false
|
|
537
|
+
if gemspec.nil?
|
|
538
|
+
warn "Gem '#{gemspec&.name}' not found"
|
|
539
|
+
else
|
|
540
|
+
if rebuild || !PinCache.has_yard?(gemspec)
|
|
541
|
+
pins = GemPins.build_yard_pins(['yard-activesupport-concern'], gemspec)
|
|
542
|
+
PinCache.serialize_yard_gem(gemspec, pins)
|
|
543
|
+
end
|
|
544
|
+
|
|
545
|
+
workspace = Solargraph::Workspace.new(Dir.pwd)
|
|
546
|
+
rbs_map = RbsMap.from_gemspec(gemspec, workspace.rbs_collection_path, workspace.rbs_collection_config_path)
|
|
547
|
+
if rebuild || !PinCache.has_rbs_collection?(gemspec, rbs_map.cache_key)
|
|
548
|
+
# cache pins even if result is zero, so we don't retry building pins
|
|
549
|
+
pins = rbs_map.pins || []
|
|
550
|
+
PinCache.serialize_rbs_collection_gem(gemspec, rbs_map.cache_key, pins)
|
|
551
|
+
end
|
|
552
|
+
end
|
|
553
|
+
end
|
|
396
554
|
end
|
|
397
555
|
end
|
|
@@ -1,37 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
# @param
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
ComplexType::UniqueType.new('Array',
|
|
27
|
-
elsif child_types.length ==
|
|
28
|
-
ComplexType::UniqueType.new('Array', rooted: true, parameters_type: :list)
|
|
29
|
-
|
|
30
|
-
ComplexType::UniqueType.new('Array',
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
class Source
|
|
5
|
+
class Chain
|
|
6
|
+
class Array < Literal
|
|
7
|
+
# @param children [::Array<Chain>]
|
|
8
|
+
# @param node [Parser::AST::Node]
|
|
9
|
+
def initialize children, node
|
|
10
|
+
super('::Array', node)
|
|
11
|
+
@children = children
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def word
|
|
15
|
+
@word ||= "<#{@type}>"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# @param api_map [ApiMap]
|
|
19
|
+
# @param name_pin [Pin::Base]
|
|
20
|
+
# @param locals [::Array<Pin::Parameter, Pin::LocalVariable>]
|
|
21
|
+
def resolve api_map, name_pin, locals
|
|
22
|
+
child_types = @children.map do |child|
|
|
23
|
+
child.infer(api_map, name_pin, locals).simplify_literals
|
|
24
|
+
end
|
|
25
|
+
type = if child_types.empty? || child_types.any?(&:undefined?)
|
|
26
|
+
ComplexType::UniqueType.new('Array', rooted: true)
|
|
27
|
+
elsif child_types.uniq.length == 1 && child_types.first.defined?
|
|
28
|
+
ComplexType::UniqueType.new('Array', [], child_types.uniq, rooted: true, parameters_type: :list)
|
|
29
|
+
elsif child_types.empty?
|
|
30
|
+
ComplexType::UniqueType.new('Array', rooted: true, parameters_type: :list)
|
|
31
|
+
else
|
|
32
|
+
ComplexType::UniqueType.new('Array', [], child_types, rooted: true, parameters_type: :fixed)
|
|
33
|
+
end
|
|
34
|
+
[Pin::ProxyType.anonymous(type, source: :chain)]
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|