solargraph 0.47.2 → 0.53.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/FUNDING.yml +1 -0
- data/.github/workflows/plugins.yml +40 -0
- data/.github/workflows/rspec.yml +4 -8
- data/.github/workflows/typecheck.yml +34 -0
- data/.yardopts +2 -2
- data/CHANGELOG.md +137 -3
- data/LICENSE +1 -1
- data/README.md +19 -16
- data/SPONSORS.md +2 -9
- data/lib/solargraph/api_map/cache.rb +60 -20
- data/lib/solargraph/api_map/source_to_yard.rb +17 -10
- data/lib/solargraph/api_map/store.rb +60 -12
- data/lib/solargraph/api_map.rb +171 -99
- data/lib/solargraph/bench.rb +3 -2
- data/lib/solargraph/cache.rb +77 -0
- data/lib/solargraph/complex_type/type_methods.rb +61 -12
- data/lib/solargraph/complex_type/unique_type.rb +193 -16
- data/lib/solargraph/complex_type.rb +113 -10
- data/lib/solargraph/convention/rakefile.rb +17 -0
- data/lib/solargraph/convention.rb +2 -3
- data/lib/solargraph/converters/dd.rb +5 -0
- data/lib/solargraph/converters/dl.rb +3 -0
- data/lib/solargraph/converters/dt.rb +3 -0
- data/lib/solargraph/diagnostics/rubocop.rb +23 -8
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +4 -1
- data/lib/solargraph/diagnostics/type_check.rb +1 -0
- data/lib/solargraph/diagnostics.rb +2 -2
- data/lib/solargraph/doc_map.rb +171 -0
- data/lib/solargraph/gem_pins.rb +64 -0
- data/lib/solargraph/language_server/host/cataloger.rb +2 -1
- data/lib/solargraph/language_server/host/diagnoser.rb +2 -2
- data/lib/solargraph/language_server/host/dispatch.rb +15 -5
- data/lib/solargraph/language_server/host/message_worker.rb +4 -0
- data/lib/solargraph/language_server/host/sources.rb +7 -4
- data/lib/solargraph/language_server/host.rb +50 -26
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +3 -1
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +13 -1
- data/lib/solargraph/language_server/message/extended/download_core.rb +1 -5
- data/lib/solargraph/language_server/message/initialize.rb +13 -0
- data/lib/solargraph/language_server/message/initialized.rb +1 -0
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +4 -1
- data/lib/solargraph/language_server/message/text_document/formatting.rb +4 -4
- data/lib/solargraph/language_server/message/text_document/hover.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/signature_help.rb +1 -6
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +24 -0
- data/lib/solargraph/language_server/message/text_document.rb +1 -1
- data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +5 -0
- data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +10 -3
- data/lib/solargraph/language_server/message.rb +1 -0
- data/lib/solargraph/language_server/transport/adapter.rb +16 -1
- data/lib/solargraph/language_server/transport/data_reader.rb +2 -0
- data/lib/solargraph/library.rb +124 -37
- data/lib/solargraph/location.rb +1 -0
- data/lib/solargraph/page.rb +6 -0
- data/lib/solargraph/parser/comment_ripper.rb +4 -0
- data/lib/solargraph/parser/node_methods.rb +47 -7
- data/lib/solargraph/parser/node_processor/base.rb +9 -0
- data/lib/solargraph/parser/{legacy → parser_gem}/class_methods.rb +31 -5
- data/lib/solargraph/parser/{legacy → parser_gem}/flawed_builder.rb +3 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_chainer.rb +57 -41
- data/lib/solargraph/parser/parser_gem/node_methods.rb +499 -0
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/alias_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +53 -0
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/begin_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/block_node.rb +3 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/casgn_node.rb +14 -4
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/cvasgn_node.rb +1 -1
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/def_node.rb +7 -20
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/defs_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/gvasgn_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/ivasgn_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/lvasgn_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/namespace_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/orasgn_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/resbody_node.rb +3 -3
- data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +42 -0
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/send_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/sym_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors.rb +54 -0
- data/lib/solargraph/parser/parser_gem.rb +12 -0
- data/lib/solargraph/parser/region.rb +1 -1
- data/lib/solargraph/parser/snippet.rb +2 -0
- data/lib/solargraph/parser.rb +9 -10
- data/lib/solargraph/pin/base.rb +69 -11
- data/lib/solargraph/pin/base_variable.rb +8 -4
- data/lib/solargraph/pin/block.rb +21 -28
- data/lib/solargraph/pin/closure.rb +17 -2
- data/lib/solargraph/pin/common.rb +7 -3
- data/lib/solargraph/pin/conversions.rb +34 -8
- data/lib/solargraph/pin/delegated_method.rb +97 -0
- data/lib/solargraph/pin/documenting.rb +25 -34
- data/lib/solargraph/pin/instance_variable.rb +4 -0
- data/lib/solargraph/pin/local_variable.rb +13 -1
- data/lib/solargraph/pin/method.rb +270 -16
- data/lib/solargraph/pin/namespace.rb +17 -1
- data/lib/solargraph/pin/parameter.rb +52 -17
- data/lib/solargraph/pin/reference/override.rb +2 -2
- data/lib/solargraph/pin/reference.rb +8 -0
- data/lib/solargraph/pin/search.rb +4 -4
- data/lib/solargraph/pin/signature.rb +143 -0
- data/lib/solargraph/pin.rb +2 -1
- data/lib/solargraph/range.rb +4 -6
- data/lib/solargraph/rbs_map/conversions.rb +601 -0
- data/lib/solargraph/rbs_map/core_fills.rb +47 -0
- data/lib/solargraph/rbs_map/core_map.rb +28 -0
- data/lib/solargraph/rbs_map/stdlib_map.rb +33 -0
- data/lib/solargraph/rbs_map.rb +84 -0
- data/lib/solargraph/shell.rb +69 -48
- data/lib/solargraph/source/chain/array.rb +32 -0
- data/lib/solargraph/source/chain/block_symbol.rb +13 -0
- data/lib/solargraph/source/chain/call.rb +125 -61
- data/lib/solargraph/source/chain/constant.rb +15 -1
- data/lib/solargraph/source/chain/if.rb +23 -0
- data/lib/solargraph/source/chain/link.rb +8 -2
- data/lib/solargraph/source/chain/or.rb +1 -1
- data/lib/solargraph/source/chain/z_super.rb +3 -3
- data/lib/solargraph/source/chain.rb +44 -14
- data/lib/solargraph/source/change.rb +3 -0
- data/lib/solargraph/source/cursor.rb +2 -0
- data/lib/solargraph/source/source_chainer.rb +8 -5
- data/lib/solargraph/source.rb +18 -19
- data/lib/solargraph/source_map/clip.rb +30 -23
- data/lib/solargraph/source_map/mapper.rb +20 -5
- data/lib/solargraph/source_map.rb +28 -13
- data/lib/solargraph/type_checker/checks.rb +10 -2
- data/lib/solargraph/type_checker.rb +201 -98
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/views/environment.erb +2 -2
- data/lib/solargraph/workspace/config.rb +14 -11
- data/lib/solargraph/workspace.rb +28 -17
- data/lib/solargraph/yard_map/cache.rb +6 -0
- data/lib/solargraph/yard_map/helpers.rb +1 -1
- data/lib/solargraph/yard_map/mapper/to_method.rb +18 -5
- data/lib/solargraph/yard_map/mapper.rb +1 -1
- data/lib/solargraph/yard_map/to_method.rb +11 -4
- data/lib/solargraph/yard_map.rb +1 -443
- data/lib/solargraph/yard_tags.rb +20 -0
- data/lib/solargraph/yardoc.rb +52 -0
- data/lib/solargraph.rb +8 -6
- data/solargraph.gemspec +19 -8
- metadata +162 -98
- data/.travis.yml +0 -19
- data/lib/solargraph/api_map/bundler_methods.rb +0 -22
- data/lib/solargraph/compat.rb +0 -37
- data/lib/solargraph/convention/rspec.rb +0 -30
- data/lib/solargraph/documentor.rb +0 -76
- data/lib/solargraph/parser/legacy/node_methods.rb +0 -325
- data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +0 -23
- data/lib/solargraph/parser/legacy/node_processors/args_node.rb +0 -35
- data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +0 -15
- data/lib/solargraph/parser/legacy/node_processors/def_node.rb +0 -63
- data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +0 -21
- data/lib/solargraph/parser/legacy/node_processors.rb +0 -54
- data/lib/solargraph/parser/legacy.rb +0 -12
- data/lib/solargraph/parser/rubyvm/class_methods.rb +0 -144
- data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -160
- data/lib/solargraph/parser/rubyvm/node_methods.rb +0 -315
- data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +0 -85
- data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +0 -42
- data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +0 -22
- data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +0 -23
- data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +0 -57
- data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +0 -23
- data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +0 -38
- data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +0 -39
- data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +0 -20
- data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +0 -27
- data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +0 -39
- data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +0 -26
- data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +0 -15
- data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +0 -45
- data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +0 -21
- data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +0 -15
- data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +0 -277
- data/lib/solargraph/parser/rubyvm/node_processors/sym_node.rb +0 -18
- data/lib/solargraph/parser/rubyvm/node_processors.rb +0 -63
- data/lib/solargraph/parser/rubyvm.rb +0 -40
- data/lib/solargraph/yard_map/core_docs.rb +0 -170
- data/lib/solargraph/yard_map/core_fills.rb +0 -208
- data/lib/solargraph/yard_map/core_gen.rb +0 -76
- data/lib/solargraph/yard_map/rdoc_to_yard.rb +0 -140
- data/lib/solargraph/yard_map/stdlib_fills.rb +0 -43
- data/lib/yard-solargraph.rb +0 -33
- data/yardoc/2.2.2.tar.gz +0 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rbs'
|
4
|
+
|
5
|
+
module Solargraph
|
6
|
+
class RbsMap
|
7
|
+
# Ruby stdlib pins
|
8
|
+
#
|
9
|
+
class StdlibMap < RbsMap
|
10
|
+
# @type [Hash{String => RbsMap}]
|
11
|
+
@stdlib_maps_hash = {}
|
12
|
+
|
13
|
+
# @param library [String]
|
14
|
+
def initialize library
|
15
|
+
cache = Cache.load('stdlib', "#{library}.ser")
|
16
|
+
if cache
|
17
|
+
pins.replace cache
|
18
|
+
@resolved = true
|
19
|
+
else
|
20
|
+
super
|
21
|
+
return unless resolved?
|
22
|
+
Cache.save('stdlib', "#{library}.ser", pins)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# @param library [String]
|
27
|
+
# @return [StdlibMap]
|
28
|
+
def self.load library
|
29
|
+
@stdlib_maps_hash[library] ||= StdlibMap.new(library)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rbs'
|
4
|
+
|
5
|
+
module Solargraph
|
6
|
+
class RbsMap
|
7
|
+
autoload :Conversions, 'solargraph/rbs_map/conversions'
|
8
|
+
autoload :CoreMap, 'solargraph/rbs_map/core_map'
|
9
|
+
autoload :CoreFills, 'solargraph/rbs_map/core_fills'
|
10
|
+
autoload :StdlibMap, 'solargraph/rbs_map/stdlib_map'
|
11
|
+
|
12
|
+
include Conversions
|
13
|
+
|
14
|
+
# @type [Hash{String => RbsMap}]
|
15
|
+
@@rbs_maps_hash = {}
|
16
|
+
|
17
|
+
attr_reader :library
|
18
|
+
|
19
|
+
# @param library [String]
|
20
|
+
def initialize library, version = nil
|
21
|
+
@library = library
|
22
|
+
@version = version
|
23
|
+
@collection = nil
|
24
|
+
loader = RBS::EnvironmentLoader.new(core_root: nil, repository: repository)
|
25
|
+
add_library loader, library, version
|
26
|
+
return unless resolved?
|
27
|
+
load_environment_to_pins(loader)
|
28
|
+
end
|
29
|
+
|
30
|
+
# @generic T
|
31
|
+
# @param path [String]
|
32
|
+
# @param klass [Class<generic<T>>]
|
33
|
+
# @return [generic<T>, nil]
|
34
|
+
def path_pin path, klass = Pin::Base
|
35
|
+
pin = pins.find { |p| p.path == path }
|
36
|
+
pin if pin&.is_a?(klass)
|
37
|
+
end
|
38
|
+
|
39
|
+
# @param path [String]
|
40
|
+
# @return [Array<Pin::Base>]
|
41
|
+
def path_pins path
|
42
|
+
pins.select { |p| p.path == path }
|
43
|
+
end
|
44
|
+
|
45
|
+
def resolved?
|
46
|
+
@resolved
|
47
|
+
end
|
48
|
+
|
49
|
+
def repository
|
50
|
+
@repository ||= RBS::Repository.new(no_stdlib: false)
|
51
|
+
end
|
52
|
+
|
53
|
+
# @param library [String]
|
54
|
+
# @return [RbsMap]
|
55
|
+
def self.load library
|
56
|
+
@@rbs_maps_hash[library] ||= RbsMap.new(library)
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.from_gemspec(gemspec)
|
60
|
+
RbsMap.new(gemspec.name, gemspec.version)
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
# @param loader [RBS::EnvironmentLoader]
|
66
|
+
# @param library [String]
|
67
|
+
# @return [Boolean] true if adding the library succeeded
|
68
|
+
def add_library loader, library, version
|
69
|
+
@resolved = if loader.has_library?(library: library, version: version)
|
70
|
+
loader.add library: library, version: version
|
71
|
+
Solargraph.logger.info "#{short_name} successfully loaded library #{library}"
|
72
|
+
true
|
73
|
+
else
|
74
|
+
Solargraph.logger.debug "#{short_name} failed to load library #{library}"
|
75
|
+
false
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# @return [String]
|
80
|
+
def short_name
|
81
|
+
self.class.name.split('::').last
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/solargraph/shell.rb
CHANGED
@@ -1,14 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'thor'
|
4
|
+
require 'yard'
|
4
5
|
|
5
6
|
module Solargraph
|
6
7
|
class Shell < Thor
|
7
8
|
include Solargraph::ServerMethods
|
8
9
|
|
10
|
+
# Tell Thor to ensure the process exits with status 1 if any error happens.
|
11
|
+
def self.exit_on_failure?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
9
15
|
map %w[--version -v] => :version
|
10
16
|
|
11
17
|
desc "--version, -v", "Print the version"
|
18
|
+
# @return [void]
|
12
19
|
def version
|
13
20
|
puts Solargraph::VERSION
|
14
21
|
end
|
@@ -16,6 +23,7 @@ module Solargraph
|
|
16
23
|
desc 'socket', 'Run a Solargraph socket server'
|
17
24
|
option :host, type: :string, aliases: :h, desc: 'The server host', default: '127.0.0.1'
|
18
25
|
option :port, type: :numeric, aliases: :p, desc: 'The server port', default: 7658
|
26
|
+
# @return [void]
|
19
27
|
def socket
|
20
28
|
require 'backport'
|
21
29
|
port = options[:port]
|
@@ -33,6 +41,7 @@ module Solargraph
|
|
33
41
|
end
|
34
42
|
|
35
43
|
desc 'stdio', 'Run a Solargraph stdio server'
|
44
|
+
# @return [void]
|
36
45
|
def stdio
|
37
46
|
require 'backport'
|
38
47
|
Backport.run do
|
@@ -49,6 +58,8 @@ module Solargraph
|
|
49
58
|
|
50
59
|
desc 'config [DIRECTORY]', 'Create or overwrite a default configuration file'
|
51
60
|
option :extensions, type: :boolean, aliases: :e, desc: 'Add installed extensions', default: true
|
61
|
+
# @param directory [String]
|
62
|
+
# @return [void]
|
52
63
|
def config(directory = '.')
|
53
64
|
matches = []
|
54
65
|
if options[:extensions]
|
@@ -71,59 +82,57 @@ module Solargraph
|
|
71
82
|
STDOUT.puts "Configuration file initialized."
|
72
83
|
end
|
73
84
|
|
74
|
-
desc 'download-core [VERSION]', 'Download core documentation'
|
75
|
-
def download_core version = nil
|
76
|
-
ver = version || Solargraph::YardMap::CoreDocs.best_download
|
77
|
-
if RUBY_VERSION != ver
|
78
|
-
puts "Documentation for #{RUBY_VERSION} is not available. Reverting to closest match..."
|
79
|
-
end
|
80
|
-
puts "Downloading docs for #{ver}..."
|
81
|
-
Solargraph::YardMap::CoreDocs.download ver
|
82
|
-
# Clear cached documentation if it exists
|
83
|
-
FileUtils.rm_rf Dir.glob(File.join(Solargraph::YardMap::CoreDocs.cache_dir, ver, '*.ser'))
|
84
|
-
puts "Download complete."
|
85
|
-
rescue ArgumentError => e
|
86
|
-
STDERR.puts "ERROR: #{e.message}"
|
87
|
-
STDERR.puts "Run `solargraph available-cores` for a list."
|
88
|
-
exit 1
|
89
|
-
end
|
90
|
-
|
91
|
-
desc 'list-cores', 'List the local documentation versions'
|
92
|
-
def list_cores
|
93
|
-
puts Solargraph::YardMap::CoreDocs.versions.join("\n")
|
94
|
-
end
|
95
|
-
|
96
|
-
desc 'available-cores', 'List available documentation versions'
|
97
|
-
def available_cores
|
98
|
-
puts Solargraph::YardMap::CoreDocs.available.join("\n")
|
99
|
-
end
|
100
|
-
|
101
85
|
desc 'clear', 'Delete all cached documentation'
|
102
86
|
long_desc %(
|
103
87
|
This command will delete all core and gem documentation from the cache.
|
104
|
-
You can also delete specific gem caches with the `uncache` command or
|
105
|
-
update documentation for specific Ruby versions with the `download-core`
|
106
|
-
command.
|
107
88
|
)
|
89
|
+
# @return [void]
|
108
90
|
def clear
|
109
91
|
puts "Deleting the cached documentation"
|
110
|
-
Solargraph::
|
92
|
+
Solargraph::Cache.clear
|
111
93
|
end
|
112
94
|
map 'clear-cache' => :clear
|
113
95
|
map 'clear-cores' => :clear
|
114
96
|
|
97
|
+
desc 'cache', 'Cache a gem', hide: true
|
98
|
+
# @return [void]
|
99
|
+
# @param gem [String]
|
100
|
+
# @param version [String, nil]
|
101
|
+
def cache gem, version = nil
|
102
|
+
spec = Gem::Specification.find_by_name(gem, version)
|
103
|
+
pins = GemPins.build(spec)
|
104
|
+
Cache.save('gems', "#{spec.name}-#{spec.version}.ser", pins)
|
105
|
+
end
|
106
|
+
|
115
107
|
desc 'uncache GEM [...GEM]', "Delete cached gem documentation"
|
108
|
+
# @return [void]
|
116
109
|
def uncache *gems
|
117
110
|
raise ArgumentError, 'No gems specified.' if gems.empty?
|
118
111
|
gems.each do |gem|
|
119
|
-
|
120
|
-
|
121
|
-
|
112
|
+
spec = Gem::Specification.find_by_name(gem)
|
113
|
+
Cache.uncache('gems', "#{spec.name}-#{spec.version}.ser")
|
114
|
+
Cache.uncache('gems', "#{spec.name}-#{spec.version}.yardoc")
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
desc 'gems [GEM[=VERSION]]', 'Cache documentation for installed gems'
|
119
|
+
option :rebuild, type: :boolean, desc: 'Rebuild existing documentation', default: false
|
120
|
+
# @return [void]
|
121
|
+
def gems *names
|
122
|
+
if names.empty?
|
123
|
+
Gem::Specification.to_a.each { |spec| do_cache spec }
|
124
|
+
else
|
125
|
+
names.each do |name|
|
126
|
+
spec = Gem::Specification.find_by_name(*name.split('='))
|
127
|
+
do_cache spec
|
128
|
+
rescue Gem::MissingSpecError
|
129
|
+
warn "Gem '#{name}' not found"
|
122
130
|
end
|
123
131
|
end
|
124
132
|
end
|
125
133
|
|
126
134
|
desc 'reporters', 'Get a list of diagnostics reporters'
|
135
|
+
# @return [void]
|
127
136
|
def reporters
|
128
137
|
puts Solargraph::Diagnostics.reporters
|
129
138
|
end
|
@@ -137,9 +146,10 @@ module Solargraph
|
|
137
146
|
)
|
138
147
|
option :level, type: :string, aliases: [:mode, :m, :l], desc: 'Type checking level', default: 'normal'
|
139
148
|
option :directory, type: :string, aliases: :d, desc: 'The workspace directory', default: '.'
|
149
|
+
# @return [void]
|
140
150
|
def typecheck *files
|
141
151
|
directory = File.realpath(options[:directory])
|
142
|
-
api_map = Solargraph::ApiMap.
|
152
|
+
api_map = Solargraph::ApiMap.load_with_cache(directory)
|
143
153
|
if files.empty?
|
144
154
|
files = api_map.source_maps.map(&:filename)
|
145
155
|
else
|
@@ -157,6 +167,7 @@ module Solargraph
|
|
157
167
|
probcount += problems.length
|
158
168
|
end
|
159
169
|
puts "#{probcount} problem#{probcount != 1 ? 's' : ''} found#{files.length != 1 ? " in #{filecount} of #{files.length} files" : ''}."
|
170
|
+
# "
|
160
171
|
exit 1 if probcount > 0
|
161
172
|
end
|
162
173
|
|
@@ -169,12 +180,13 @@ module Solargraph
|
|
169
180
|
)
|
170
181
|
option :directory, type: :string, aliases: :d, desc: 'The workspace directory', default: '.'
|
171
182
|
option :verbose, type: :boolean, aliases: :v, desc: 'Verbose output', default: false
|
183
|
+
# @return [void]
|
172
184
|
def scan
|
173
185
|
require 'benchmark'
|
174
186
|
directory = File.realpath(options[:directory])
|
175
187
|
api_map = nil
|
176
188
|
time = Benchmark.measure {
|
177
|
-
api_map = Solargraph::ApiMap.
|
189
|
+
api_map = Solargraph::ApiMap.load_with_cache(directory)
|
178
190
|
api_map.pins.each do |pin|
|
179
191
|
begin
|
180
192
|
puts pin_description(pin) if options[:verbose]
|
@@ -191,18 +203,14 @@ module Solargraph
|
|
191
203
|
puts "Scanned #{directory} (#{api_map.pins.length} pins) in #{time.real} seconds."
|
192
204
|
end
|
193
205
|
|
194
|
-
desc '
|
195
|
-
option :
|
196
|
-
option :
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
def rdoc gem, version = '>= 0'
|
203
|
-
spec = Gem::Specification.find_by_name(gem, version)
|
204
|
-
puts "Caching #{spec.name} #{spec.version} from RDoc"
|
205
|
-
Solargraph::YardMap::RdocToYard.run(spec)
|
206
|
+
desc 'list', 'List the files in the workspace and the total count'
|
207
|
+
option :count, type: :boolean, aliases: :c, desc: 'Display the file count only', default: false
|
208
|
+
option :directory, type: :string, aliases: :d, desc: 'The directory to read', default: '.'
|
209
|
+
# @return [void]
|
210
|
+
def list
|
211
|
+
workspace = Solargraph::Workspace.new(options[:directory])
|
212
|
+
puts workspace.filenames unless options[:count]
|
213
|
+
puts "#{workspace.filenames.length} files total."
|
206
214
|
end
|
207
215
|
|
208
216
|
private
|
@@ -222,5 +230,18 @@ module Solargraph
|
|
222
230
|
desc += " (#{pin.location.filename} #{pin.location.range.start.line})" if pin.location
|
223
231
|
desc
|
224
232
|
end
|
233
|
+
|
234
|
+
# @param gemspec [Gem::Specification]
|
235
|
+
# @return [void]
|
236
|
+
def do_cache gemspec
|
237
|
+
cached = Yardoc.cached?(gemspec)
|
238
|
+
if cached && !options.rebuild
|
239
|
+
puts "Cache already exists for #{gemspec.name} #{gemspec.version}"
|
240
|
+
else
|
241
|
+
puts "#{cached ? 'Rebuilding' : 'Caching'} gem documentation for #{gemspec.name} #{gemspec.version}"
|
242
|
+
pins = GemPins.build(gemspec)
|
243
|
+
Cache.save('gems', "#{gemspec.name}-#{gemspec.version}.ser", pins)
|
244
|
+
end
|
245
|
+
end
|
225
246
|
end
|
226
247
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Solargraph
|
2
|
+
class Source
|
3
|
+
class Chain
|
4
|
+
class Array < Literal
|
5
|
+
# @param children [::Array<Chain>]
|
6
|
+
def initialize children
|
7
|
+
super('::Array')
|
8
|
+
@children = children
|
9
|
+
end
|
10
|
+
|
11
|
+
def word
|
12
|
+
@word ||= "<#{@type}>"
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param api_map [ApiMap]
|
16
|
+
# @param name_pin [Pin::Base]
|
17
|
+
# @param locals [Enumerable<Pin::LocalVariable>]
|
18
|
+
def resolve api_map, name_pin, locals
|
19
|
+
child_types = @children.map do |child|
|
20
|
+
child.infer(api_map, name_pin, locals).tag
|
21
|
+
end
|
22
|
+
type = if child_types.uniq.length == 1 && child_types.first != 'undefined'
|
23
|
+
"::Array<#{child_types.first}>"
|
24
|
+
else
|
25
|
+
'::Array'
|
26
|
+
end
|
27
|
+
[Pin::ProxyType.anonymous(ComplexType.try_parse(type))]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -7,97 +7,100 @@ module Solargraph
|
|
7
7
|
# @return [String]
|
8
8
|
attr_reader :word
|
9
9
|
|
10
|
-
# @return [Array<Chain>]
|
10
|
+
# @return [::Array<Chain>]
|
11
11
|
attr_reader :arguments
|
12
12
|
|
13
|
+
# @return [Chain, nil]
|
14
|
+
attr_reader :block
|
15
|
+
|
13
16
|
# @param word [String]
|
14
|
-
# @param arguments [Array<Chain>]
|
15
|
-
# @param
|
16
|
-
|
17
|
-
def initialize word, arguments = [], with_block = false
|
17
|
+
# @param arguments [::Array<Chain>]
|
18
|
+
# @param block [Chain, nil]
|
19
|
+
def initialize word, arguments = [], block = nil
|
18
20
|
@word = word
|
19
21
|
@arguments = arguments
|
20
|
-
@
|
22
|
+
@block = block
|
23
|
+
fix_block_pass
|
21
24
|
end
|
22
25
|
|
23
26
|
def with_block?
|
24
|
-
|
27
|
+
!!@block
|
25
28
|
end
|
26
29
|
|
27
30
|
# @param api_map [ApiMap]
|
28
31
|
# @param name_pin [Pin::Base]
|
29
|
-
# @param locals [Array<Pin::
|
32
|
+
# @param locals [::Array<Pin::LocalVariable>]
|
30
33
|
def resolve api_map, name_pin, locals
|
31
34
|
return super_pins(api_map, name_pin) if word == 'super'
|
35
|
+
return yield_pins(api_map, name_pin) if word == 'yield'
|
32
36
|
found = if head?
|
33
37
|
locals.select { |p| p.name == word }
|
34
38
|
else
|
35
39
|
[]
|
36
40
|
end
|
37
41
|
return inferred_pins(found, api_map, name_pin.context, locals) unless found.empty?
|
38
|
-
|
42
|
+
# @param [ComplexType::UniqueType]
|
43
|
+
pins = name_pin.binder.each_unique_type.flat_map do |context|
|
44
|
+
api_map.get_method_stack(context.namespace == '' ? '' : context.tag, word, scope: context.scope)
|
45
|
+
end
|
39
46
|
return [] if pins.empty?
|
40
47
|
inferred_pins(pins, api_map, name_pin.context, locals)
|
41
48
|
end
|
42
49
|
|
43
50
|
private
|
44
51
|
|
45
|
-
# @param pins [
|
52
|
+
# @param pins [::Enumerable<Pin::Method>]
|
46
53
|
# @param api_map [ApiMap]
|
47
54
|
# @param context [ComplexType]
|
48
|
-
# @param locals [Pin::LocalVariable]
|
49
|
-
# @return [Array<Pin::Base>]
|
55
|
+
# @param locals [::Array<Pin::LocalVariable>]
|
56
|
+
# @return [::Array<Pin::Base>]
|
50
57
|
def inferred_pins pins, api_map, context, locals
|
51
58
|
result = pins.map do |p|
|
52
|
-
|
59
|
+
next p unless p.is_a?(Pin::Method)
|
60
|
+
overloads = p.signatures
|
53
61
|
# next p if overloads.empty?
|
54
62
|
type = ComplexType::UNDEFINED
|
55
|
-
#
|
56
|
-
|
57
|
-
|
58
|
-
|
63
|
+
# start with overloads that require blocks; if we are
|
64
|
+
# passing a block, we want to find a signature that will
|
65
|
+
# use it. If we didn't pass a block, the logic below will
|
66
|
+
# reject it regardless
|
67
|
+
|
68
|
+
sorted_overloads = overloads.sort { |ol| ol.block? ? -1 : 1 }
|
69
|
+
new_signature_pin = nil
|
70
|
+
sorted_overloads.each do |ol|
|
71
|
+
next unless arity_matches?(arguments, ol)
|
59
72
|
match = true
|
73
|
+
|
74
|
+
atypes = []
|
60
75
|
arguments.each_with_index do |arg, idx|
|
61
|
-
achain = arguments[idx]
|
62
|
-
next if achain.nil?
|
63
76
|
param = ol.parameters[idx]
|
64
77
|
if param.nil?
|
65
|
-
match =
|
78
|
+
match = ol.parameters.any?(&:restarg?)
|
66
79
|
break
|
67
80
|
end
|
68
|
-
|
69
|
-
next if par.nil? || par.types.nil? || par.types.empty?
|
70
|
-
atype = achain.infer(api_map, Pin::ProxyType.anonymous(context), locals)
|
71
|
-
other = ComplexType.try_parse(*par.types)
|
81
|
+
atype = atypes[idx] ||= arg.infer(api_map, Pin::ProxyType.anonymous(context), locals)
|
72
82
|
# @todo Weak type comparison
|
73
|
-
unless atype.tag ==
|
83
|
+
# unless atype.tag == param.return_type.tag || api_map.super_and_sub?(param.return_type.tag, atype.tag)
|
84
|
+
unless param.return_type.undefined? || atype.name == param.return_type.name || api_map.super_and_sub?(param.return_type.name, atype.name) || param.return_type.generic?
|
74
85
|
match = false
|
75
86
|
break
|
76
87
|
end
|
77
88
|
end
|
78
89
|
if match
|
79
|
-
|
80
|
-
|
81
|
-
|
90
|
+
if ol.block && with_block?
|
91
|
+
block_atypes = ol.block.parameters.map(&:return_type)
|
92
|
+
blocktype = block_call_type(api_map, context, block_atypes, locals)
|
93
|
+
end
|
94
|
+
new_signature_pin = ol.resolve_generics_from_context_until_complete(ol.generics, atypes, nil, nil, blocktype)
|
95
|
+
new_return_type = new_signature_pin.return_type
|
96
|
+
type = with_params(new_return_type.self_to(context.to_s), context).qualify(api_map, context.namespace) if new_return_type.defined?
|
82
97
|
type ||= ComplexType::UNDEFINED
|
83
98
|
end
|
84
99
|
break if type.defined?
|
85
100
|
end
|
101
|
+
p = p.with_single_signature(new_signature_pin) unless new_signature_pin.nil?
|
86
102
|
next p.proxy(type) if type.defined?
|
87
|
-
|
88
|
-
if type
|
89
|
-
next Solargraph::Pin::Method.new(
|
90
|
-
location: p.location,
|
91
|
-
closure: p.closure,
|
92
|
-
name: p.name,
|
93
|
-
comments: "@return [#{context.subtypes.first.to_s}]",
|
94
|
-
scope: p.scope,
|
95
|
-
visibility: p.visibility,
|
96
|
-
parameters: p.parameters,
|
97
|
-
node: p.node
|
98
|
-
)
|
99
|
-
end
|
100
|
-
if p.is_a?(Pin::Method) && !p.macros.empty?
|
103
|
+
if !p.macros.empty?
|
101
104
|
result = process_macro(p, api_map, context, locals)
|
102
105
|
next result unless result.return_type.undefined?
|
103
106
|
elsif !p.directives.empty?
|
@@ -107,19 +110,29 @@ module Solargraph
|
|
107
110
|
p
|
108
111
|
end
|
109
112
|
result.map do |pin|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
+
if pin.path == 'Class#new' && context.tag != 'Class'
|
114
|
+
pin.proxy(ComplexType.try_parse(context.namespace))
|
115
|
+
else
|
116
|
+
next pin if pin.return_type.undefined?
|
117
|
+
selfy = pin.return_type.self_to(context.tag)
|
118
|
+
selfy == pin.return_type ? pin : pin.proxy(selfy)
|
119
|
+
end
|
113
120
|
end
|
114
121
|
end
|
115
122
|
|
116
|
-
# @param pin [Pin::
|
123
|
+
# @param pin [Pin::Base]
|
117
124
|
# @param api_map [ApiMap]
|
118
125
|
# @param context [ComplexType]
|
119
|
-
# @param locals [Pin::Base]
|
126
|
+
# @param locals [Enumerable<Pin::Base>]
|
120
127
|
# @return [Pin::Base]
|
121
128
|
def process_macro pin, api_map, context, locals
|
122
129
|
pin.macros.each do |macro|
|
130
|
+
# @todo 'Wrong argument type for
|
131
|
+
# Solargraph::Source::Chain::Call#inner_process_macro:
|
132
|
+
# macro expected YARD::Tags::MacroDirective, received
|
133
|
+
# generic<Elem>' is because we lose 'rooted' information
|
134
|
+
# in the 'Chain::Array' class internally, leaving
|
135
|
+
# ::Array#each shadowed when it shouldn't be.
|
123
136
|
result = inner_process_macro(pin, macro, api_map, context, locals)
|
124
137
|
return result unless result.return_type.undefined?
|
125
138
|
end
|
@@ -129,7 +142,7 @@ module Solargraph
|
|
129
142
|
# @param pin [Pin::Method]
|
130
143
|
# @param api_map [ApiMap]
|
131
144
|
# @param context [ComplexType]
|
132
|
-
# @param locals [Pin::Base]
|
145
|
+
# @param locals [Enumerable<Pin::Base>]
|
133
146
|
# @return [Pin::ProxyType]
|
134
147
|
def process_directive pin, api_map, context, locals
|
135
148
|
pin.directives.each do |dir|
|
@@ -141,11 +154,11 @@ module Solargraph
|
|
141
154
|
Pin::ProxyType.anonymous ComplexType::UNDEFINED
|
142
155
|
end
|
143
156
|
|
144
|
-
# @param pin [Pin]
|
157
|
+
# @param pin [Pin::Base]
|
145
158
|
# @param macro [YARD::Tags::MacroDirective]
|
146
159
|
# @param api_map [ApiMap]
|
147
160
|
# @param context [ComplexType]
|
148
|
-
# @param locals [
|
161
|
+
# @param locals [Enumerable<Pin::Base>]
|
149
162
|
# @return [Pin::ProxyType]
|
150
163
|
def inner_process_macro pin, macro, api_map, context, locals
|
151
164
|
vals = arguments.map{ |c| Pin::ProxyType.anonymous(c.infer(api_map, pin, locals)) }
|
@@ -169,35 +182,86 @@ module Solargraph
|
|
169
182
|
|
170
183
|
# @param docstring [YARD::Docstring]
|
171
184
|
# @param context [ComplexType]
|
172
|
-
# @return [ComplexType]
|
185
|
+
# @return [ComplexType, nil]
|
173
186
|
def extra_return_type docstring, context
|
174
|
-
if docstring.has_tag?(
|
187
|
+
if docstring.has_tag?('return_single_parameter') #&& context.subtypes.one?
|
175
188
|
return context.subtypes.first || ComplexType::UNDEFINED
|
176
|
-
elsif docstring.has_tag?(
|
189
|
+
elsif docstring.has_tag?('return_value_parameter') && context.value_types.one?
|
177
190
|
return context.value_types.first
|
178
191
|
end
|
179
192
|
nil
|
180
193
|
end
|
181
194
|
|
182
|
-
# @param arguments [Array<Chain>]
|
183
|
-
# @param
|
195
|
+
# @param arguments [::Array<Chain>]
|
196
|
+
# @param signature [Pin::Signature]
|
184
197
|
# @return [Boolean]
|
185
|
-
def
|
198
|
+
def arity_matches? arguments, signature
|
199
|
+
parameters = signature.parameters
|
186
200
|
argcount = arguments.length
|
187
|
-
# argcount -= 1 if !arguments.empty? && arguments.last.links.first.word.start_with?('&')
|
188
201
|
parcount = parameters.length
|
189
|
-
parcount -= 1 if !parameters.empty? && parameters.last.
|
190
|
-
return false if
|
202
|
+
parcount -= 1 if !parameters.empty? && parameters.last.block?
|
203
|
+
return false if signature.block? && !with_block?
|
204
|
+
return false if argcount < parcount && !(argcount == parcount - 1 && parameters.last.restarg?)
|
191
205
|
true
|
192
206
|
end
|
193
207
|
|
194
208
|
# @param api_map [ApiMap]
|
195
209
|
# @param name_pin [Pin::Base]
|
196
|
-
# @return [Array<Pin::Base>]
|
210
|
+
# @return [::Array<Pin::Base>]
|
197
211
|
def super_pins api_map, name_pin
|
198
|
-
pins = api_map.get_method_stack(name_pin.namespace, name_pin.name, scope: name_pin.scope)
|
212
|
+
pins = api_map.get_method_stack(name_pin.namespace, name_pin.name, scope: name_pin.context.scope)
|
199
213
|
pins.reject{|p| p.path == name_pin.path}
|
200
214
|
end
|
215
|
+
|
216
|
+
# @param api_map [ApiMap]
|
217
|
+
# @param name_pin [Pin::Base]
|
218
|
+
# @return [::Array<Pin::Base>]
|
219
|
+
def yield_pins api_map, name_pin
|
220
|
+
method_pin = api_map.get_method_stack(name_pin.namespace, name_pin.name, scope: name_pin.context.scope).first
|
221
|
+
return [] if method_pin.nil?
|
222
|
+
|
223
|
+
method_pin.signatures.map(&:block).compact
|
224
|
+
end
|
225
|
+
|
226
|
+
# @param type [ComplexType]
|
227
|
+
# @param context [ComplexType]
|
228
|
+
# @return [ComplexType]
|
229
|
+
def with_params type, context
|
230
|
+
return type unless type.to_s.include?('$')
|
231
|
+
ComplexType.try_parse(type.to_s.gsub('$', context.value_types.map(&:tag).join(', ')).gsub('<>', ''))
|
232
|
+
end
|
233
|
+
|
234
|
+
# @return [void]
|
235
|
+
def fix_block_pass
|
236
|
+
argument = @arguments.last&.links&.first
|
237
|
+
@block = @arguments.pop if argument.is_a?(BlockSymbol) || argument.is_a?(BlockVariable)
|
238
|
+
end
|
239
|
+
|
240
|
+
# @param api_map [ApiMap]
|
241
|
+
# @param context [ComplexType]
|
242
|
+
# @param block_parameter_types [::Array<ComplexType>]
|
243
|
+
# @param locals [::Array<Pin::LocalVariable>]
|
244
|
+
# @return [ComplexType, nil]
|
245
|
+
def block_call_type(api_map, context, block_parameter_types, locals)
|
246
|
+
return nil unless with_block?
|
247
|
+
|
248
|
+
# @todo Handle BlockVariable
|
249
|
+
if block.links.map(&:class) == [BlockSymbol]
|
250
|
+
# Ruby's shorthand for sending the passed in method name
|
251
|
+
# to the first yield parameter with no arguments
|
252
|
+
block_symbol_name = block.links.first.word
|
253
|
+
block_symbol_call_path = "#{block_parameter_types.first}##{block_symbol_name}"
|
254
|
+
callee = api_map.get_path_pins(block_symbol_call_path).first
|
255
|
+
return_type = callee&.return_type
|
256
|
+
# @todo: Figure out why we get unresolved generics at
|
257
|
+
# this point and need to assume method return types
|
258
|
+
# based on the generic type
|
259
|
+
return_type ||= api_map.get_path_pins("#{context.subtypes.first}##{block.links.first.word}").first&.return_type
|
260
|
+
return_type || ComplexType::UNDEFINED
|
261
|
+
else
|
262
|
+
block.infer(api_map, Pin::ProxyType.anonymous(context), locals)
|
263
|
+
end
|
264
|
+
end
|
201
265
|
end
|
202
266
|
end
|
203
267
|
end
|