solargraph 0.58.2 → 0.59.0.dev.2
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/.envrc +3 -0
- data/.github/workflows/linting.yml +4 -5
- data/.github/workflows/plugins.yml +41 -34
- data/.github/workflows/rspec.yml +44 -23
- data/.github/workflows/typecheck.yml +2 -2
- data/.rubocop.yml +32 -5
- data/.rubocop_todo.yml +50 -966
- data/Gemfile +3 -1
- data/README.md +3 -3
- data/Rakefile +26 -23
- data/bin/solargraph +2 -1
- data/lib/solargraph/api_map/cache.rb +3 -3
- data/lib/solargraph/api_map/constants.rb +13 -3
- data/lib/solargraph/api_map/index.rb +23 -18
- data/lib/solargraph/api_map/source_to_yard.rb +22 -9
- data/lib/solargraph/api_map/store.rb +33 -28
- data/lib/solargraph/api_map.rb +150 -82
- data/lib/solargraph/bench.rb +44 -45
- data/lib/solargraph/complex_type/conformance.rb +176 -0
- data/lib/solargraph/complex_type/type_methods.rb +28 -17
- data/lib/solargraph/complex_type/unique_type.rb +218 -57
- data/lib/solargraph/complex_type.rb +170 -57
- data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -61
- data/lib/solargraph/convention/data_definition/data_definition_node.rb +7 -5
- data/lib/solargraph/convention/data_definition.rb +5 -2
- data/lib/solargraph/convention/gemfile.rb +15 -15
- data/lib/solargraph/convention/gemspec.rb +23 -23
- data/lib/solargraph/convention/rakefile.rb +17 -17
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +2 -1
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +4 -3
- data/lib/solargraph/convention/struct_definition.rb +8 -4
- data/lib/solargraph/convention.rb +78 -78
- data/lib/solargraph/converters/dd.rb +19 -17
- data/lib/solargraph/converters/dl.rb +17 -15
- data/lib/solargraph/converters/dt.rb +17 -15
- data/lib/solargraph/converters/misc.rb +3 -1
- data/lib/solargraph/diagnostics/require_not_found.rb +1 -0
- data/lib/solargraph/diagnostics/rubocop.rb +11 -10
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
- data/lib/solargraph/diagnostics/type_check.rb +11 -10
- data/lib/solargraph/diagnostics/update_errors.rb +37 -41
- data/lib/solargraph/doc_map.rb +133 -373
- data/lib/solargraph/equality.rb +4 -4
- data/lib/solargraph/gem_pins.rb +21 -20
- data/lib/solargraph/language_server/error_codes.rb +20 -20
- data/lib/solargraph/language_server/host/diagnoser.rb +1 -1
- data/lib/solargraph/language_server/host/dispatch.rb +3 -3
- data/lib/solargraph/language_server/host/message_worker.rb +4 -3
- data/lib/solargraph/language_server/host/sources.rb +2 -1
- data/lib/solargraph/language_server/host.rb +30 -22
- data/lib/solargraph/language_server/message/base.rb +97 -97
- data/lib/solargraph/language_server/message/client/register_capability.rb +13 -15
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +58 -60
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +12 -18
- data/lib/solargraph/language_server/message/extended/document.rb +1 -0
- data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -32
- data/lib/solargraph/language_server/message/extended/download_core.rb +20 -19
- data/lib/solargraph/language_server/message/extended/search.rb +20 -20
- data/lib/solargraph/language_server/message/initialize.rb +197 -191
- data/lib/solargraph/language_server/message/text_document/completion.rb +10 -8
- data/lib/solargraph/language_server/message/text_document/definition.rb +41 -32
- data/lib/solargraph/language_server/message/text_document/document_highlight.rb +23 -16
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +29 -19
- data/lib/solargraph/language_server/message/text_document/formatting.rb +8 -6
- data/lib/solargraph/language_server/message/text_document/hover.rb +5 -5
- data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +18 -11
- data/lib/solargraph/language_server/message/text_document/references.rb +23 -16
- data/lib/solargraph/language_server/message/text_document/rename.rb +26 -19
- data/lib/solargraph/language_server/message/text_document/signature_help.rb +3 -2
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +25 -17
- data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +41 -35
- data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +48 -40
- data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +32 -26
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +27 -17
- data/lib/solargraph/language_server/message.rb +94 -94
- data/lib/solargraph/language_server/request.rb +29 -27
- data/lib/solargraph/language_server/transport/data_reader.rb +72 -74
- data/lib/solargraph/language_server/uri_helpers.rb +49 -49
- data/lib/solargraph/library.rb +85 -44
- data/lib/solargraph/location.rb +17 -14
- data/lib/solargraph/logging.rb +24 -4
- data/lib/solargraph/page.rb +92 -92
- data/lib/solargraph/parser/comment_ripper.rb +19 -4
- data/lib/solargraph/parser/flow_sensitive_typing.rb +326 -108
- data/lib/solargraph/parser/node_processor/base.rb +34 -4
- data/lib/solargraph/parser/node_processor.rb +8 -7
- data/lib/solargraph/parser/parser_gem/class_methods.rb +32 -14
- data/lib/solargraph/parser/parser_gem/flawed_builder.rb +19 -19
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +50 -25
- data/lib/solargraph/parser/parser_gem/node_methods.rb +91 -70
- data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +4 -4
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +13 -11
- data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +9 -0
- data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +12 -12
- data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +10 -3
- data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +38 -37
- data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +36 -6
- data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +5 -3
- data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -1
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +3 -3
- data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
- data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +4 -5
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +124 -113
- data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -29
- data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
- data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +6 -2
- data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
- data/lib/solargraph/parser/parser_gem.rb +14 -12
- data/lib/solargraph/parser/region.rb +9 -3
- data/lib/solargraph/parser/snippet.rb +3 -1
- data/lib/solargraph/parser.rb +25 -23
- data/lib/solargraph/pin/base.rb +126 -80
- data/lib/solargraph/pin/base_variable.rb +273 -24
- data/lib/solargraph/pin/block.rb +29 -6
- data/lib/solargraph/pin/breakable.rb +7 -1
- data/lib/solargraph/pin/callable.rb +65 -21
- data/lib/solargraph/pin/closure.rb +7 -10
- data/lib/solargraph/pin/common.rb +24 -6
- data/lib/solargraph/pin/compound_statement.rb +55 -0
- data/lib/solargraph/pin/constant.rb +43 -45
- data/lib/solargraph/pin/conversions.rb +10 -4
- data/lib/solargraph/pin/delegated_method.rb +19 -8
- data/lib/solargraph/pin/documenting.rb +4 -2
- data/lib/solargraph/pin/instance_variable.rb +5 -1
- data/lib/solargraph/pin/keyword.rb +0 -4
- data/lib/solargraph/pin/local_variable.rb +15 -59
- data/lib/solargraph/pin/method.rb +153 -104
- data/lib/solargraph/pin/method_alias.rb +8 -0
- data/lib/solargraph/pin/namespace.rb +19 -12
- data/lib/solargraph/pin/parameter.rb +100 -36
- data/lib/solargraph/pin/proxy_type.rb +4 -1
- data/lib/solargraph/pin/reference/override.rb +1 -1
- data/lib/solargraph/pin/reference/superclass.rb +2 -0
- data/lib/solargraph/pin/reference.rb +19 -0
- data/lib/solargraph/pin/search.rb +3 -2
- data/lib/solargraph/pin/signature.rb +15 -12
- data/lib/solargraph/pin/symbol.rb +2 -1
- data/lib/solargraph/pin/until.rb +2 -4
- data/lib/solargraph/pin/while.rb +2 -4
- data/lib/solargraph/pin.rb +2 -0
- data/lib/solargraph/pin_cache.rb +490 -73
- data/lib/solargraph/position.rb +14 -10
- data/lib/solargraph/range.rb +16 -15
- data/lib/solargraph/rbs_map/conversions.rb +343 -214
- data/lib/solargraph/rbs_map/core_fills.rb +91 -84
- data/lib/solargraph/rbs_map/core_map.rb +24 -17
- data/lib/solargraph/rbs_map/stdlib_map.rb +33 -5
- data/lib/solargraph/rbs_map.rb +77 -32
- data/lib/solargraph/server_methods.rb +16 -16
- data/lib/solargraph/shell.rb +128 -73
- data/lib/solargraph/source/chain/array.rb +39 -37
- data/lib/solargraph/source/chain/call.rb +96 -56
- data/lib/solargraph/source/chain/class_variable.rb +13 -13
- data/lib/solargraph/source/chain/constant.rb +5 -1
- data/lib/solargraph/source/chain/global_variable.rb +13 -13
- data/lib/solargraph/source/chain/hash.rb +8 -5
- data/lib/solargraph/source/chain/if.rb +12 -10
- data/lib/solargraph/source/chain/instance_variable.rb +24 -1
- data/lib/solargraph/source/chain/link.rb +99 -109
- data/lib/solargraph/source/chain/literal.rb +9 -6
- data/lib/solargraph/source/chain/or.rb +10 -4
- data/lib/solargraph/source/chain/q_call.rb +13 -11
- data/lib/solargraph/source/chain/variable.rb +15 -13
- data/lib/solargraph/source/chain/z_super.rb +28 -30
- data/lib/solargraph/source/chain.rb +49 -38
- data/lib/solargraph/source/change.rb +12 -5
- data/lib/solargraph/source/cursor.rb +23 -17
- data/lib/solargraph/source/encoding_fixes.rb +6 -7
- data/lib/solargraph/source/source_chainer.rb +56 -32
- data/lib/solargraph/source/updater.rb +5 -1
- data/lib/solargraph/source.rb +59 -35
- data/lib/solargraph/source_map/clip.rb +48 -29
- data/lib/solargraph/source_map/data.rb +4 -1
- data/lib/solargraph/source_map/mapper.rb +71 -42
- data/lib/solargraph/source_map.rb +21 -9
- data/lib/solargraph/type_checker/problem.rb +3 -1
- data/lib/solargraph/type_checker/rules.rb +81 -8
- data/lib/solargraph/type_checker.rb +195 -120
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +13 -10
- data/lib/solargraph/workspace/gemspecs.rb +367 -0
- data/lib/solargraph/workspace/require_paths.rb +1 -0
- data/lib/solargraph/workspace.rb +149 -30
- data/lib/solargraph/yard_map/helpers.rb +8 -3
- data/lib/solargraph/yard_map/mapper/to_method.rb +13 -7
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +2 -1
- data/lib/solargraph/yard_map/mapper.rb +13 -8
- data/lib/solargraph/yard_tags.rb +20 -20
- data/lib/solargraph/yardoc.rb +33 -23
- data/lib/solargraph.rb +29 -8
- data/rbs/fills/rubygems/0/dependency.rbs +193 -0
- data/rbs/fills/tuple/tuple.rbs +28 -0
- data/rbs/shims/ast/0/node.rbs +1 -1
- data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
- data/solargraph.gemspec +36 -34
- metadata +38 -33
- data/lib/solargraph/type_checker/checks.rb +0 -124
- data/lib/solargraph/type_checker/param_def.rb +0 -37
- data/lib/solargraph/yard_map/to_method.rb +0 -89
|
@@ -1,41 +1,37 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Solargraph
|
|
4
|
-
module Diagnostics
|
|
5
|
-
class UpdateErrors < Base
|
|
6
|
-
def diagnose source, api_map
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
#
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
module Diagnostics
|
|
5
|
+
class UpdateErrors < Base
|
|
6
|
+
def diagnose source, api_map
|
|
7
|
+
combine_ranges(source.code, source.error_ranges).map do |range|
|
|
8
|
+
{ range: range.to_hash,
|
|
9
|
+
severity: Diagnostics::Severities::ERROR,
|
|
10
|
+
source: 'Solargraph',
|
|
11
|
+
message: 'Syntax error' }
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
# Combine an array of ranges by their starting lines.
|
|
18
|
+
#
|
|
19
|
+
# @param code [String]
|
|
20
|
+
# @param ranges [Array<Range>]
|
|
21
|
+
# @return [Array<Range>]
|
|
22
|
+
def combine_ranges code, ranges
|
|
23
|
+
result = []
|
|
24
|
+
lines = []
|
|
25
|
+
ranges.sort { |a, b| a.start.line <=> b.start.line }.each do |rng|
|
|
26
|
+
next if rng.nil? || lines.include?(rng.start.line)
|
|
27
|
+
lines.push rng.start.line
|
|
28
|
+
next if rng.start.line >= code.lines.length
|
|
29
|
+
scol = code.lines[rng.start.line].index(/[^\s]/) || 0
|
|
30
|
+
ecol = code.lines[rng.start.line].length
|
|
31
|
+
result.push Range.from_to(rng.start.line, scol, rng.start.line, ecol)
|
|
32
|
+
end
|
|
33
|
+
result
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
data/lib/solargraph/doc_map.rb
CHANGED
|
@@ -5,122 +5,86 @@ require 'benchmark'
|
|
|
5
5
|
require 'open3'
|
|
6
6
|
|
|
7
7
|
module Solargraph
|
|
8
|
-
# A collection of pins generated from
|
|
8
|
+
# A collection of pins generated from specific 'require' statements
|
|
9
|
+
# in code. Multiple can be created per workspace, to represent the
|
|
10
|
+
# pins available in different files based on their particular
|
|
11
|
+
# 'require' lines.
|
|
9
12
|
#
|
|
10
13
|
class DocMap
|
|
11
14
|
include Logging
|
|
12
15
|
|
|
13
|
-
# @return [
|
|
14
|
-
attr_reader :requires
|
|
15
|
-
alias required requires
|
|
16
|
-
|
|
17
|
-
# @return [Array<Gem::Specification>]
|
|
18
|
-
attr_reader :preferences
|
|
19
|
-
|
|
20
|
-
# @return [Array<Pin::Base>]
|
|
21
|
-
attr_reader :pins
|
|
22
|
-
|
|
23
|
-
# @return [Array<Gem::Specification>]
|
|
24
|
-
def uncached_gemspecs
|
|
25
|
-
uncached_yard_gemspecs.concat(uncached_rbs_collection_gemspecs)
|
|
26
|
-
.sort
|
|
27
|
-
.uniq { |gemspec| "#{gemspec.name}:#{gemspec.version}" }
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
# @return [Array<Gem::Specification>]
|
|
31
|
-
attr_reader :uncached_yard_gemspecs
|
|
32
|
-
|
|
33
|
-
# @return [Array<Gem::Specification>]
|
|
34
|
-
attr_reader :uncached_rbs_collection_gemspecs
|
|
35
|
-
|
|
36
|
-
# @return [String, nil]
|
|
37
|
-
attr_reader :rbs_collection_path
|
|
38
|
-
|
|
39
|
-
# @return [String, nil]
|
|
40
|
-
attr_reader :rbs_collection_config_path
|
|
41
|
-
|
|
42
|
-
# @return [Workspace, nil]
|
|
16
|
+
# @return [Workspace]
|
|
43
17
|
attr_reader :workspace
|
|
44
18
|
|
|
45
19
|
# @return [Environ]
|
|
46
20
|
attr_reader :environ
|
|
47
21
|
|
|
48
22
|
# @param requires [Array<String>]
|
|
49
|
-
# @param preferences [Array<Gem::Specification>]
|
|
50
23
|
# @param workspace [Workspace, nil]
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
@
|
|
24
|
+
# @param out [IO, nil] output stream for logging
|
|
25
|
+
def initialize requires, workspace, out: $stderr
|
|
26
|
+
@provided_requires = requires.compact
|
|
54
27
|
@workspace = workspace
|
|
55
|
-
@
|
|
56
|
-
@rbs_collection_config_path = workspace&.rbs_collection_config_path
|
|
57
|
-
@environ = Convention.for_global(self)
|
|
58
|
-
@requires.concat @environ.requires if @environ
|
|
59
|
-
load_serialized_gem_pins
|
|
60
|
-
pins.concat @environ.pins
|
|
28
|
+
@out = out
|
|
61
29
|
end
|
|
62
30
|
|
|
63
|
-
# @
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
cache(gemspec, out: out)
|
|
31
|
+
# @return [Array<String>]
|
|
32
|
+
def requires
|
|
33
|
+
@requires ||= @provided_requires + (workspace.global_environ&.requires || [])
|
|
34
|
+
end
|
|
35
|
+
alias required requires
|
|
36
|
+
|
|
37
|
+
# @sg-ignore flow sensitive typing needs to understand reassignment
|
|
38
|
+
# @return [Array<Gem::Specification>]
|
|
39
|
+
def uncached_gemspecs
|
|
40
|
+
if @uncached_gemspecs.nil?
|
|
41
|
+
@uncached_gemspecs = []
|
|
42
|
+
pins # force lazy-loaded pin lookup
|
|
76
43
|
end
|
|
77
|
-
|
|
78
|
-
@uncached_rbs_collection_gemspecs = []
|
|
79
|
-
@uncached_yard_gemspecs = []
|
|
44
|
+
@uncached_gemspecs
|
|
80
45
|
end
|
|
81
46
|
|
|
82
|
-
# @
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
def cache_yard_pins(gemspec, out)
|
|
86
|
-
pins = GemPins.build_yard_pins(yard_plugins, gemspec)
|
|
87
|
-
PinCache.serialize_yard_gem(gemspec, pins)
|
|
88
|
-
logger.info { "Cached #{pins.length} YARD pins for gem #{gemspec.name}:#{gemspec.version}" } unless pins.empty?
|
|
47
|
+
# @return [Array<Pin::Base>]
|
|
48
|
+
def pins
|
|
49
|
+
@pins ||= load_serialized_gem_pins + (workspace.global_environ&.pins || [])
|
|
89
50
|
end
|
|
90
51
|
|
|
91
|
-
# @param gemspec [Gem::Specification]
|
|
92
|
-
# @param out [IO]
|
|
93
52
|
# @return [void]
|
|
94
|
-
def
|
|
95
|
-
|
|
96
|
-
pins =
|
|
97
|
-
rbs_version_cache_key = rbs_map.cache_key
|
|
98
|
-
# cache pins even if result is zero, so we don't retry building pins
|
|
99
|
-
pins ||= []
|
|
100
|
-
PinCache.serialize_rbs_collection_gem(gemspec, rbs_version_cache_key, pins)
|
|
101
|
-
logger.info { "Cached #{pins.length} RBS collection pins for gem #{gemspec.name} #{gemspec.version} with cache_key #{rbs_version_cache_key.inspect}" unless pins.empty? }
|
|
53
|
+
def reset_pins!
|
|
54
|
+
@uncached_gemspecs = nil
|
|
55
|
+
@pins = nil
|
|
102
56
|
end
|
|
103
57
|
|
|
104
|
-
# @
|
|
58
|
+
# @return [Solargraph::PinCache]
|
|
59
|
+
def pin_cache
|
|
60
|
+
@pin_cache ||= workspace.fresh_pincache
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def any_uncached?
|
|
64
|
+
uncached_gemspecs.any?
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Cache all pins needed for the sources in this doc_map
|
|
68
|
+
# @param out [StringIO, IO, nil] output stream for logging
|
|
105
69
|
# @param rebuild [Boolean] whether to rebuild the pins even if they are cached
|
|
106
|
-
# @param out [IO, nil] output stream for logging
|
|
107
70
|
# @return [void]
|
|
108
|
-
def
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
type << 'RBS collection' if build_rbs_collection
|
|
115
|
-
out.puts("Caching #{type.join(' and ')} pins for gem #{gemspec.name}:#{gemspec.version}") if out
|
|
71
|
+
def cache_doc_map_gems! out, rebuild: false
|
|
72
|
+
unless uncached_gemspecs.empty?
|
|
73
|
+
logger.info do
|
|
74
|
+
gem_desc = uncached_gemspecs.map { |gemspec| "#{gemspec.name}:#{gemspec.version}" }.join(', ')
|
|
75
|
+
"Caching pins for gems: #{gem_desc}"
|
|
76
|
+
end
|
|
116
77
|
end
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
78
|
+
time = Benchmark.measure do
|
|
79
|
+
uncached_gemspecs.each do |gemspec|
|
|
80
|
+
cache(gemspec, rebuild: rebuild, out: out)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
milliseconds = (time.real * 1000).round
|
|
84
|
+
if (milliseconds > 500) && uncached_gemspecs.any? && out && uncached_gemspecs.any?
|
|
85
|
+
out.puts "Built #{uncached_gemspecs.length} gems in #{milliseconds} ms"
|
|
86
|
+
end
|
|
87
|
+
reset_pins!
|
|
124
88
|
end
|
|
125
89
|
|
|
126
90
|
# @return [Array<String>]
|
|
@@ -128,312 +92,108 @@ module Solargraph
|
|
|
128
92
|
@unresolved_requires ||= required_gems_map.select { |_, gemspecs| gemspecs.nil? }.keys
|
|
129
93
|
end
|
|
130
94
|
|
|
131
|
-
# @return [
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
# @return [Hash{Array(String, String) => Array<Pin::Base>}] Indexed by gemspec name and version
|
|
147
|
-
def rbs_collection_pins_in_memory
|
|
148
|
-
self.class.all_rbs_collection_gems_in_memory[rbs_collection_path] ||= {}
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
# @return [Hash{Array(String, String) => Array<Pin::Base>}] Indexed by gemspec name and version
|
|
152
|
-
def self.all_combined_pins_in_memory
|
|
153
|
-
@combined_pins_in_memory ||= {}
|
|
95
|
+
# @return [Array<Gem::Specification>]
|
|
96
|
+
# @param out [IO, nil]
|
|
97
|
+
def dependencies out: $stderr
|
|
98
|
+
@dependencies ||=
|
|
99
|
+
begin
|
|
100
|
+
gem_deps = gemspecs
|
|
101
|
+
.flat_map { |spec| workspace.fetch_dependencies(spec, out: out) }
|
|
102
|
+
.uniq(&:name)
|
|
103
|
+
stdlib_deps = gemspecs
|
|
104
|
+
.flat_map { |spec| workspace.stdlib_dependencies(spec.name) }
|
|
105
|
+
.flat_map { |dep_name| workspace.resolve_require(dep_name) }
|
|
106
|
+
.compact
|
|
107
|
+
existing_gems = gemspecs.map(&:name)
|
|
108
|
+
(gem_deps + stdlib_deps).reject { |gemspec| existing_gems.include? gemspec.name }
|
|
109
|
+
end
|
|
154
110
|
end
|
|
155
111
|
|
|
156
|
-
#
|
|
157
|
-
#
|
|
158
|
-
|
|
159
|
-
|
|
112
|
+
# Cache gem documentation if needed for this doc_map
|
|
113
|
+
#
|
|
114
|
+
# @param gemspec [Gem::Specification]
|
|
115
|
+
# @param rebuild [Boolean] whether to rebuild the pins even if they are cached
|
|
116
|
+
# @param out [StringIO, IO, nil] output stream for logging
|
|
117
|
+
#
|
|
118
|
+
# @return [void]
|
|
119
|
+
def cache gemspec, rebuild: false, out: nil
|
|
120
|
+
pin_cache.cache_gem(gemspec: gemspec,
|
|
121
|
+
rebuild: rebuild,
|
|
122
|
+
out: out)
|
|
160
123
|
end
|
|
161
124
|
|
|
162
|
-
|
|
163
|
-
def yard_plugins
|
|
164
|
-
@environ.yard_plugins
|
|
165
|
-
end
|
|
125
|
+
private
|
|
166
126
|
|
|
167
|
-
# @return [
|
|
168
|
-
def
|
|
169
|
-
@
|
|
127
|
+
# @return [Array<Gem::Specification>]
|
|
128
|
+
def gemspecs
|
|
129
|
+
@gemspecs ||= required_gems_map.values.compact.flatten
|
|
170
130
|
end
|
|
171
131
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
@pins = []
|
|
177
|
-
@uncached_yard_gemspecs = []
|
|
178
|
-
@uncached_rbs_collection_gemspecs = []
|
|
132
|
+
# @param out [IO, nil]
|
|
133
|
+
# @return [Array<Pin::Base>]
|
|
134
|
+
def load_serialized_gem_pins out: @out
|
|
135
|
+
serialized_pins = []
|
|
179
136
|
with_gemspecs, without_gemspecs = required_gems_map.partition { |_, v| v }
|
|
180
|
-
# @sg-ignore Need support for RBS duck interfaces like _ToHash
|
|
181
137
|
# @type [Array<String>]
|
|
182
|
-
|
|
183
|
-
# @sg-ignore Need support for RBS duck interfaces like _ToHash
|
|
138
|
+
missing_paths = without_gemspecs.to_h.keys
|
|
184
139
|
# @type [Array<Gem::Specification>]
|
|
185
|
-
gemspecs =
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
140
|
+
gemspecs = with_gemspecs.to_h.values.flatten.compact + dependencies(out: out).to_a
|
|
141
|
+
|
|
142
|
+
# if we are type checking a gem project, we should not include
|
|
143
|
+
# pins from rbs or yard from that gem here - we use our own
|
|
144
|
+
# parser for those pins
|
|
145
|
+
|
|
146
|
+
# @param gemspec [Gem::Specification, Bundler::LazySpecification, Bundler::StubSpecification]
|
|
147
|
+
gemspecs.reject! do |gemspec|
|
|
148
|
+
gemspec.respond_to?(:source) &&
|
|
149
|
+
gemspec.source.instance_of?(Bundler::Source::Gemspec) &&
|
|
150
|
+
gemspec.source.respond_to?(:path) &&
|
|
151
|
+
gemspec.source.path == Pathname.new('.')
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
missing_paths.each do |path|
|
|
155
|
+
# this will load from disk if needed; no need to manage
|
|
156
|
+
# uncached_gemspecs to trigger that later
|
|
157
|
+
stdlib_name_guess = path.split('/').first
|
|
158
|
+
|
|
159
|
+
# try to resolve the stdlib name
|
|
160
|
+
# @type [Array<String>]
|
|
161
|
+
deps = workspace.stdlib_dependencies(stdlib_name_guess) || []
|
|
162
|
+
[stdlib_name_guess, *deps].compact.each do |potential_stdlib_name|
|
|
163
|
+
# @sg-ignore Need to support splatting in literal array
|
|
164
|
+
rbs_pins = pin_cache.cache_stdlib_rbs_map potential_stdlib_name
|
|
165
|
+
serialized_pins.concat rbs_pins if rbs_pins
|
|
166
|
+
end
|
|
189
167
|
end
|
|
190
168
|
|
|
191
|
-
|
|
169
|
+
serialized_pins.length
|
|
192
170
|
time = Benchmark.measure do
|
|
193
171
|
gemspecs.each do |gemspec|
|
|
194
|
-
|
|
195
|
-
|
|
172
|
+
# only deserializes already-cached gems
|
|
173
|
+
gemspec_pins = pin_cache.deserialize_combined_pin_cache gemspec
|
|
174
|
+
if gemspec_pins
|
|
175
|
+
serialized_pins.concat gemspec_pins
|
|
176
|
+
else
|
|
177
|
+
uncached_gemspecs << gemspec
|
|
178
|
+
end
|
|
196
179
|
end
|
|
197
180
|
end
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
181
|
+
serialized_pins.length
|
|
182
|
+
milliseconds = (time.real * 1000).round
|
|
183
|
+
if (milliseconds > 500) && out && gemspecs.any?
|
|
184
|
+
out.puts "Deserialized #{serialized_pins.length} gem pins from #{PinCache.base_dir} in #{milliseconds} ms"
|
|
185
|
+
end
|
|
186
|
+
uncached_gemspecs.uniq! { |gemspec| "#{gemspec.name}:#{gemspec.version}" }
|
|
187
|
+
serialized_pins
|
|
202
188
|
end
|
|
203
189
|
|
|
204
190
|
# @return [Hash{String => Array<Gem::Specification>}]
|
|
205
191
|
def required_gems_map
|
|
206
|
-
@required_gems_map ||= requires.to_h { |path| [path,
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
# @return [Hash{String => Gem::Specification}]
|
|
210
|
-
def preference_map
|
|
211
|
-
@preference_map ||= preferences.to_h { |gemspec| [gemspec.name, gemspec] }
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
# @param gemspec [Gem::Specification]
|
|
215
|
-
# @return [Array<Pin::Base>, nil]
|
|
216
|
-
def deserialize_yard_pin_cache gemspec
|
|
217
|
-
if yard_pins_in_memory.key?([gemspec.name, gemspec.version])
|
|
218
|
-
return yard_pins_in_memory[[gemspec.name, gemspec.version]]
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
cached = PinCache.deserialize_yard_gem(gemspec)
|
|
222
|
-
if cached
|
|
223
|
-
logger.info { "Loaded #{cached.length} cached YARD pins from #{gemspec.name}:#{gemspec.version}" }
|
|
224
|
-
yard_pins_in_memory[[gemspec.name, gemspec.version]] = cached
|
|
225
|
-
cached
|
|
226
|
-
else
|
|
227
|
-
logger.debug "No YARD pin cache for #{gemspec.name}:#{gemspec.version}"
|
|
228
|
-
@uncached_yard_gemspecs.push gemspec
|
|
229
|
-
nil
|
|
230
|
-
end
|
|
231
|
-
end
|
|
232
|
-
|
|
233
|
-
# @param gemspec [Gem::Specification]
|
|
234
|
-
# @return [void]
|
|
235
|
-
def deserialize_combined_pin_cache(gemspec)
|
|
236
|
-
unless combined_pins_in_memory[[gemspec.name, gemspec.version]].nil?
|
|
237
|
-
return combined_pins_in_memory[[gemspec.name, gemspec.version]]
|
|
238
|
-
end
|
|
239
|
-
|
|
240
|
-
rbs_map = RbsMap.from_gemspec(gemspec, rbs_collection_path, rbs_collection_config_path)
|
|
241
|
-
rbs_version_cache_key = rbs_map.cache_key
|
|
242
|
-
|
|
243
|
-
cached = PinCache.deserialize_combined_gem(gemspec, rbs_version_cache_key)
|
|
244
|
-
if cached
|
|
245
|
-
logger.info { "Loaded #{cached.length} cached YARD pins from #{gemspec.name}:#{gemspec.version}" }
|
|
246
|
-
combined_pins_in_memory[[gemspec.name, gemspec.version]] = cached
|
|
247
|
-
return combined_pins_in_memory[[gemspec.name, gemspec.version]]
|
|
248
|
-
end
|
|
249
|
-
|
|
250
|
-
rbs_collection_pins = deserialize_rbs_collection_cache gemspec, rbs_version_cache_key
|
|
251
|
-
|
|
252
|
-
yard_pins = deserialize_yard_pin_cache gemspec
|
|
253
|
-
|
|
254
|
-
if !rbs_collection_pins.nil? && !yard_pins.nil?
|
|
255
|
-
logger.debug { "Combining pins for #{gemspec.name}:#{gemspec.version}" }
|
|
256
|
-
combined_pins = GemPins.combine(yard_pins, rbs_collection_pins)
|
|
257
|
-
PinCache.serialize_combined_gem(gemspec, rbs_version_cache_key, combined_pins)
|
|
258
|
-
combined_pins_in_memory[[gemspec.name, gemspec.version]] = combined_pins
|
|
259
|
-
logger.info { "Generated #{combined_pins_in_memory[[gemspec.name, gemspec.version]].length} combined pins for #{gemspec.name} #{gemspec.version}" }
|
|
260
|
-
return combined_pins
|
|
261
|
-
end
|
|
262
|
-
|
|
263
|
-
if !yard_pins.nil?
|
|
264
|
-
logger.debug { "Using only YARD pins for #{gemspec.name}:#{gemspec.version}" }
|
|
265
|
-
combined_pins_in_memory[[gemspec.name, gemspec.version]] = yard_pins
|
|
266
|
-
return combined_pins_in_memory[[gemspec.name, gemspec.version]]
|
|
267
|
-
elsif !rbs_collection_pins.nil?
|
|
268
|
-
logger.debug { "Using only RBS collection pins for #{gemspec.name}:#{gemspec.version}" }
|
|
269
|
-
combined_pins_in_memory[[gemspec.name, gemspec.version]] = rbs_collection_pins
|
|
270
|
-
return combined_pins_in_memory[[gemspec.name, gemspec.version]]
|
|
271
|
-
else
|
|
272
|
-
logger.debug { "Pins not yet cached for #{gemspec.name}:#{gemspec.version}" }
|
|
273
|
-
return nil
|
|
274
|
-
end
|
|
275
|
-
end
|
|
276
|
-
|
|
277
|
-
# @param path [String] require path that might be in the RBS stdlib collection
|
|
278
|
-
# @return [void]
|
|
279
|
-
def deserialize_stdlib_rbs_map path
|
|
280
|
-
map = RbsMap::StdlibMap.load(path)
|
|
281
|
-
if map.resolved?
|
|
282
|
-
logger.debug { "Loading stdlib pins for #{path}" }
|
|
283
|
-
@pins.concat map.pins
|
|
284
|
-
logger.debug { "Loaded #{map.pins.length} stdlib pins for #{path}" }
|
|
285
|
-
map.pins
|
|
286
|
-
else
|
|
287
|
-
# @todo Temporarily ignoring unresolved `require 'set'`
|
|
288
|
-
logger.debug { "Require path #{path} could not be resolved in RBS" } unless path == 'set'
|
|
289
|
-
nil
|
|
290
|
-
end
|
|
291
|
-
end
|
|
292
|
-
|
|
293
|
-
# @param gemspec [Gem::Specification]
|
|
294
|
-
# @param rbs_version_cache_key [String]
|
|
295
|
-
# @return [Array<Pin::Base>, nil]
|
|
296
|
-
def deserialize_rbs_collection_cache gemspec, rbs_version_cache_key
|
|
297
|
-
return if rbs_collection_pins_in_memory.key?([gemspec, rbs_version_cache_key])
|
|
298
|
-
cached = PinCache.deserialize_rbs_collection_gem(gemspec, rbs_version_cache_key)
|
|
299
|
-
if cached
|
|
300
|
-
logger.info { "Loaded #{cached.length} pins from RBS collection cache for #{gemspec.name}:#{gemspec.version}" } unless cached.empty?
|
|
301
|
-
rbs_collection_pins_in_memory[[gemspec, rbs_version_cache_key]] = cached
|
|
302
|
-
cached
|
|
303
|
-
else
|
|
304
|
-
logger.debug "No RBS collection pin cache for #{gemspec.name} #{gemspec.version}"
|
|
305
|
-
@uncached_rbs_collection_gemspecs.push gemspec
|
|
306
|
-
nil
|
|
307
|
-
end
|
|
308
|
-
end
|
|
309
|
-
|
|
310
|
-
# @param path [String]
|
|
311
|
-
# @return [::Array<Gem::Specification>, nil]
|
|
312
|
-
def resolve_path_to_gemspecs path
|
|
313
|
-
return nil if path.empty?
|
|
314
|
-
return gemspecs_required_from_bundler if path == 'bundler/require'
|
|
315
|
-
|
|
316
|
-
# @type [Gem::Specification, nil]
|
|
317
|
-
gemspec = Gem::Specification.find_by_path(path)
|
|
318
|
-
if gemspec.nil?
|
|
319
|
-
gem_name_guess = path.split('/').first
|
|
320
|
-
begin
|
|
321
|
-
# this can happen when the gem is included via a local path in
|
|
322
|
-
# a Gemfile; Gem doesn't try to index the paths in that case.
|
|
323
|
-
#
|
|
324
|
-
# See if we can make a good guess:
|
|
325
|
-
potential_gemspec = Gem::Specification.find_by_name(gem_name_guess)
|
|
326
|
-
file = "lib/#{path}.rb"
|
|
327
|
-
gemspec = potential_gemspec if potential_gemspec.files.any? { |gemspec_file| file == gemspec_file }
|
|
328
|
-
rescue Gem::MissingSpecError
|
|
329
|
-
logger.debug { "Require path #{path} could not be resolved to a gem via find_by_path or guess of #{gem_name_guess}" }
|
|
330
|
-
[]
|
|
331
|
-
end
|
|
332
|
-
end
|
|
333
|
-
return nil if gemspec.nil?
|
|
334
|
-
[gemspec_or_preference(gemspec)]
|
|
192
|
+
@required_gems_map ||= requires.to_h { |path| [path, workspace.resolve_require(path)] }
|
|
335
193
|
end
|
|
336
194
|
|
|
337
|
-
# @param gemspec [Gem::Specification]
|
|
338
|
-
# @return [Gem::Specification]
|
|
339
|
-
def gemspec_or_preference gemspec
|
|
340
|
-
# :nocov: dormant feature
|
|
341
|
-
return gemspec unless preference_map.key?(gemspec.name)
|
|
342
|
-
return gemspec if gemspec.version == preference_map[gemspec.name].version
|
|
343
|
-
|
|
344
|
-
change_gemspec_version gemspec, preference_map[gemspec.name].version
|
|
345
|
-
# :nocov:
|
|
346
|
-
end
|
|
347
|
-
|
|
348
|
-
# @param gemspec [Gem::Specification]
|
|
349
|
-
# @param version [Gem::Version]
|
|
350
|
-
# @return [Gem::Specification]
|
|
351
|
-
def change_gemspec_version gemspec, version
|
|
352
|
-
Gem::Specification.find_by_name(gemspec.name, "= #{version}")
|
|
353
|
-
rescue Gem::MissingSpecError
|
|
354
|
-
Solargraph.logger.info "Gem #{gemspec.name} version #{version} not found. Using #{gemspec.version} instead"
|
|
355
|
-
gemspec
|
|
356
|
-
end
|
|
357
|
-
|
|
358
|
-
# @param gemspec [Gem::Specification]
|
|
359
|
-
# @return [Array<Gem::Specification>]
|
|
360
|
-
def fetch_dependencies gemspec
|
|
361
|
-
# @param spec [Gem::Dependency]
|
|
362
|
-
# @param deps [Set<Gem::Specification>]
|
|
363
|
-
only_runtime_dependencies(gemspec).each_with_object(Set.new) do |spec, deps|
|
|
364
|
-
Solargraph.logger.info "Adding #{spec.name} dependency for #{gemspec.name}"
|
|
365
|
-
dep = Gem.loaded_specs[spec.name]
|
|
366
|
-
# @todo is next line necessary?
|
|
367
|
-
# @sg-ignore Unresolved call to requirement on Gem::Dependency
|
|
368
|
-
dep ||= Gem::Specification.find_by_name(spec.name, spec.requirement)
|
|
369
|
-
deps.merge fetch_dependencies(dep) if deps.add?(dep)
|
|
370
|
-
rescue Gem::MissingSpecError
|
|
371
|
-
# @sg-ignore Unresolved call to requirement on Gem::Dependency
|
|
372
|
-
Solargraph.logger.warn "Gem dependency #{spec.name} #{spec.requirement} for #{gemspec.name} not found in RubyGems."
|
|
373
|
-
end.to_a
|
|
374
|
-
end
|
|
375
|
-
|
|
376
|
-
# @param gemspec [Gem::Specification]
|
|
377
|
-
# @return [Array<Gem::Dependency>]
|
|
378
|
-
def only_runtime_dependencies gemspec
|
|
379
|
-
gemspec.dependencies - gemspec.development_dependencies
|
|
380
|
-
end
|
|
381
|
-
|
|
382
|
-
|
|
383
195
|
def inspect
|
|
384
196
|
self.class.inspect
|
|
385
197
|
end
|
|
386
|
-
|
|
387
|
-
# @return [Array<Gem::Specification>, nil]
|
|
388
|
-
def gemspecs_required_from_bundler
|
|
389
|
-
# @todo Handle projects with custom Bundler/Gemfile setups
|
|
390
|
-
return unless workspace.gemfile?
|
|
391
|
-
|
|
392
|
-
if workspace.gemfile? && Bundler.definition&.lockfile&.to_s&.start_with?(workspace.directory)
|
|
393
|
-
# Find only the gems bundler is now using
|
|
394
|
-
Bundler.definition.locked_gems.specs.flat_map do |lazy_spec|
|
|
395
|
-
logger.info "Handling #{lazy_spec.name}:#{lazy_spec.version}"
|
|
396
|
-
[Gem::Specification.find_by_name(lazy_spec.name, lazy_spec.version)]
|
|
397
|
-
rescue Gem::MissingSpecError => e
|
|
398
|
-
logger.info("Could not find #{lazy_spec.name}:#{lazy_spec.version} with find_by_name, falling back to guess")
|
|
399
|
-
# can happen in local filesystem references
|
|
400
|
-
specs = resolve_path_to_gemspecs lazy_spec.name
|
|
401
|
-
logger.warn "Gem #{lazy_spec.name} #{lazy_spec.version} from bundle not found: #{e}" if specs.nil?
|
|
402
|
-
next specs
|
|
403
|
-
end.compact
|
|
404
|
-
else
|
|
405
|
-
logger.info 'Fetching gemspecs required from Bundler (bundler/require)'
|
|
406
|
-
gemspecs_required_from_external_bundle
|
|
407
|
-
end
|
|
408
|
-
end
|
|
409
|
-
|
|
410
|
-
# @return [Array<Gem::Specification>, nil]
|
|
411
|
-
def gemspecs_required_from_external_bundle
|
|
412
|
-
logger.info 'Fetching gemspecs required from external bundle'
|
|
413
|
-
return [] unless workspace&.directory
|
|
414
|
-
|
|
415
|
-
Solargraph.with_clean_env do
|
|
416
|
-
cmd = [
|
|
417
|
-
'ruby', '-e',
|
|
418
|
-
"require 'bundler'; require 'json'; Dir.chdir('#{workspace&.directory}') { puts Bundler.definition.locked_gems.specs.map { |spec| [spec.name, spec.version] }.to_h.to_json }"
|
|
419
|
-
]
|
|
420
|
-
o, e, s = Open3.capture3(*cmd)
|
|
421
|
-
if s.success?
|
|
422
|
-
Solargraph.logger.debug "External bundle: #{o}"
|
|
423
|
-
hash = o && !o.empty? ? JSON.parse(o.split("\n").last) : {}
|
|
424
|
-
hash.flat_map do |name, version|
|
|
425
|
-
Gem::Specification.find_by_name(name, version)
|
|
426
|
-
rescue Gem::MissingSpecError => e
|
|
427
|
-
logger.info("Could not find #{name}:#{version} with find_by_name, falling back to guess")
|
|
428
|
-
# can happen in local filesystem references
|
|
429
|
-
specs = resolve_path_to_gemspecs name
|
|
430
|
-
logger.warn "Gem #{name} #{version} from bundle not found: #{e}" if specs.nil?
|
|
431
|
-
next specs
|
|
432
|
-
end.compact
|
|
433
|
-
else
|
|
434
|
-
Solargraph.logger.warn "Failed to load gems from bundle at #{workspace&.directory}: #{e}"
|
|
435
|
-
end
|
|
436
|
-
end
|
|
437
|
-
end
|
|
438
198
|
end
|
|
439
199
|
end
|
data/lib/solargraph/equality.rb
CHANGED
|
@@ -10,16 +10,16 @@ module Solargraph
|
|
|
10
10
|
|
|
11
11
|
# @param other [Object]
|
|
12
12
|
# @return [Boolean]
|
|
13
|
-
def eql?
|
|
13
|
+
def eql? other
|
|
14
14
|
self.class.eql?(other.class) &&
|
|
15
|
-
# @sg-ignore
|
|
15
|
+
# @sg-ignore flow sensitive typing should support .class == .class
|
|
16
16
|
equality_fields.eql?(other.equality_fields)
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
# @param other [Object]
|
|
20
20
|
# @return [Boolean]
|
|
21
|
-
def ==
|
|
22
|
-
|
|
21
|
+
def == other
|
|
22
|
+
eql?(other)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def hash
|