solargraph 0.52.0 → 0.53.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/plugins.yml +40 -0
- data/.github/workflows/rspec.yml +1 -3
- data/.github/workflows/typecheck.yml +34 -0
- data/CHANGELOG.md +53 -0
- data/README.md +13 -16
- data/SPONSORS.md +1 -7
- data/lib/solargraph/api_map/cache.rb +59 -21
- data/lib/solargraph/api_map/source_to_yard.rb +17 -10
- data/lib/solargraph/api_map/store.rb +45 -9
- data/lib/solargraph/api_map.rb +178 -113
- data/lib/solargraph/bench.rb +3 -2
- data/lib/solargraph/cache.rb +29 -5
- data/lib/solargraph/complex_type/type_methods.rb +53 -8
- data/lib/solargraph/complex_type/unique_type.rb +171 -58
- data/lib/solargraph/complex_type.rb +62 -9
- data/lib/solargraph/convention.rb +0 -1
- 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 +8 -7
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +1 -0
- 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 +1 -0
- 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 +35 -7
- 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/initialize.rb +5 -2
- data/lib/solargraph/language_server/message/text_document/hover.rb +2 -0
- data/lib/solargraph/language_server/message/text_document.rb +0 -1
- data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +5 -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 +71 -12
- data/lib/solargraph/location.rb +1 -0
- data/lib/solargraph/page.rb +6 -0
- data/lib/solargraph/parser/comment_ripper.rb +3 -0
- data/lib/solargraph/parser/node_methods.rb +47 -8
- data/lib/solargraph/parser/node_processor/base.rb +9 -0
- data/lib/solargraph/parser/{legacy → parser_gem}/class_methods.rb +29 -3
- data/lib/solargraph/parser/{legacy → parser_gem}/flawed_builder.rb +3 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_chainer.rb +42 -34
- data/lib/solargraph/parser/{legacy → parser_gem}/node_methods.rb +201 -29
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/alias_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/args_node.rb +4 -1
- 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 +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/cvasgn_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → 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/{legacy → parser_gem}/node_processors/sclass_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/send_node.rb +2 -2
- data/lib/solargraph/parser/{rubyvm → 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/snippet.rb +2 -0
- data/lib/solargraph/parser.rb +8 -11
- data/lib/solargraph/pin/base.rb +63 -8
- data/lib/solargraph/pin/base_variable.rb +7 -3
- data/lib/solargraph/pin/block.rb +26 -38
- data/lib/solargraph/pin/closure.rb +17 -2
- data/lib/solargraph/pin/common.rb +7 -3
- data/lib/solargraph/pin/conversions.rb +33 -3
- 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 +110 -16
- data/lib/solargraph/pin/namespace.rb +16 -10
- data/lib/solargraph/pin/parameter.rb +41 -10
- data/lib/solargraph/pin/reference/override.rb +2 -2
- data/lib/solargraph/pin/reference.rb +8 -0
- data/lib/solargraph/pin/search.rb +3 -3
- data/lib/solargraph/pin/signature.rb +114 -2
- data/lib/solargraph/pin.rb +0 -1
- data/lib/solargraph/range.rb +2 -2
- data/lib/solargraph/rbs_map/conversions.rb +213 -61
- data/lib/solargraph/rbs_map/core_fills.rb +12 -28
- data/lib/solargraph/rbs_map/core_map.rb +2 -12
- data/lib/solargraph/rbs_map/stdlib_map.rb +2 -8
- data/lib/solargraph/rbs_map.rb +24 -12
- data/lib/solargraph/shell.rb +62 -59
- data/lib/solargraph/source/chain/array.rb +4 -1
- data/lib/solargraph/source/chain/block_symbol.rb +13 -0
- data/lib/solargraph/source/chain/call.rb +95 -26
- 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 +7 -1
- data/lib/solargraph/source/chain/or.rb +1 -1
- data/lib/solargraph/source/chain/z_super.rb +2 -2
- data/lib/solargraph/source/chain.rb +20 -4
- data/lib/solargraph/source/change.rb +3 -0
- data/lib/solargraph/source/cursor.rb +2 -0
- data/lib/solargraph/source/source_chainer.rb +6 -5
- data/lib/solargraph/source.rb +15 -16
- data/lib/solargraph/source_map/clip.rb +14 -9
- data/lib/solargraph/source_map/mapper.rb +10 -0
- data/lib/solargraph/source_map.rb +12 -10
- data/lib/solargraph/type_checker/checks.rb +10 -2
- data/lib/solargraph/type_checker.rb +96 -21
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +8 -6
- data/lib/solargraph/workspace.rb +15 -2
- 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 +16 -3
- data/lib/solargraph/yard_map/to_method.rb +11 -4
- data/lib/solargraph/yard_map.rb +0 -292
- data/lib/solargraph/yardoc.rb +52 -0
- data/lib/solargraph.rb +4 -1
- data/solargraph.gemspec +2 -2
- metadata +35 -58
- data/lib/solargraph/api_map/bundler_methods.rb +0 -22
- data/lib/solargraph/documentor.rb +0 -76
- data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +0 -23
- data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +0 -15
- data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +0 -18
- data/lib/solargraph/parser/legacy/node_processors.rb +0 -55
- data/lib/solargraph/parser/legacy.rb +0 -12
- data/lib/solargraph/parser/rubyvm/class_methods.rb +0 -151
- data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -163
- data/lib/solargraph/parser/rubyvm/node_methods.rb +0 -317
- 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 -33
- data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +0 -23
- data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +0 -75
- data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +0 -68
- 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 -51
- data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +0 -32
- data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +0 -15
- data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +0 -279
- data/lib/solargraph/parser/rubyvm/node_processors.rb +0 -64
- data/lib/solargraph/parser/rubyvm/node_wrapper.rb +0 -47
- data/lib/solargraph/parser/rubyvm.rb +0 -40
- data/lib/solargraph/rbs_map/core_signs.rb +0 -33
@@ -6,6 +6,7 @@ module Solargraph
|
|
6
6
|
# parameters, and invalid param tags.
|
7
7
|
#
|
8
8
|
class TypeCheck < Base
|
9
|
+
# @return [Array<Hash>]
|
9
10
|
def diagnose source, api_map
|
10
11
|
# return [] unless args.include?('always') || api_map.workspaced?(source.filename)
|
11
12
|
severity = Diagnostics::Severities::ERROR
|
@@ -33,14 +33,14 @@ module Solargraph
|
|
33
33
|
# Find a reporter by name.
|
34
34
|
#
|
35
35
|
# @param name [String] The name with which the reporter was registered
|
36
|
-
# @return [Class<Solargraph::Diagnostics::Base
|
36
|
+
# @return [Class<Solargraph::Diagnostics::Base>, nil]
|
37
37
|
def reporter name
|
38
38
|
reporter_hash[name]
|
39
39
|
end
|
40
40
|
|
41
41
|
private
|
42
42
|
|
43
|
-
# @return [Hash]
|
43
|
+
# @return [Hash{String => Class<Solargraph::Diagnostics::Base>}]
|
44
44
|
def reporter_hash
|
45
45
|
@reporter_hash ||= {}
|
46
46
|
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Solargraph
|
4
|
+
# A collection of pins generated from required gems.
|
5
|
+
#
|
6
|
+
class DocMap
|
7
|
+
# @return [Array<String>]
|
8
|
+
attr_reader :requires
|
9
|
+
|
10
|
+
# @return [Array<Gem::Specification>]
|
11
|
+
attr_reader :preferences
|
12
|
+
|
13
|
+
# @return [Array<Pin::Base>]
|
14
|
+
attr_reader :pins
|
15
|
+
|
16
|
+
# @return [Array<Gem::Specification>]
|
17
|
+
attr_reader :uncached_gemspecs
|
18
|
+
|
19
|
+
# @param requires [Array<String>]
|
20
|
+
# @param preferences [Array<Gem::Specification>]
|
21
|
+
def initialize(requires, preferences)
|
22
|
+
@requires = requires.compact
|
23
|
+
@preferences = preferences.compact
|
24
|
+
generate
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Array<Gem::Specification>]
|
28
|
+
def gemspecs
|
29
|
+
@gemspecs ||= required_gem_map.values.compact
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [Array<String>]
|
33
|
+
def unresolved_requires
|
34
|
+
@unresolved_requires ||= required_gem_map.select { |_, gemspec| gemspec.nil? }.keys
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return [Hash{Gem::Specification => Array[Pin::Base]}]
|
38
|
+
def self.gems_in_memory
|
39
|
+
@gems_in_memory ||= {}
|
40
|
+
end
|
41
|
+
|
42
|
+
def dependencies
|
43
|
+
@dependencies ||= (gemspecs.flat_map { |spec| fetch_dependencies(spec) } - gemspecs).to_set
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
# @return [void]
|
49
|
+
def generate
|
50
|
+
@pins = []
|
51
|
+
@uncached_gemspecs = []
|
52
|
+
required_gem_map.each do |path, gemspec|
|
53
|
+
if gemspec
|
54
|
+
try_cache gemspec
|
55
|
+
else
|
56
|
+
try_stdlib_map path
|
57
|
+
end
|
58
|
+
end
|
59
|
+
dependencies.each { |dep| try_cache dep }
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return [Hash{String => Gem::Specification, nil}]
|
63
|
+
def required_gem_map
|
64
|
+
@required_gem_map ||= requires.to_h { |path| [path, resolve_path_to_gemspec(path)] }
|
65
|
+
end
|
66
|
+
|
67
|
+
# @return [Hash{String => Gem::Specification}]
|
68
|
+
def preference_map
|
69
|
+
@preference_map ||= preferences.to_h { |gemspec| [gemspec.name, gemspec] }
|
70
|
+
end
|
71
|
+
|
72
|
+
# @param gemspec [Gem::Specification]
|
73
|
+
# @return [void]
|
74
|
+
def try_cache gemspec
|
75
|
+
return if try_gem_in_memory(gemspec)
|
76
|
+
cache_file = File.join('gems', "#{gemspec.name}-#{gemspec.version}.ser")
|
77
|
+
if Cache.exist?(cache_file)
|
78
|
+
gempins = Cache.load(cache_file)
|
79
|
+
self.class.gems_in_memory[gemspec] = gempins
|
80
|
+
@pins.concat gempins
|
81
|
+
else
|
82
|
+
Solargraph.logger.debug "No pin cache for #{gemspec.name} #{gemspec.version}"
|
83
|
+
@uncached_gemspecs.push gemspec
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# @param path [String] require path that might be in the RBS stdlib collection
|
88
|
+
# @return [void]
|
89
|
+
def try_stdlib_map path
|
90
|
+
map = RbsMap::StdlibMap.load(path)
|
91
|
+
if map.resolved?
|
92
|
+
Solargraph.logger.debug "Loading stdlib pins for #{path}"
|
93
|
+
@pins.concat map.pins
|
94
|
+
else
|
95
|
+
# @todo Temporarily ignoring unresolved `require 'set'`
|
96
|
+
Solargraph.logger.warn "Require path #{path} could not be resolved" unless path == 'set'
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# @param gemspec [Gem::Specification]
|
101
|
+
# @return [Boolean]
|
102
|
+
def try_gem_in_memory gemspec
|
103
|
+
gempins = DocMap.gems_in_memory[gemspec]
|
104
|
+
return false unless gempins
|
105
|
+
Solargraph.logger.debug "Found #{gemspec.name} #{gemspec.version} in memory"
|
106
|
+
@pins.concat gempins
|
107
|
+
true
|
108
|
+
end
|
109
|
+
|
110
|
+
# @param path [String]
|
111
|
+
# @return [Gem::Specification, nil]
|
112
|
+
def resolve_path_to_gemspec path
|
113
|
+
return nil if path.empty?
|
114
|
+
|
115
|
+
gemspec = Gem::Specification.find_by_path(path)
|
116
|
+
if gemspec.nil?
|
117
|
+
gem_name_guess = path.split('/').first
|
118
|
+
begin
|
119
|
+
# this can happen when the gem is included via a local path in
|
120
|
+
# a Gemfile; Gem doesn't try to index the paths in that case.
|
121
|
+
#
|
122
|
+
# See if we can make a good guess:
|
123
|
+
potential_gemspec = Gem::Specification.find_by_name(gem_name_guess)
|
124
|
+
file = "lib/#{path}.rb"
|
125
|
+
gemspec = potential_gemspec if potential_gemspec.files.any? { |gemspec_file| file == gemspec_file }
|
126
|
+
rescue Gem::MissingSpecError
|
127
|
+
Solargraph.logger.debug "Require path #{path} could not be resolved to a gem via find_by_path or guess of #{gem_name_guess}"
|
128
|
+
nil
|
129
|
+
end
|
130
|
+
end
|
131
|
+
gemspec_or_preference gemspec
|
132
|
+
end
|
133
|
+
|
134
|
+
# @param gemspec [Gem::Specification, nil]
|
135
|
+
# @return [Gem::Specification, nil]
|
136
|
+
def gemspec_or_preference gemspec
|
137
|
+
return gemspec unless gemspec && preference_map.key?(gemspec.name)
|
138
|
+
return gemspec if gemspec.version == preference_map[gemspec.name].version
|
139
|
+
|
140
|
+
change_gemspec_version gemspec, preference_map[by_path.name].version
|
141
|
+
end
|
142
|
+
|
143
|
+
# @param gemspec [Gem::Specification]
|
144
|
+
# @param version [Gem::Version]
|
145
|
+
# @return [Gem::Specification]
|
146
|
+
def change_gemspec_version gemspec, version
|
147
|
+
Gem::Specification.find_by_name(gemspec.name, "= #{version}")
|
148
|
+
rescue Gem::MissingSpecError
|
149
|
+
Solargraph.logger.info "Gem #{gemspec.name} version #{version} not found. Using #{gemspec.version} instead"
|
150
|
+
gemspec
|
151
|
+
end
|
152
|
+
|
153
|
+
# @param gemspec [Gem::Specification]
|
154
|
+
# @return [Array<Gem::Specification>]
|
155
|
+
def fetch_dependencies gemspec
|
156
|
+
only_runtime_dependencies(gemspec).each_with_object(Set.new) do |spec, deps|
|
157
|
+
Solargraph.logger.info "Adding #{spec.name} dependency for #{gemspec.name}"
|
158
|
+
dep = Gem::Specification.find_by_name(spec.name, spec.requirement)
|
159
|
+
deps.merge fetch_dependencies(dep) if deps.add?(dep)
|
160
|
+
rescue Gem::MissingSpecError
|
161
|
+
Solargraph.logger.warn "Gem dependency #{spec.name} #{spec.requirements} for #{gemspec.name} not found."
|
162
|
+
end.to_a
|
163
|
+
end
|
164
|
+
|
165
|
+
# @param gemspec [Gem::Specification]
|
166
|
+
# @return [Array<Gem::Dependency>]
|
167
|
+
def only_runtime_dependencies gemspec
|
168
|
+
gemspec.dependencies - gemspec.development_dependencies
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rbs'
|
4
|
+
|
5
|
+
module Solargraph
|
6
|
+
# A utility for building gem pins from a combination of YARD and RBS
|
7
|
+
# documentation.
|
8
|
+
#
|
9
|
+
module GemPins
|
10
|
+
# Build an array of pins from a gem specification. The process starts with
|
11
|
+
# YARD, enhances the resulting pins with RBS definitions, and appends RBS
|
12
|
+
# pins that don't exist in the YARD mapping.
|
13
|
+
#
|
14
|
+
# @param gemspec [Gem::Specification]
|
15
|
+
# @return [Array<Pin::Base>]
|
16
|
+
def self.build(gemspec)
|
17
|
+
yard_pins = build_yard_pins(gemspec)
|
18
|
+
rbs_map = RbsMap.from_gemspec(gemspec)
|
19
|
+
in_yard = Set.new
|
20
|
+
combined = yard_pins.map do |yard|
|
21
|
+
in_yard.add yard.path
|
22
|
+
next yard unless yard.is_a?(Pin::Method)
|
23
|
+
rbs = rbs_map.path_pin(yard.path, Pin::Method)
|
24
|
+
next yard unless rbs
|
25
|
+
# @todo Could not include: attribute and anon_splat
|
26
|
+
# @sg-ignore
|
27
|
+
yard.class.new(
|
28
|
+
location: yard.location,
|
29
|
+
closure: yard.closure,
|
30
|
+
name: yard.name,
|
31
|
+
comments: yard.comments,
|
32
|
+
scope: yard.scope,
|
33
|
+
parameters: rbs.parameters,
|
34
|
+
generics: rbs.generics,
|
35
|
+
node: yard.node,
|
36
|
+
signatures: yard.signatures,
|
37
|
+
return_type: best_return_type(rbs.return_type, yard.return_type)
|
38
|
+
)
|
39
|
+
end
|
40
|
+
in_rbs = rbs_map.pins.reject { |pin| in_yard.include?(pin.path) }
|
41
|
+
combined + in_rbs
|
42
|
+
end
|
43
|
+
|
44
|
+
class << self
|
45
|
+
private
|
46
|
+
|
47
|
+
# @param gemspec [Gem::Specification]
|
48
|
+
# @return [Array<Pin::Base>]
|
49
|
+
def build_yard_pins(gemspec)
|
50
|
+
Yardoc.cache(gemspec) unless Yardoc.cached?(gemspec)
|
51
|
+
yardoc = Yardoc.load!(gemspec)
|
52
|
+
YardMap::Mapper.new(yardoc, gemspec).map
|
53
|
+
end
|
54
|
+
|
55
|
+
# Select the first defined type.
|
56
|
+
#
|
57
|
+
# @param choices [Array<ComplexType>]
|
58
|
+
# @return [ComplexType]
|
59
|
+
def best_return_type *choices
|
60
|
+
choices.find { |pin| pin.defined? } || choices.first || ComplexType::UNDEFINED
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -38,7 +38,7 @@ module Solargraph
|
|
38
38
|
|
39
39
|
# Start the diagnosis thread.
|
40
40
|
#
|
41
|
-
# @return [self]
|
41
|
+
# @return [self, nil]
|
42
42
|
def start
|
43
43
|
return unless @stopped
|
44
44
|
@stopped = false
|
@@ -81,7 +81,7 @@ module Solargraph
|
|
81
81
|
# @return [Mutex]
|
82
82
|
attr_reader :mutex
|
83
83
|
|
84
|
-
# @return [Array]
|
84
|
+
# @return [::Array]
|
85
85
|
attr_reader :queue
|
86
86
|
end
|
87
87
|
end
|
@@ -6,6 +6,12 @@ module Solargraph
|
|
6
6
|
# Methods for associating sources with libraries via URIs.
|
7
7
|
#
|
8
8
|
module Dispatch
|
9
|
+
# @abstract
|
10
|
+
# @return [Host::Diagnoser]
|
11
|
+
def diagnoser
|
12
|
+
raise NotImplementedError, 'Host::Dispatch requires a diagnoser method'
|
13
|
+
end
|
14
|
+
|
9
15
|
# @return [Sources]
|
10
16
|
def sources
|
11
17
|
@sources ||= begin
|
@@ -15,7 +21,7 @@ module Solargraph
|
|
15
21
|
end
|
16
22
|
end
|
17
23
|
|
18
|
-
# @return [Array<Library>]
|
24
|
+
# @return [::Array<Library>]
|
19
25
|
def libraries
|
20
26
|
@libraries ||= []
|
21
27
|
end
|
@@ -27,9 +33,9 @@ module Solargraph
|
|
27
33
|
# @return [void]
|
28
34
|
def update_libraries uri
|
29
35
|
src = sources.find(uri)
|
30
|
-
libraries.
|
31
|
-
|
32
|
-
|
36
|
+
using = libraries.select { |lib| lib.contain?(src.filename) }
|
37
|
+
using.push generic_library_for(uri) if using.empty?
|
38
|
+
using.each { |lib| lib.merge src }
|
33
39
|
diagnoser.schedule uri
|
34
40
|
end
|
35
41
|
|
@@ -89,6 +95,10 @@ module Solargraph
|
|
89
95
|
nil
|
90
96
|
end
|
91
97
|
|
98
|
+
def options
|
99
|
+
@options ||= {}.freeze
|
100
|
+
end
|
101
|
+
|
92
102
|
# Get a generic library for the given URI and attach the corresponding
|
93
103
|
# source.
|
94
104
|
#
|
@@ -103,7 +113,7 @@ module Solargraph
|
|
103
113
|
|
104
114
|
# @return [Library]
|
105
115
|
def generic_library
|
106
|
-
@generic_library ||= Solargraph::Library.new
|
116
|
+
@generic_library ||= Solargraph::Library.new(Solargraph::Workspace.new('', nil, options), nil)
|
107
117
|
end
|
108
118
|
end
|
109
119
|
end
|
@@ -16,6 +16,7 @@ module Solargraph
|
|
16
16
|
end
|
17
17
|
|
18
18
|
# pending handle messages
|
19
|
+
# @return [Array<Hash>]
|
19
20
|
def messages
|
20
21
|
@messages ||= []
|
21
22
|
end
|
@@ -24,6 +25,7 @@ module Solargraph
|
|
24
25
|
@stopped
|
25
26
|
end
|
26
27
|
|
28
|
+
# @return [void]
|
27
29
|
def stop
|
28
30
|
@stopped = true
|
29
31
|
end
|
@@ -37,6 +39,7 @@ module Solargraph
|
|
37
39
|
end
|
38
40
|
end
|
39
41
|
|
42
|
+
# @return [void]
|
40
43
|
def start
|
41
44
|
return unless @stopped
|
42
45
|
@stopped = false
|
@@ -45,6 +48,7 @@ module Solargraph
|
|
45
48
|
end
|
46
49
|
end
|
47
50
|
|
51
|
+
# @return [void]
|
48
52
|
def tick
|
49
53
|
message = @mutex.synchronize do
|
50
54
|
@resource.wait(@mutex) if messages.empty?
|
@@ -43,6 +43,7 @@ module Solargraph
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
+
# @param uri [String]
|
46
47
|
# @return [void]
|
47
48
|
def add_uri(uri)
|
48
49
|
queue.push(uri)
|
@@ -72,6 +73,8 @@ module Solargraph
|
|
72
73
|
open_source_hash[uri] = source
|
73
74
|
end
|
74
75
|
|
76
|
+
# @param uri [String]
|
77
|
+
# @return [void]
|
75
78
|
def open_from_disk uri
|
76
79
|
source = Solargraph::Source.load(UriHelpers.uri_to_file(uri))
|
77
80
|
open_source_hash[uri] = source
|
@@ -83,7 +86,7 @@ module Solargraph
|
|
83
86
|
#
|
84
87
|
# @param uri [String]
|
85
88
|
# @param updater [Source::Updater]
|
86
|
-
# @return [
|
89
|
+
# @return [void]
|
87
90
|
def update uri, updater
|
88
91
|
src = find(uri)
|
89
92
|
mutex.synchronize { open_source_hash[uri] = src.synchronize(updater) }
|
@@ -109,7 +112,7 @@ module Solargraph
|
|
109
112
|
# @raise [FileNotFoundError] if the URI does not match an open source.
|
110
113
|
#
|
111
114
|
# @param uri [String]
|
112
|
-
# @return [Source]
|
115
|
+
# @return [Solargraph::Source]
|
113
116
|
def find uri
|
114
117
|
open_source_hash[uri] || raise(Solargraph::FileNotFoundError, "Host could not find #{uri}")
|
115
118
|
end
|
@@ -136,7 +139,7 @@ module Solargraph
|
|
136
139
|
|
137
140
|
private
|
138
141
|
|
139
|
-
# @return [Hash]
|
142
|
+
# @return [Hash{String => Solargraph::Source}]
|
140
143
|
def open_source_hash
|
141
144
|
@open_source_hash ||= {}
|
142
145
|
end
|
@@ -146,7 +149,7 @@ module Solargraph
|
|
146
149
|
|
147
150
|
# An array of source URIs that are waiting to finish synchronizing.
|
148
151
|
#
|
149
|
-
# @return [Array<String>]
|
152
|
+
# @return [::Array<String>]
|
150
153
|
def queue
|
151
154
|
@queue ||= []
|
152
155
|
end
|
@@ -3,7 +3,6 @@
|
|
3
3
|
require 'diff/lcs'
|
4
4
|
require 'observer'
|
5
5
|
require 'securerandom'
|
6
|
-
require 'set'
|
7
6
|
|
8
7
|
module Solargraph
|
9
8
|
module LanguageServer
|
@@ -59,7 +58,7 @@ module Solargraph
|
|
59
58
|
logger.level = LOG_LEVELS[options['logLevel']] || DEFAULT_LOG_LEVEL
|
60
59
|
end
|
61
60
|
|
62
|
-
# @return [Hash]
|
61
|
+
# @return [Hash{String => [Boolean, String]}]
|
63
62
|
def options
|
64
63
|
@options ||= default_configuration
|
65
64
|
end
|
@@ -101,8 +100,8 @@ module Solargraph
|
|
101
100
|
# Start processing a request from the client. After the message is
|
102
101
|
# processed, caller is responsible for sending the response.
|
103
102
|
#
|
104
|
-
# @param request [Hash] The contents of the message.
|
105
|
-
# @return [Solargraph::LanguageServer::Message::Base] The message handler.
|
103
|
+
# @param request [Hash{String => unspecified}] The contents of the message.
|
104
|
+
# @return [Solargraph::LanguageServer::Message::Base, nil] The message handler.
|
106
105
|
def receive request
|
107
106
|
if request['method']
|
108
107
|
logger.info "Server received #{request['method']}"
|
@@ -127,6 +126,7 @@ module Solargraph
|
|
127
126
|
else
|
128
127
|
logger.warn "Invalid message received."
|
129
128
|
logger.debug request
|
129
|
+
nil
|
130
130
|
end
|
131
131
|
end
|
132
132
|
|
@@ -292,7 +292,8 @@ module Solargraph
|
|
292
292
|
path = ''
|
293
293
|
path = normalize_separators(directory) unless directory.nil?
|
294
294
|
begin
|
295
|
-
|
295
|
+
workspace = Solargraph::Workspace.new(path, nil, options)
|
296
|
+
lib = Solargraph::Library.new(workspace, name)
|
296
297
|
libraries.push lib
|
297
298
|
async_library_map lib
|
298
299
|
rescue WorkspaceTooLargeError => e
|
@@ -492,6 +493,24 @@ module Solargraph
|
|
492
493
|
end
|
493
494
|
if params['data']['path']
|
494
495
|
result.concat library.path_pins(params['data']['path'])
|
496
|
+
# @todo This exception is necessary because `Library#path_pins` does
|
497
|
+
# not perform a namespace method query, so the implicit `.new` pin
|
498
|
+
# might not exist.
|
499
|
+
if result.empty? && params['data']['path'] =~ /\.new$/
|
500
|
+
result.concat(library.path_pins(params['data']['path'].sub(/\.new$/, '#initialize')).map do |pin|
|
501
|
+
next pin unless pin.name == 'initialize'
|
502
|
+
|
503
|
+
Pin::Method.new(
|
504
|
+
name: 'new',
|
505
|
+
scope: :class,
|
506
|
+
location: pin.location,
|
507
|
+
parameters: pin.parameters,
|
508
|
+
return_type: ComplexType.try_parse(params['data']['path']),
|
509
|
+
comments: pin.comments,
|
510
|
+
closure: pin.closure
|
511
|
+
)
|
512
|
+
end)
|
513
|
+
end
|
495
514
|
end
|
496
515
|
# Selecting by both location and path can result in duplicate pins
|
497
516
|
result.uniq { |p| [p.path, p.location] }
|
@@ -505,6 +524,8 @@ module Solargraph
|
|
505
524
|
library.read_text(filename)
|
506
525
|
end
|
507
526
|
|
527
|
+
# @param uri [String]
|
528
|
+
# @return [Hash]
|
508
529
|
def formatter_config uri
|
509
530
|
library = library_for(uri)
|
510
531
|
library.workspace.config.formatter
|
@@ -632,7 +653,7 @@ module Solargraph
|
|
632
653
|
requests.keys
|
633
654
|
end
|
634
655
|
|
635
|
-
# @return [Hash{String =>
|
656
|
+
# @return [Hash{String => [Boolean,String]}]
|
636
657
|
def default_configuration
|
637
658
|
{
|
638
659
|
'completion' => true,
|
@@ -663,6 +684,7 @@ module Solargraph
|
|
663
684
|
libraries.each(&:catalog)
|
664
685
|
end
|
665
686
|
|
687
|
+
# @return [Hash{String => BasicObject}]
|
666
688
|
def client_capabilities
|
667
689
|
@client_capabilities ||= {}
|
668
690
|
end
|
@@ -687,7 +709,7 @@ module Solargraph
|
|
687
709
|
# A hash of client requests by ID. The host uses this to keep track of
|
688
710
|
# pending responses.
|
689
711
|
#
|
690
|
-
# @return [Hash{Integer =>
|
712
|
+
# @return [Hash{Integer => Solargraph::LanguageServer::Host}]
|
691
713
|
def requests
|
692
714
|
@requests ||= {}
|
693
715
|
end
|
@@ -779,6 +801,9 @@ module Solargraph
|
|
779
801
|
'textDocument/definition' => {
|
780
802
|
definitionProvider: true
|
781
803
|
},
|
804
|
+
'textDocument/typeDefinition' => {
|
805
|
+
typeDefinitionProvider: true
|
806
|
+
},
|
782
807
|
'textDocument/references' => {
|
783
808
|
referencesProvider: true
|
784
809
|
},
|
@@ -832,6 +857,9 @@ module Solargraph
|
|
832
857
|
end
|
833
858
|
end
|
834
859
|
|
860
|
+
# @param library [Library]
|
861
|
+
# @param uuid [String, nil]
|
862
|
+
# @return [void]
|
835
863
|
def do_async_library_map library, uuid = nil
|
836
864
|
total = library.workspace.sources.length
|
837
865
|
if uuid
|
@@ -29,7 +29,7 @@ module Solargraph
|
|
29
29
|
end
|
30
30
|
|
31
31
|
# @param text [String]
|
32
|
-
# @return [Hash{Symbol => String}]
|
32
|
+
# @return [Hash{Symbol => String}, nil]
|
33
33
|
def markup_content text
|
34
34
|
return nil if text.strip.empty?
|
35
35
|
{
|
@@ -38,6 +38,8 @@ module Solargraph
|
|
38
38
|
}
|
39
39
|
end
|
40
40
|
|
41
|
+
# @param pins [Array<Pin::Base>]
|
42
|
+
# @return [String]
|
41
43
|
def join_docs pins
|
42
44
|
result = []
|
43
45
|
last_link = nil
|
@@ -1,6 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
|
4
|
+
# @todo PR the RBS gem to add this
|
5
|
+
# @!parse
|
6
|
+
# module ::Gem
|
7
|
+
# class SpecFetcher; end
|
8
|
+
# end
|
4
9
|
|
5
10
|
module Solargraph
|
6
11
|
module LanguageServer
|
@@ -11,16 +16,23 @@ module Solargraph
|
|
11
16
|
# is true, notify the client when the gem is up to date.
|
12
17
|
#
|
13
18
|
class CheckGemVersion < Base
|
19
|
+
# @return [Gem::SpecFetcher]
|
14
20
|
def self.fetcher
|
15
21
|
@fetcher ||= Gem::SpecFetcher.new
|
16
22
|
end
|
17
23
|
|
24
|
+
# @param obj [Gem::SpecFetcher]
|
25
|
+
# @return [Gem::SpecFetcher]
|
18
26
|
def self.fetcher= obj
|
19
27
|
@fetcher = obj
|
20
28
|
end
|
21
29
|
|
22
30
|
GEM_ZERO = Gem::Version.new('0.0.0')
|
23
31
|
|
32
|
+
# @param host [Solargraph::LanguageServer::Host]
|
33
|
+
# @param request [Hash]
|
34
|
+
# @param current [Gem::Version]
|
35
|
+
# @param available [Gem::Version, nil]
|
24
36
|
def initialize host, request, current: Gem::Version.new(Solargraph::VERSION), available: nil
|
25
37
|
super(host, request)
|
26
38
|
@current = current
|
@@ -54,6 +54,7 @@ module Solargraph
|
|
54
54
|
params['workspaceFolders']
|
55
55
|
end
|
56
56
|
|
57
|
+
# @return [Hash{Symbol => undefined}]
|
57
58
|
def static_completion
|
58
59
|
return {} unless host.options['completion']
|
59
60
|
{
|
@@ -64,6 +65,7 @@ module Solargraph
|
|
64
65
|
}
|
65
66
|
end
|
66
67
|
|
68
|
+
# @return [Hash{Symbol => BasicObject}]
|
67
69
|
def static_code_action
|
68
70
|
{
|
69
71
|
codeActionProvider: true,
|
@@ -71,6 +73,7 @@ module Solargraph
|
|
71
73
|
}
|
72
74
|
end
|
73
75
|
|
76
|
+
# @return [Hash{Symbol => BasicObject}]
|
74
77
|
def static_signature_help
|
75
78
|
{
|
76
79
|
signatureHelpProvider: {
|
@@ -123,9 +126,9 @@ module Solargraph
|
|
123
126
|
end
|
124
127
|
|
125
128
|
def static_type_definitions
|
126
|
-
return {} unless host.options['
|
129
|
+
return {} unless host.options['typeDefinitions']
|
127
130
|
{
|
128
|
-
|
131
|
+
typeDefinitionProvider: true
|
129
132
|
}
|
130
133
|
end
|
131
134
|
|
@@ -12,7 +12,6 @@ module Solargraph
|
|
12
12
|
autoload :DidSave, 'solargraph/language_server/message/text_document/did_save'
|
13
13
|
autoload :Hover, 'solargraph/language_server/message/text_document/hover'
|
14
14
|
autoload :SignatureHelp, 'solargraph/language_server/message/text_document/signature_help'
|
15
|
-
autoload :DiagnosticsQueue, 'solargraph/language_server/message/text_document/diagnostics_queue'
|
16
15
|
autoload :OnTypeFormatting, 'solargraph/language_server/message/text_document/on_type_formatting'
|
17
16
|
autoload :Definition, 'solargraph/language_server/message/text_document/definition'
|
18
17
|
autoload :TypeDefinition, 'solargraph/language_server/message/text_document/type_definition'
|
@@ -11,8 +11,12 @@ module Solargraph::LanguageServer::Message::Workspace
|
|
11
11
|
|
12
12
|
private
|
13
13
|
|
14
|
+
# @return [void]
|
14
15
|
def register_from_options
|
16
|
+
Solargraph.logger.debug "Registering capabilities from options: #{host.options.inspect}"
|
17
|
+
# @type [Array<String>]
|
15
18
|
y = []
|
19
|
+
# @type [Array<String>]
|
16
20
|
n = []
|
17
21
|
(host.options['completion'] ? y : n).push('textDocument/completion')
|
18
22
|
(host.options['hover'] ? y : n).push('textDocument/hover', 'textDocument/signatureHelp')
|
@@ -20,6 +24,7 @@ module Solargraph::LanguageServer::Message::Workspace
|
|
20
24
|
(host.options['formatting'] ? y : n).push('textDocument/formatting')
|
21
25
|
(host.options['symbols'] ? y : n).push('textDocument/documentSymbol', 'workspace/symbol')
|
22
26
|
(host.options['definitions'] ? y : n).push('textDocument/definition')
|
27
|
+
(host.options['typeDefinitions'] ? y : n).push('textDocument/typeDefinition')
|
23
28
|
(host.options['references'] ? y : n).push('textDocument/references')
|
24
29
|
(host.options['folding'] ? y : n).push('textDocument/folding')
|
25
30
|
(host.options['highlights'] ? y : n).push('textDocument/documentHighlight')
|