solargraph 0.54.0 → 0.58.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 +127 -0
- data/.github/workflows/plugins.yml +184 -6
- data/.github/workflows/rspec.yml +55 -5
- data/.github/workflows/typecheck.yml +8 -3
- data/.gitignore +7 -0
- data/.overcommit.yml +72 -0
- data/.rspec +1 -0
- data/.rubocop.yml +66 -0
- data/.rubocop_todo.yml +1279 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +171 -0
- data/README.md +20 -6
- data/Rakefile +125 -13
- data/bin/solargraph +8 -5
- data/lib/solargraph/api_map/cache.rb +13 -3
- data/lib/solargraph/api_map/constants.rb +279 -0
- data/lib/solargraph/api_map/index.rb +193 -0
- data/lib/solargraph/api_map/source_to_yard.rb +13 -4
- data/lib/solargraph/api_map/store.rb +207 -132
- data/lib/solargraph/api_map.rb +394 -261
- data/lib/solargraph/bench.rb +18 -1
- data/lib/solargraph/complex_type/type_methods.rb +29 -12
- data/lib/solargraph/complex_type/unique_type.rb +205 -26
- data/lib/solargraph/complex_type.rb +126 -26
- data/lib/solargraph/convention/active_support_concern.rb +111 -0
- data/lib/solargraph/convention/base.rb +20 -3
- 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 +61 -0
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +102 -0
- data/lib/solargraph/convention/struct_definition.rb +164 -0
- data/lib/solargraph/convention.rb +36 -4
- data/lib/solargraph/diagnostics/rubocop.rb +6 -1
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
- data/lib/solargraph/doc_map.rb +316 -64
- data/lib/solargraph/environ.rb +9 -2
- data/lib/solargraph/equality.rb +34 -0
- data/lib/solargraph/gem_pins.rb +64 -38
- data/lib/solargraph/language_server/host/dispatch.rb +2 -0
- data/lib/solargraph/language_server/host/message_worker.rb +54 -5
- data/lib/solargraph/language_server/host.rb +36 -18
- data/lib/solargraph/language_server/message/base.rb +20 -12
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -0
- data/lib/solargraph/language_server/message/extended/document.rb +5 -2
- data/lib/solargraph/language_server/message/extended/document_gems.rb +3 -3
- data/lib/solargraph/language_server/message/initialize.rb +3 -1
- data/lib/solargraph/language_server/message/text_document/completion.rb +0 -3
- data/lib/solargraph/language_server/message/text_document/definition.rb +5 -3
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +3 -3
- data/lib/solargraph/language_server/message/text_document/formatting.rb +23 -2
- data/lib/solargraph/language_server/message/text_document/hover.rb +1 -1
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +4 -3
- data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +2 -0
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -2
- data/lib/solargraph/language_server/progress.rb +27 -2
- data/lib/solargraph/language_server/request.rb +4 -1
- data/lib/solargraph/library.rb +83 -73
- data/lib/solargraph/location.rb +45 -1
- data/lib/solargraph/logging.rb +12 -2
- data/lib/solargraph/page.rb +3 -0
- data/lib/solargraph/parser/comment_ripper.rb +20 -7
- data/lib/solargraph/parser/flow_sensitive_typing.rb +255 -0
- data/lib/solargraph/parser/node_processor/base.rb +10 -5
- data/lib/solargraph/parser/node_processor.rb +26 -8
- data/lib/solargraph/parser/parser_gem/class_methods.rb +10 -18
- data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +13 -11
- data/lib/solargraph/parser/parser_gem/node_methods.rb +10 -19
- data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +22 -0
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +26 -20
- data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +7 -4
- data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +6 -3
- data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +23 -0
- data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +4 -2
- data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +14 -2
- data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +8 -7
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +98 -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 +3 -1
- data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +16 -6
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +64 -32
- data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +3 -1
- data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -0
- data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +29 -0
- data/lib/solargraph/parser/parser_gem/node_processors.rb +14 -0
- data/lib/solargraph/parser/region.rb +4 -1
- data/lib/solargraph/parser/snippet.rb +2 -0
- data/lib/solargraph/parser.rb +3 -5
- data/lib/solargraph/pin/base.rb +417 -42
- data/lib/solargraph/pin/base_variable.rb +21 -12
- data/lib/solargraph/pin/block.rb +9 -26
- data/lib/solargraph/pin/breakable.rb +9 -0
- data/lib/solargraph/pin/callable.rb +231 -0
- data/lib/solargraph/pin/closure.rb +30 -10
- data/lib/solargraph/pin/common.rb +12 -7
- data/lib/solargraph/pin/constant.rb +2 -0
- data/lib/solargraph/pin/conversions.rb +3 -2
- data/lib/solargraph/pin/delegated_method.rb +20 -1
- data/lib/solargraph/pin/documenting.rb +16 -0
- data/lib/solargraph/pin/instance_variable.rb +2 -2
- data/lib/solargraph/pin/keyword.rb +7 -2
- data/lib/solargraph/pin/local_variable.rb +15 -7
- data/lib/solargraph/pin/method.rb +241 -70
- data/lib/solargraph/pin/method_alias.rb +3 -0
- data/lib/solargraph/pin/namespace.rb +21 -13
- data/lib/solargraph/pin/parameter.rb +94 -32
- data/lib/solargraph/pin/proxy_type.rb +17 -7
- data/lib/solargraph/pin/reference/override.rb +24 -6
- data/lib/solargraph/pin/reference/require.rb +2 -2
- data/lib/solargraph/pin/reference/superclass.rb +5 -0
- data/lib/solargraph/pin/reference.rb +17 -0
- data/lib/solargraph/pin/search.rb +6 -1
- data/lib/solargraph/pin/signature.rb +39 -121
- data/lib/solargraph/pin/singleton.rb +1 -1
- data/lib/solargraph/pin/symbol.rb +8 -2
- data/lib/solargraph/pin/until.rb +18 -0
- data/lib/solargraph/pin/while.rb +18 -0
- data/lib/solargraph/pin.rb +8 -2
- data/lib/solargraph/pin_cache.rb +245 -0
- data/lib/solargraph/position.rb +19 -0
- data/lib/solargraph/range.rb +23 -4
- data/lib/solargraph/rbs_map/conversions.rb +315 -99
- data/lib/solargraph/rbs_map/core_fills.rb +50 -16
- data/lib/solargraph/rbs_map/core_map.rb +41 -11
- data/lib/solargraph/rbs_map/stdlib_map.rb +15 -5
- data/lib/solargraph/rbs_map.rb +87 -16
- data/lib/solargraph/shell.rb +117 -17
- data/lib/solargraph/source/chain/array.rb +13 -8
- data/lib/solargraph/source/chain/block_symbol.rb +1 -1
- data/lib/solargraph/source/chain/block_variable.rb +1 -1
- data/lib/solargraph/source/chain/call.rb +135 -66
- data/lib/solargraph/source/chain/constant.rb +3 -66
- data/lib/solargraph/source/chain/hash.rb +9 -3
- data/lib/solargraph/source/chain/head.rb +1 -1
- data/lib/solargraph/source/chain/if.rb +7 -2
- data/lib/solargraph/source/chain/link.rb +38 -6
- data/lib/solargraph/source/chain/literal.rb +27 -2
- data/lib/solargraph/source/chain/or.rb +2 -2
- data/lib/solargraph/source/chain/z_super.rb +1 -1
- data/lib/solargraph/source/chain.rb +140 -63
- data/lib/solargraph/source/change.rb +2 -2
- data/lib/solargraph/source/cursor.rb +4 -4
- data/lib/solargraph/source/source_chainer.rb +3 -3
- data/lib/solargraph/source.rb +110 -89
- data/lib/solargraph/source_map/clip.rb +22 -28
- data/lib/solargraph/source_map/data.rb +34 -0
- data/lib/solargraph/source_map/mapper.rb +11 -7
- data/lib/solargraph/source_map.rb +50 -43
- data/lib/solargraph/type_checker/checks.rb +4 -0
- data/lib/solargraph/type_checker/param_def.rb +2 -0
- data/lib/solargraph/type_checker/rules.rb +35 -8
- data/lib/solargraph/type_checker.rb +331 -189
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/views/_method.erb +10 -10
- data/lib/solargraph/views/_namespace.erb +3 -3
- data/lib/solargraph/views/document.erb +10 -10
- data/lib/solargraph/views/environment.erb +3 -5
- data/lib/solargraph/workspace/config.rb +25 -5
- data/lib/solargraph/workspace/require_paths.rb +97 -0
- data/lib/solargraph/workspace.rb +53 -72
- data/lib/solargraph/yard_map/helpers.rb +29 -1
- data/lib/solargraph/yard_map/mapper/to_constant.rb +8 -5
- data/lib/solargraph/yard_map/mapper/to_method.rb +55 -19
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +11 -7
- data/lib/solargraph/yard_map/mapper.rb +5 -3
- data/lib/solargraph/yard_map/to_method.rb +6 -3
- data/lib/solargraph/yardoc.rb +45 -10
- data/lib/solargraph.rb +35 -1
- data/rbs/fills/bundler/0/bundler.rbs +4271 -0
- data/rbs/fills/open3/0/open3.rbs +172 -0
- data/rbs/fills/rubygems/0/basic_specification.rbs +326 -0
- data/rbs/fills/rubygems/0/errors.rbs +364 -0
- data/rbs/fills/rubygems/0/spec_fetcher.rbs +107 -0
- data/rbs/fills/rubygems/0/specification.rbs +1753 -0
- data/rbs/fills/tuple/tuple.rbs +149 -0
- data/rbs_collection.yaml +19 -0
- data/sig/shims/ast/0/node.rbs +5 -0
- data/sig/shims/ast/2.4/.rbs_meta.yaml +9 -0
- data/sig/shims/ast/2.4/ast.rbs +73 -0
- data/sig/shims/parser/3.2.0.1/builders/default.rbs +195 -0
- data/sig/shims/parser/3.2.0.1/manifest.yaml +7 -0
- data/sig/shims/parser/3.2.0.1/parser.rbs +201 -0
- data/sig/shims/parser/3.2.0.1/polyfill.rbs +4 -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 +32 -10
- metadata +237 -37
- data/lib/.rubocop.yml +0 -22
- data/lib/solargraph/cache.rb +0 -77
- data/lib/solargraph/parser/node_methods.rb +0 -83
|
@@ -13,38 +13,72 @@ module Solargraph
|
|
|
13
13
|
'elsif', 'end', 'ensure', 'false', 'for', 'if', 'in', 'module', 'next',
|
|
14
14
|
'nil', 'not', 'or', 'redo', 'rescue', 'retry', 'return', 'self', 'super',
|
|
15
15
|
'then', 'true', 'undef', 'unless', 'until', 'when', 'while', 'yield'
|
|
16
|
-
].map { |k| Pin::Keyword.new(k) }
|
|
16
|
+
].map { |k| Pin::Keyword.new(k, source: :core_fill) }
|
|
17
17
|
|
|
18
18
|
MISSING = [
|
|
19
|
-
Solargraph::Pin::Method.new(name: 'tap', scope: :instance,
|
|
20
|
-
closure: Solargraph::Pin::Namespace.new(name: 'Object')),
|
|
21
19
|
Solargraph::Pin::Method.new(name: 'class', scope: :instance,
|
|
22
|
-
closure: Solargraph::Pin::Namespace.new(name: 'Object'), comments: '@return [Class<self>]'
|
|
20
|
+
closure: Solargraph::Pin::Namespace.new(name: 'Object', source: :core_fill), comments: '@return [::Class<self>]',
|
|
21
|
+
source: :core_fill)
|
|
23
22
|
]
|
|
24
23
|
|
|
25
24
|
OVERRIDES = [
|
|
26
|
-
Override.from_comment('BasicObject#instance_eval', '@yieldreceiver [self]'
|
|
27
|
-
|
|
28
|
-
Override.from_comment('
|
|
29
|
-
|
|
30
|
-
Override.from_comment('Module#
|
|
31
|
-
|
|
32
|
-
Override.from_comment('Module#
|
|
25
|
+
Override.from_comment('BasicObject#instance_eval', '@yieldreceiver [self]',
|
|
26
|
+
source: :core_fill),
|
|
27
|
+
Override.from_comment('BasicObject#instance_exec', '@yieldreceiver [self]',
|
|
28
|
+
source: :core_fill),
|
|
29
|
+
Override.from_comment('Module#define_method', '@yieldreceiver [::Object<self>]',
|
|
30
|
+
source: :core_fill),
|
|
31
|
+
Override.from_comment('Module#class_eval', '@yieldreceiver [::Class<self>]',
|
|
32
|
+
source: :core_fill),
|
|
33
|
+
Override.from_comment('Module#class_exec', '@yieldreceiver [::Class<self>]',
|
|
34
|
+
source: :core_fill),
|
|
35
|
+
Override.from_comment('Module#module_eval', '@yieldreceiver [::Module<self>]',
|
|
36
|
+
source: :core_fill),
|
|
37
|
+
Override.from_comment('Module#module_exec', '@yieldreceiver [::Module<self>]',
|
|
38
|
+
source: :core_fill),
|
|
33
39
|
# RBS does not define Class with a generic, so all calls to
|
|
34
40
|
# generic() return an 'untyped'. We can do better:
|
|
35
|
-
Override.method_return('Class#allocate', 'self')
|
|
41
|
+
Override.method_return('Class#allocate', 'self', source: :core_fill),
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
# @todo I don't see any direct link in RBS to build this from -
|
|
45
|
+
# presumably RBS is using duck typing to match interfaces
|
|
46
|
+
# against concrete classes
|
|
47
|
+
INCLUDES = [
|
|
48
|
+
Solargraph::Pin::Reference::Include.new(name: '_ToAry',
|
|
49
|
+
closure: Solargraph::Pin::Namespace.new(name: 'Array', source: :core_fill),
|
|
50
|
+
generic_values: ['generic<Elem>'],
|
|
51
|
+
source: :core_fill),
|
|
52
|
+
Solargraph::Pin::Reference::Include.new(name: '_ToAry',
|
|
53
|
+
closure: Solargraph::Pin::Namespace.new(name: 'Set', source: :core_fill),
|
|
54
|
+
generic_values: ['generic<Elem>'],
|
|
55
|
+
source: :core_fill),
|
|
56
|
+
Solargraph::Pin::Reference::Include.new(name: '_Each',
|
|
57
|
+
closure: Solargraph::Pin::Namespace.new(name: 'Array', source: :core_fill),
|
|
58
|
+
generic_values: ['generic<Elem>'],
|
|
59
|
+
source: :core_fill),
|
|
60
|
+
Solargraph::Pin::Reference::Include.new(name: '_Each',
|
|
61
|
+
closure: Solargraph::Pin::Namespace.new(name: 'Set', source: :core_fill),
|
|
62
|
+
generic_values: ['generic<Elem>'],
|
|
63
|
+
source: :core_fill),
|
|
64
|
+
Solargraph::Pin::Reference::Include.new(name: '_ToS',
|
|
65
|
+
closure: Solargraph::Pin::Namespace.new(name: 'Object', source: :core_fill),
|
|
66
|
+
source: :core_fill),
|
|
67
|
+
Solargraph::Pin::Reference::Include.new(name: '_ToS',
|
|
68
|
+
closure: Solargraph::Pin::Namespace.new(name: 'String', source: :core_fill),
|
|
69
|
+
source: :core_fill)
|
|
36
70
|
]
|
|
37
71
|
|
|
38
72
|
# HACK: Add Errno exception classes
|
|
39
|
-
errno = Solargraph::Pin::Namespace.new(name: 'Errno')
|
|
73
|
+
errno = Solargraph::Pin::Namespace.new(name: 'Errno', source: :core_fill)
|
|
40
74
|
errnos = []
|
|
41
75
|
Errno.constants.each do |const|
|
|
42
|
-
errnos.push Solargraph::Pin::Namespace.new(type: :class, name: const.to_s, closure: errno)
|
|
43
|
-
errnos.push Solargraph::Pin::Reference::Superclass.new(closure: errnos.last, name: 'SystemCallError')
|
|
76
|
+
errnos.push Solargraph::Pin::Namespace.new(type: :class, name: const.to_s, closure: errno, source: :core_fill)
|
|
77
|
+
errnos.push Solargraph::Pin::Reference::Superclass.new(closure: errnos.last, name: 'SystemCallError', source: :core_fill)
|
|
44
78
|
end
|
|
45
79
|
ERRNOS = errnos
|
|
46
80
|
|
|
47
|
-
ALL = KEYWORDS + MISSING + OVERRIDES + ERRNOS
|
|
81
|
+
ALL = KEYWORDS + MISSING + OVERRIDES + ERRNOS + INCLUDES
|
|
48
82
|
end
|
|
49
83
|
end
|
|
50
84
|
end
|
|
@@ -5,23 +5,53 @@ module Solargraph
|
|
|
5
5
|
# Ruby core pins
|
|
6
6
|
#
|
|
7
7
|
class CoreMap
|
|
8
|
-
include
|
|
8
|
+
include Logging
|
|
9
9
|
|
|
10
|
-
def
|
|
11
|
-
|
|
10
|
+
def resolved?
|
|
11
|
+
true
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
FILLS_DIRECTORY = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'rbs', 'fills'))
|
|
15
|
+
|
|
16
|
+
def initialize; end
|
|
17
|
+
|
|
18
|
+
# @return [Enumerable<Pin::Base>]
|
|
19
|
+
def pins
|
|
20
|
+
return @pins if @pins
|
|
21
|
+
|
|
22
|
+
@pins = []
|
|
23
|
+
cache = PinCache.deserialize_core
|
|
12
24
|
if cache
|
|
13
|
-
pins.replace cache
|
|
25
|
+
@pins.replace cache
|
|
14
26
|
else
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
27
|
+
@pins.concat conversions.pins
|
|
28
|
+
|
|
29
|
+
# Avoid RBS::DuplicatedDeclarationError by loading in a different EnvironmentLoader
|
|
30
|
+
fill_loader = RBS::EnvironmentLoader.new(core_root: nil, repository: RBS::Repository.new(no_stdlib: false))
|
|
31
|
+
fill_loader.add(path: Pathname(FILLS_DIRECTORY))
|
|
32
|
+
fill_conversions = Conversions.new(loader: fill_loader)
|
|
33
|
+
@pins.concat fill_conversions.pins
|
|
34
|
+
|
|
35
|
+
@pins.concat RbsMap::CoreFills::ALL
|
|
36
|
+
|
|
19
37
|
processed = ApiMap::Store.new(pins).pins.reject { |p| p.is_a?(Solargraph::Pin::Reference::Override) }
|
|
20
|
-
|
|
21
|
-
pins.replace processed
|
|
38
|
+
@pins.replace processed
|
|
22
39
|
|
|
23
|
-
|
|
40
|
+
PinCache.serialize_core @pins
|
|
24
41
|
end
|
|
42
|
+
@pins
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
# @return [RBS::EnvironmentLoader]
|
|
48
|
+
def loader
|
|
49
|
+
@loader ||= RBS::EnvironmentLoader.new(repository: RBS::Repository.new(no_stdlib: false))
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# @return [Conversions]
|
|
53
|
+
def conversions
|
|
54
|
+
@conversions ||= Conversions.new(loader: loader)
|
|
25
55
|
end
|
|
26
56
|
end
|
|
27
57
|
end
|
|
@@ -7,19 +7,29 @@ module Solargraph
|
|
|
7
7
|
# Ruby stdlib pins
|
|
8
8
|
#
|
|
9
9
|
class StdlibMap < RbsMap
|
|
10
|
+
include Logging
|
|
11
|
+
|
|
10
12
|
# @type [Hash{String => RbsMap}]
|
|
11
13
|
@stdlib_maps_hash = {}
|
|
12
14
|
|
|
13
15
|
# @param library [String]
|
|
14
16
|
def initialize library
|
|
15
|
-
|
|
16
|
-
if
|
|
17
|
-
pins
|
|
17
|
+
cached_pins = PinCache.deserialize_stdlib_require library
|
|
18
|
+
if cached_pins
|
|
19
|
+
@pins = cached_pins
|
|
18
20
|
@resolved = true
|
|
21
|
+
@loaded = true
|
|
22
|
+
logger.debug { "Deserialized #{cached_pins.length} cached pins for stdlib require #{library.inspect}" }
|
|
19
23
|
else
|
|
20
24
|
super
|
|
21
|
-
|
|
22
|
-
|
|
25
|
+
unless resolved?
|
|
26
|
+
@pins = []
|
|
27
|
+
logger.info { "Could not resolve #{library.inspect}" }
|
|
28
|
+
return
|
|
29
|
+
end
|
|
30
|
+
generated_pins = pins
|
|
31
|
+
logger.debug { "Found #{generated_pins.length} pins for stdlib library #{library}" }
|
|
32
|
+
PinCache.serialize_stdlib_require library, generated_pins
|
|
23
33
|
end
|
|
24
34
|
end
|
|
25
35
|
|
data/lib/solargraph/rbs_map.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'digest'
|
|
3
4
|
require 'pathname'
|
|
4
5
|
require 'rbs'
|
|
5
6
|
|
|
@@ -10,25 +11,86 @@ module Solargraph
|
|
|
10
11
|
autoload :CoreFills, 'solargraph/rbs_map/core_fills'
|
|
11
12
|
autoload :StdlibMap, 'solargraph/rbs_map/stdlib_map'
|
|
12
13
|
|
|
13
|
-
include
|
|
14
|
+
include Logging
|
|
14
15
|
|
|
15
16
|
# @type [Hash{String => RbsMap}]
|
|
16
17
|
@@rbs_maps_hash = {}
|
|
17
18
|
|
|
18
19
|
attr_reader :library
|
|
19
20
|
|
|
21
|
+
attr_reader :rbs_collection_paths
|
|
22
|
+
|
|
23
|
+
attr_reader :rbs_collection_config_path
|
|
24
|
+
|
|
20
25
|
# @param library [String]
|
|
21
26
|
# @param version [String, nil]
|
|
22
|
-
# @param
|
|
23
|
-
|
|
27
|
+
# @param rbs_collection_config_path [String, Pathname, nil]
|
|
28
|
+
# @param rbs_collection_paths [Array<Pathname, String>]
|
|
29
|
+
def initialize library, version = nil, rbs_collection_config_path: nil, rbs_collection_paths: []
|
|
30
|
+
if rbs_collection_config_path.nil? && !rbs_collection_paths.empty?
|
|
31
|
+
raise 'Please provide rbs_collection_config_path if you provide rbs_collection_paths'
|
|
32
|
+
end
|
|
24
33
|
@library = library
|
|
25
34
|
@version = version
|
|
26
|
-
@
|
|
27
|
-
@
|
|
28
|
-
loader = RBS::EnvironmentLoader.new(core_root: nil, repository: repository)
|
|
35
|
+
@rbs_collection_config_path = rbs_collection_config_path
|
|
36
|
+
@rbs_collection_paths = rbs_collection_paths
|
|
29
37
|
add_library loader, library, version
|
|
30
|
-
|
|
31
|
-
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @return [RBS::EnvironmentLoader]
|
|
41
|
+
def loader
|
|
42
|
+
@loader ||= RBS::EnvironmentLoader.new(core_root: nil, repository: repository)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# @return [String] representing the version of the RBS info fetched
|
|
46
|
+
# for the given library. Must change when the RBS info is
|
|
47
|
+
# updated upstream for the same library and version. May change
|
|
48
|
+
# if the config for where information comes form changes.
|
|
49
|
+
def cache_key
|
|
50
|
+
@hextdigest ||= begin
|
|
51
|
+
# @type [String, nil]
|
|
52
|
+
data = nil
|
|
53
|
+
if rbs_collection_config_path
|
|
54
|
+
lockfile_path = RBS::Collection::Config.to_lockfile_path(Pathname.new(rbs_collection_config_path))
|
|
55
|
+
if lockfile_path.exist?
|
|
56
|
+
collection_config = RBS::Collection::Config.from_path lockfile_path
|
|
57
|
+
gem_config = collection_config.gem(library)
|
|
58
|
+
data = gem_config&.to_s
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
if data.nil? || data.empty?
|
|
62
|
+
if resolved?
|
|
63
|
+
# definitely came from the gem itself and not elsewhere -
|
|
64
|
+
# only one version per gem
|
|
65
|
+
'gem-export'
|
|
66
|
+
else
|
|
67
|
+
'unresolved'
|
|
68
|
+
end
|
|
69
|
+
else
|
|
70
|
+
Digest::SHA1.hexdigest(data)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# @param gemspec [Gem::Specification, Bundler::LazySpecification]
|
|
76
|
+
# @param rbs_collection_path [String, Pathname, nil]
|
|
77
|
+
# @param rbs_collection_config_path [String, Pathname, nil]
|
|
78
|
+
# @return [RbsMap]
|
|
79
|
+
def self.from_gemspec gemspec, rbs_collection_path, rbs_collection_config_path
|
|
80
|
+
rbs_map = RbsMap.new(gemspec.name, gemspec.version,
|
|
81
|
+
rbs_collection_paths: [rbs_collection_path].compact,
|
|
82
|
+
rbs_collection_config_path: rbs_collection_config_path)
|
|
83
|
+
return rbs_map if rbs_map.resolved?
|
|
84
|
+
|
|
85
|
+
# try any version of the gem in the collection
|
|
86
|
+
RbsMap.new(gemspec.name, nil,
|
|
87
|
+
rbs_collection_paths: [rbs_collection_path].compact,
|
|
88
|
+
rbs_collection_config_path: rbs_collection_config_path)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# @return [Array<Pin::Base>]
|
|
92
|
+
def pins
|
|
93
|
+
@pins ||= resolved? ? conversions.pins : []
|
|
32
94
|
end
|
|
33
95
|
|
|
34
96
|
# @generic T
|
|
@@ -50,11 +112,13 @@ module Solargraph
|
|
|
50
112
|
@resolved
|
|
51
113
|
end
|
|
52
114
|
|
|
115
|
+
# @return [RBS::Repository]
|
|
53
116
|
def repository
|
|
54
117
|
@repository ||= RBS::Repository.new(no_stdlib: false).tap do |repo|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
118
|
+
@rbs_collection_paths.each do |dir|
|
|
119
|
+
dir_path = Pathname.new(dir)
|
|
120
|
+
repo.add(dir_path) if dir_path.exist? && dir_path.directory?
|
|
121
|
+
end
|
|
58
122
|
end
|
|
59
123
|
end
|
|
60
124
|
|
|
@@ -64,22 +128,29 @@ module Solargraph
|
|
|
64
128
|
@@rbs_maps_hash[library] ||= RbsMap.new(library)
|
|
65
129
|
end
|
|
66
130
|
|
|
67
|
-
|
|
68
|
-
|
|
131
|
+
private
|
|
132
|
+
|
|
133
|
+
# @return [RBS::EnvironmentLoader]
|
|
134
|
+
def loader
|
|
135
|
+
@loader ||= RBS::EnvironmentLoader.new(core_root: nil, repository: repository)
|
|
69
136
|
end
|
|
70
137
|
|
|
71
|
-
|
|
138
|
+
# @return [Conversions]
|
|
139
|
+
def conversions
|
|
140
|
+
@conversions ||= Conversions.new(loader: loader)
|
|
141
|
+
end
|
|
72
142
|
|
|
73
143
|
# @param loader [RBS::EnvironmentLoader]
|
|
74
144
|
# @param library [String]
|
|
145
|
+
# @param version [String, nil]
|
|
75
146
|
# @return [Boolean] true if adding the library succeeded
|
|
76
147
|
def add_library loader, library, version
|
|
77
148
|
@resolved = if loader.has_library?(library: library, version: version)
|
|
78
149
|
loader.add library: library, version: version
|
|
79
|
-
|
|
150
|
+
logger.debug { "#{short_name} successfully loaded library #{library}:#{version}" }
|
|
80
151
|
true
|
|
81
152
|
else
|
|
82
|
-
|
|
153
|
+
logger.info { "#{short_name} did not find data for library #{library}:#{version}" }
|
|
83
154
|
false
|
|
84
155
|
end
|
|
85
156
|
end
|
data/lib/solargraph/shell.rb
CHANGED
|
@@ -36,6 +36,7 @@ module Solargraph
|
|
|
36
36
|
Signal.trap("TERM") do
|
|
37
37
|
Backport.stop
|
|
38
38
|
end
|
|
39
|
+
# @sg-ignore Wrong argument type for Backport.prepare_tcp_server: adapter expected Backport::Adapter, received Module<Solargraph::LanguageServer::Transport::Adapter>
|
|
39
40
|
Backport.prepare_tcp_server host: options[:host], port: port, adapter: Solargraph::LanguageServer::Transport::Adapter
|
|
40
41
|
STDERR.puts "Solargraph is listening PORT=#{port} PID=#{Process.pid}"
|
|
41
42
|
end
|
|
@@ -52,6 +53,7 @@ module Solargraph
|
|
|
52
53
|
Signal.trap("TERM") do
|
|
53
54
|
Backport.stop
|
|
54
55
|
end
|
|
56
|
+
# @sg-ignore Wrong argument type for Backport.prepare_stdio_server: adapter expected Backport::Adapter, received Module<Solargraph::LanguageServer::Transport::Adapter>
|
|
55
57
|
Backport.prepare_stdio_server adapter: Solargraph::LanguageServer::Transport::Adapter
|
|
56
58
|
STDERR.puts "Solargraph is listening on stdio PID=#{Process.pid}"
|
|
57
59
|
end
|
|
@@ -77,6 +79,7 @@ module Solargraph
|
|
|
77
79
|
conf['extensions'].push m
|
|
78
80
|
end
|
|
79
81
|
end
|
|
82
|
+
# @param file [File]
|
|
80
83
|
File.open(File.join(directory, '.solargraph.yml'), 'w') do |file|
|
|
81
84
|
file.puts conf.to_yaml
|
|
82
85
|
end
|
|
@@ -89,46 +92,66 @@ module Solargraph
|
|
|
89
92
|
)
|
|
90
93
|
# @return [void]
|
|
91
94
|
def clear
|
|
92
|
-
puts "Deleting
|
|
93
|
-
Solargraph::
|
|
95
|
+
puts "Deleting all cached documentation (gems, core and stdlib)"
|
|
96
|
+
Solargraph::PinCache.clear
|
|
94
97
|
end
|
|
95
98
|
map 'clear-cache' => :clear
|
|
96
99
|
map 'clear-cores' => :clear
|
|
97
100
|
|
|
98
101
|
desc 'cache', 'Cache a gem', hide: true
|
|
102
|
+
option :rebuild, type: :boolean, desc: 'Rebuild existing documentation', default: false
|
|
99
103
|
# @return [void]
|
|
100
104
|
# @param gem [String]
|
|
101
105
|
# @param version [String, nil]
|
|
102
106
|
def cache gem, version = nil
|
|
107
|
+
api_map = Solargraph::ApiMap.load(Dir.pwd)
|
|
103
108
|
spec = Gem::Specification.find_by_name(gem, version)
|
|
104
|
-
|
|
105
|
-
Cache.save('gems', "#{spec.name}-#{spec.version}.ser", pins)
|
|
109
|
+
api_map.cache_gem(spec, rebuild: options[:rebuild], out: $stdout)
|
|
106
110
|
end
|
|
107
111
|
|
|
108
|
-
desc 'uncache GEM [...GEM]', "Delete cached gem documentation"
|
|
112
|
+
desc 'uncache GEM [...GEM]', "Delete specific cached gem documentation"
|
|
113
|
+
long_desc %(
|
|
114
|
+
Specify one or more gem names to clear. 'core' or 'stdlib' may
|
|
115
|
+
also be specified to clear cached system documentation.
|
|
116
|
+
Documentation will be regenerated as needed.
|
|
117
|
+
)
|
|
118
|
+
# @param gems [Array<String>]
|
|
109
119
|
# @return [void]
|
|
110
120
|
def uncache *gems
|
|
111
121
|
raise ArgumentError, 'No gems specified.' if gems.empty?
|
|
112
122
|
gems.each do |gem|
|
|
123
|
+
if gem == 'core'
|
|
124
|
+
PinCache.uncache_core
|
|
125
|
+
next
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
if gem == 'stdlib'
|
|
129
|
+
PinCache.uncache_stdlib
|
|
130
|
+
next
|
|
131
|
+
end
|
|
132
|
+
|
|
113
133
|
spec = Gem::Specification.find_by_name(gem)
|
|
114
|
-
|
|
115
|
-
Cache.uncache('gems', "#{spec.name}-#{spec.version}.yardoc")
|
|
134
|
+
PinCache.uncache_gem(spec, out: $stdout)
|
|
116
135
|
end
|
|
117
136
|
end
|
|
118
137
|
|
|
119
138
|
desc 'gems [GEM[=VERSION]]', 'Cache documentation for installed gems'
|
|
120
139
|
option :rebuild, type: :boolean, desc: 'Rebuild existing documentation', default: false
|
|
140
|
+
# @param names [Array<String>]
|
|
121
141
|
# @return [void]
|
|
122
142
|
def gems *names
|
|
143
|
+
api_map = ApiMap.load('.')
|
|
123
144
|
if names.empty?
|
|
124
|
-
Gem::Specification.to_a.each { |spec| do_cache spec }
|
|
145
|
+
Gem::Specification.to_a.each { |spec| do_cache spec, api_map }
|
|
146
|
+
STDERR.puts "Documentation cached for all #{Gem::Specification.count} gems."
|
|
125
147
|
else
|
|
126
148
|
names.each do |name|
|
|
127
149
|
spec = Gem::Specification.find_by_name(*name.split('='))
|
|
128
|
-
do_cache spec
|
|
150
|
+
do_cache spec, api_map
|
|
129
151
|
rescue Gem::MissingSpecError
|
|
130
152
|
warn "Gem '#{name}' not found"
|
|
131
153
|
end
|
|
154
|
+
STDERR.puts "Documentation cached for #{names.count} gems."
|
|
132
155
|
end
|
|
133
156
|
end
|
|
134
157
|
|
|
@@ -150,6 +173,9 @@ module Solargraph
|
|
|
150
173
|
# @return [void]
|
|
151
174
|
def typecheck *files
|
|
152
175
|
directory = File.realpath(options[:directory])
|
|
176
|
+
workspace = Solargraph::Workspace.new(directory)
|
|
177
|
+
level = options[:level].to_sym
|
|
178
|
+
rules = workspace.rules(level)
|
|
153
179
|
api_map = Solargraph::ApiMap.load_with_cache(directory, $stdout)
|
|
154
180
|
probcount = 0
|
|
155
181
|
if files.empty?
|
|
@@ -161,7 +187,7 @@ module Solargraph
|
|
|
161
187
|
|
|
162
188
|
time = Benchmark.measure {
|
|
163
189
|
files.each do |file|
|
|
164
|
-
checker = TypeChecker.new(file, api_map: api_map, level: options[:level].to_sym)
|
|
190
|
+
checker = TypeChecker.new(file, api_map: api_map, level: options[:level].to_sym, workspace: workspace)
|
|
165
191
|
problems = checker.problems
|
|
166
192
|
next if problems.empty?
|
|
167
193
|
problems.sort! { |a, b| a.location.range.start.line <=> b.location.range.start.line }
|
|
@@ -189,6 +215,7 @@ module Solargraph
|
|
|
189
215
|
# @return [void]
|
|
190
216
|
def scan
|
|
191
217
|
directory = File.realpath(options[:directory])
|
|
218
|
+
# @type [Solargraph::ApiMap, nil]
|
|
192
219
|
api_map = nil
|
|
193
220
|
time = Benchmark.measure {
|
|
194
221
|
api_map = Solargraph::ApiMap.load_with_cache(directory, $stdout)
|
|
@@ -218,6 +245,63 @@ module Solargraph
|
|
|
218
245
|
puts "#{workspace.filenames.length} files total."
|
|
219
246
|
end
|
|
220
247
|
|
|
248
|
+
desc 'pin [PATH]', 'Describe a pin', hide: true
|
|
249
|
+
option :rbs, type: :boolean, desc: 'Output the pin as RBS', default: false
|
|
250
|
+
option :typify, type: :boolean, desc: 'Output the calculated return type of the pin from annotations', default: false
|
|
251
|
+
option :references, type: :boolean, desc: 'Show references', default: false
|
|
252
|
+
option :probe, type: :boolean, desc: 'Output the calculated return type of the pin from annotations and inference', default: false
|
|
253
|
+
option :stack, type: :boolean, desc: 'Show entire stack of a method pin by including definitions in superclasses', default: false
|
|
254
|
+
# @param path [String] The path to the method pin, e.g. 'Class#method' or 'Class.method'
|
|
255
|
+
# @return [void]
|
|
256
|
+
def pin path
|
|
257
|
+
api_map = Solargraph::ApiMap.load_with_cache('.', $stderr)
|
|
258
|
+
is_method = path.include?('#') || path.include?('.')
|
|
259
|
+
if is_method && options[:stack]
|
|
260
|
+
scope, ns, meth = if path.include? '#'
|
|
261
|
+
[:instance, *path.split('#', 2)]
|
|
262
|
+
else
|
|
263
|
+
[:class, *path.split('.', 2)]
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
# @sg-ignore Wrong argument type for
|
|
267
|
+
# Solargraph::ApiMap#get_method_stack: rooted_tag
|
|
268
|
+
# expected String, received Array<String>
|
|
269
|
+
pins = api_map.get_method_stack(ns, meth, scope: scope)
|
|
270
|
+
else
|
|
271
|
+
pins = api_map.get_path_pins path
|
|
272
|
+
end
|
|
273
|
+
# @type [Hash{Symbol => Pin::Base}]
|
|
274
|
+
references = {}
|
|
275
|
+
pin = pins.first
|
|
276
|
+
case pin
|
|
277
|
+
when nil
|
|
278
|
+
$stderr.puts "Pin not found for path '#{path}'"
|
|
279
|
+
exit 1
|
|
280
|
+
when Pin::Namespace
|
|
281
|
+
if options[:references]
|
|
282
|
+
superclass_tag = api_map.qualify_superclass(pin.return_type.tag)
|
|
283
|
+
superclass_pin = api_map.get_path_pins(superclass_tag).first if superclass_tag
|
|
284
|
+
references[:superclass] = superclass_pin if superclass_pin
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
pins.each do |pin|
|
|
289
|
+
if options[:typify] || options[:probe]
|
|
290
|
+
type = ComplexType::UNDEFINED
|
|
291
|
+
type = pin.typify(api_map) if options[:typify]
|
|
292
|
+
type = pin.probe(api_map) if options[:probe] && type.undefined?
|
|
293
|
+
print_type(type)
|
|
294
|
+
next
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
print_pin(pin)
|
|
298
|
+
end
|
|
299
|
+
references.each do |key, refpin|
|
|
300
|
+
puts "\n# #{key.to_s.capitalize}:\n\n"
|
|
301
|
+
print_pin(refpin)
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
|
|
221
305
|
private
|
|
222
306
|
|
|
223
307
|
# @param pin [Solargraph::Pin::Base]
|
|
@@ -237,15 +321,31 @@ module Solargraph
|
|
|
237
321
|
end
|
|
238
322
|
|
|
239
323
|
# @param gemspec [Gem::Specification]
|
|
324
|
+
# @param api_map [ApiMap]
|
|
325
|
+
# @return [void]
|
|
326
|
+
def do_cache gemspec, api_map
|
|
327
|
+
# @todo if the rebuild: option is passed as a positional arg,
|
|
328
|
+
# typecheck doesn't complain on the below line
|
|
329
|
+
api_map.cache_gem(gemspec, rebuild: options.rebuild, out: $stdout)
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
# @param type [ComplexType]
|
|
333
|
+
# @return [void]
|
|
334
|
+
def print_type(type)
|
|
335
|
+
if options[:rbs]
|
|
336
|
+
puts type.to_rbs
|
|
337
|
+
else
|
|
338
|
+
puts type.rooted_tag
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
# @param pin [Solargraph::Pin::Base]
|
|
240
343
|
# @return [void]
|
|
241
|
-
def
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
puts "Cache already exists for #{gemspec.name} #{gemspec.version}"
|
|
344
|
+
def print_pin(pin)
|
|
345
|
+
if options[:rbs]
|
|
346
|
+
puts pin.to_rbs
|
|
245
347
|
else
|
|
246
|
-
puts
|
|
247
|
-
pins = GemPins.build(gemspec)
|
|
248
|
-
Cache.save('gems', "#{gemspec.name}-#{gemspec.version}.ser", pins)
|
|
348
|
+
puts pin.inspect
|
|
249
349
|
end
|
|
250
350
|
end
|
|
251
351
|
end
|
|
@@ -3,8 +3,9 @@ module Solargraph
|
|
|
3
3
|
class Chain
|
|
4
4
|
class Array < Literal
|
|
5
5
|
# @param children [::Array<Chain>]
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
# @param node [Parser::AST::Node]
|
|
7
|
+
def initialize children, node
|
|
8
|
+
super('::Array', node)
|
|
8
9
|
@children = children
|
|
9
10
|
end
|
|
10
11
|
|
|
@@ -14,17 +15,21 @@ module Solargraph
|
|
|
14
15
|
|
|
15
16
|
# @param api_map [ApiMap]
|
|
16
17
|
# @param name_pin [Pin::Base]
|
|
17
|
-
# @param locals [
|
|
18
|
+
# @param locals [::Array<Pin::Parameter, Pin::LocalVariable>]
|
|
18
19
|
def resolve api_map, name_pin, locals
|
|
19
20
|
child_types = @children.map do |child|
|
|
20
|
-
child.infer(api_map, name_pin, locals).
|
|
21
|
+
child.infer(api_map, name_pin, locals).simplify_literals
|
|
21
22
|
end
|
|
22
|
-
type = if child_types.
|
|
23
|
-
|
|
23
|
+
type = if child_types.length == 0 || child_types.any?(&:undefined?)
|
|
24
|
+
ComplexType::UniqueType.new('Array', rooted: true)
|
|
25
|
+
elsif child_types.uniq.length == 1 && child_types.first.defined?
|
|
26
|
+
ComplexType::UniqueType.new('Array', [], child_types.uniq, rooted: true, parameters_type: :list)
|
|
27
|
+
elsif child_types.length == 0
|
|
28
|
+
ComplexType::UniqueType.new('Array', rooted: true, parameters_type: :list)
|
|
24
29
|
else
|
|
25
|
-
'
|
|
30
|
+
ComplexType::UniqueType.new('Array', [], child_types, rooted: true, parameters_type: :fixed)
|
|
26
31
|
end
|
|
27
|
-
[Pin::ProxyType.anonymous(
|
|
32
|
+
[Pin::ProxyType.anonymous(type, source: :chain)]
|
|
28
33
|
end
|
|
29
34
|
end
|
|
30
35
|
end
|