rbs 1.5.1 → 1.7.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +10 -0
- data/.github/workflows/ruby.yml +0 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +51 -0
- data/Gemfile +2 -0
- data/Rakefile +7 -22
- data/Steepfile +9 -1
- data/core/enumerator.rbs +1 -0
- data/core/io.rbs +3 -1
- data/core/kernel.rbs +4 -4
- data/core/trace_point.rbs +1 -1
- data/docs/collection.md +116 -0
- data/ext/rbs/extension/constants.c +140 -0
- data/ext/rbs/extension/constants.h +72 -0
- data/ext/rbs/extension/extconf.rb +3 -0
- data/ext/rbs/extension/lexer.c +1070 -0
- data/ext/rbs/extension/lexer.h +145 -0
- data/ext/rbs/extension/location.c +295 -0
- data/ext/rbs/extension/location.h +59 -0
- data/ext/rbs/extension/main.c +9 -0
- data/ext/rbs/extension/parser.c +2418 -0
- data/ext/rbs/extension/parser.h +23 -0
- data/ext/rbs/extension/parserstate.c +313 -0
- data/ext/rbs/extension/parserstate.h +141 -0
- data/ext/rbs/extension/rbs_extension.h +40 -0
- data/ext/rbs/extension/ruby_objs.c +585 -0
- data/ext/rbs/extension/ruby_objs.h +46 -0
- data/ext/rbs/extension/unescape.c +65 -0
- data/goodcheck.yml +1 -1
- data/lib/rbs/ast/comment.rb +0 -12
- data/lib/rbs/buffer.rb +4 -0
- data/lib/rbs/builtin_names.rb +1 -0
- data/lib/rbs/cli.rb +98 -10
- data/lib/rbs/collection/cleaner.rb +29 -0
- data/lib/rbs/collection/config/lockfile_generator.rb +95 -0
- data/lib/rbs/collection/config.rb +85 -0
- data/lib/rbs/collection/installer.rb +27 -0
- data/lib/rbs/collection/sources/git.rb +162 -0
- data/lib/rbs/collection/sources/rubygems.rb +40 -0
- data/lib/rbs/collection/sources/stdlib.rb +38 -0
- data/lib/rbs/collection/sources.rb +22 -0
- data/lib/rbs/collection.rb +13 -0
- data/lib/rbs/environment_loader.rb +12 -0
- data/lib/rbs/errors.rb +16 -1
- data/lib/rbs/location.rb +221 -217
- data/lib/rbs/location_aux.rb +108 -0
- data/lib/rbs/locator.rb +10 -7
- data/lib/rbs/parser_aux.rb +24 -0
- data/lib/rbs/repository.rb +13 -7
- data/lib/rbs/types.rb +2 -3
- data/lib/rbs/validator.rb +4 -1
- data/lib/rbs/version.rb +1 -1
- data/lib/rbs/writer.rb +4 -2
- data/lib/rbs.rb +4 -7
- data/rbs.gemspec +2 -1
- data/sig/ancestor_builder.rbs +2 -2
- data/sig/annotation.rbs +2 -2
- data/sig/builtin_names.rbs +1 -0
- data/sig/cli.rbs +5 -0
- data/sig/collection/cleaner.rbs +13 -0
- data/sig/collection/collections.rbs +112 -0
- data/sig/collection/config.rbs +69 -0
- data/sig/collection/installer.rbs +15 -0
- data/sig/collection.rbs +4 -0
- data/sig/comment.rbs +7 -7
- data/sig/constant_table.rbs +1 -1
- data/sig/declarations.rbs +9 -9
- data/sig/definition.rbs +1 -1
- data/sig/definition_builder.rbs +2 -2
- data/sig/environment_loader.rbs +3 -0
- data/sig/errors.rbs +30 -25
- data/sig/location.rbs +42 -79
- data/sig/locator.rbs +2 -2
- data/sig/members.rbs +7 -7
- data/sig/method_types.rbs +3 -3
- data/sig/parser.rbs +11 -21
- data/sig/polyfill.rbs +12 -3
- data/sig/repository.rbs +4 -0
- data/sig/types.rbs +45 -27
- data/sig/writer.rbs +1 -1
- data/stdlib/json/0/json.rbs +3 -3
- data/stdlib/objspace/0/objspace.rbs +406 -0
- data/stdlib/openssl/0/openssl.rbs +1 -1
- data/stdlib/tempfile/0/tempfile.rbs +270 -0
- data/steep/Gemfile.lock +10 -10
- metadata +43 -7
- data/lib/rbs/parser.rb +0 -3614
@@ -0,0 +1,46 @@
|
|
1
|
+
#ifndef RBS__RUBY_OBJS_H
|
2
|
+
#define RBS__RUBY_OBJS_H
|
3
|
+
|
4
|
+
#include "ruby.h"
|
5
|
+
|
6
|
+
VALUE rbs_alias(VALUE typename, VALUE location);
|
7
|
+
VALUE rbs_ast_annotation(VALUE string, VALUE location);
|
8
|
+
VALUE rbs_ast_comment(VALUE string, VALUE location);
|
9
|
+
VALUE rbs_ast_decl_alias(VALUE name, VALUE type, VALUE annotations, VALUE location, VALUE comment);
|
10
|
+
VALUE rbs_ast_decl_class_super(VALUE name, VALUE args, VALUE location);
|
11
|
+
VALUE rbs_ast_decl_class(VALUE name, VALUE type_params, VALUE super_class, VALUE members, VALUE annotations, VALUE location, VALUE comment);
|
12
|
+
VALUE rbs_ast_decl_constant(VALUE name, VALUE type, VALUE location, VALUE comment);
|
13
|
+
VALUE rbs_ast_decl_global(VALUE name, VALUE type, VALUE location, VALUE comment);
|
14
|
+
VALUE rbs_ast_decl_interface(VALUE name, VALUE type_params, VALUE members, VALUE annotations, VALUE location, VALUE comment);
|
15
|
+
VALUE rbs_ast_decl_module_self(VALUE name, VALUE args, VALUE location);
|
16
|
+
VALUE rbs_ast_decl_module_type_params_param(VALUE name, VALUE variance, VALUE skip_validation, VALUE location);
|
17
|
+
VALUE rbs_ast_decl_module_type_params();
|
18
|
+
VALUE rbs_ast_decl_module(VALUE name, VALUE type_params, VALUE self_types, VALUE members, VALUE annotations, VALUE location, VALUE comment);
|
19
|
+
VALUE rbs_ast_members_alias(VALUE new_name, VALUE old_name, VALUE kind, VALUE annotations, VALUE location, VALUE comment);
|
20
|
+
VALUE rbs_ast_members_attribute(VALUE klass, VALUE name, VALUE type, VALUE ivar_name, VALUE kind, VALUE annotations, VALUE location, VALUE comment);
|
21
|
+
VALUE rbs_ast_members_method_definition(VALUE name, VALUE kind, VALUE types, VALUE annotations, VALUE location, VALUE comment, VALUE overload);
|
22
|
+
VALUE rbs_ast_members_mixin(VALUE klass, VALUE name, VALUE args, VALUE annotations, VALUE location, VALUE comment);
|
23
|
+
VALUE rbs_ast_members_variable(VALUE klass, VALUE name, VALUE type, VALUE location, VALUE comment);
|
24
|
+
VALUE rbs_ast_members_visibility(VALUE klass, VALUE location);
|
25
|
+
VALUE rbs_base_type(VALUE klass, VALUE location);
|
26
|
+
VALUE rbs_block(VALUE type, VALUE required);
|
27
|
+
VALUE rbs_class_instance(VALUE typename, VALUE type_args, VALUE location);
|
28
|
+
VALUE rbs_class_singleton(VALUE typename, VALUE location);
|
29
|
+
VALUE rbs_function_param(VALUE type, VALUE name, VALUE location);
|
30
|
+
VALUE rbs_function(VALUE required_positional_params, VALUE optional_positional_params, VALUE rest_positional_params, VALUE trailing_positional_params, VALUE required_keywords, VALUE optional_keywords, VALUE rest_keywords, VALUE return_type);
|
31
|
+
VALUE rbs_interface(VALUE typename, VALUE type_args, VALUE location);
|
32
|
+
VALUE rbs_intersection(VALUE types, VALUE location);
|
33
|
+
VALUE rbs_literal(VALUE literal, VALUE location);
|
34
|
+
VALUE rbs_method_type(VALUE type_params, VALUE type, VALUE block, VALUE location);
|
35
|
+
VALUE rbs_namespace(VALUE path, VALUE absolute);
|
36
|
+
VALUE rbs_optional(VALUE type, VALUE location);
|
37
|
+
VALUE rbs_proc(VALUE function, VALUE block, VALUE location);
|
38
|
+
VALUE rbs_record(VALUE fields, VALUE location);
|
39
|
+
VALUE rbs_tuple(VALUE types, VALUE location);
|
40
|
+
VALUE rbs_type_name(VALUE namespace, VALUE name);
|
41
|
+
VALUE rbs_union(VALUE types, VALUE location);
|
42
|
+
VALUE rbs_variable(VALUE name, VALUE location);
|
43
|
+
|
44
|
+
void pp(VALUE object);
|
45
|
+
|
46
|
+
#endif
|
@@ -0,0 +1,65 @@
|
|
1
|
+
#include "rbs_extension.h"
|
2
|
+
|
3
|
+
static VALUE REGEXP = 0;
|
4
|
+
static VALUE HASH = 0;
|
5
|
+
|
6
|
+
static const char *regexp_str = "\\\\[abefnrstv\"]";
|
7
|
+
|
8
|
+
static ID gsub = 0;
|
9
|
+
|
10
|
+
void rbs_unescape_string(VALUE string) {
|
11
|
+
if (!REGEXP) {
|
12
|
+
REGEXP = rb_reg_new(regexp_str, strlen(regexp_str), 0);
|
13
|
+
rb_global_variable(®EXP);
|
14
|
+
}
|
15
|
+
|
16
|
+
if (!gsub) {
|
17
|
+
gsub = rb_intern("gsub!");
|
18
|
+
}
|
19
|
+
|
20
|
+
if (!HASH) {
|
21
|
+
HASH = rb_hash_new();
|
22
|
+
rb_hash_aset(HASH, rb_str_new_literal("\\a"), rb_str_new_literal("\a"));
|
23
|
+
rb_hash_aset(HASH, rb_str_new_literal("\\b"), rb_str_new_literal("\b"));
|
24
|
+
rb_hash_aset(HASH, rb_str_new_literal("\\e"), rb_str_new_literal("\e"));
|
25
|
+
rb_hash_aset(HASH, rb_str_new_literal("\\f"), rb_str_new_literal("\f"));
|
26
|
+
rb_hash_aset(HASH, rb_str_new_literal("\\n"), rb_str_new_literal("\n"));
|
27
|
+
rb_hash_aset(HASH, rb_str_new_literal("\\r"), rb_str_new_literal("\r"));
|
28
|
+
rb_hash_aset(HASH, rb_str_new_literal("\\s"), rb_str_new_literal(" "));
|
29
|
+
rb_hash_aset(HASH, rb_str_new_literal("\\t"), rb_str_new_literal("\t"));
|
30
|
+
rb_hash_aset(HASH, rb_str_new_literal("\\v"), rb_str_new_literal("\v"));
|
31
|
+
rb_hash_aset(HASH, rb_str_new_literal("\\\""), rb_str_new_literal("\""));
|
32
|
+
rb_global_variable(&HASH);
|
33
|
+
}
|
34
|
+
|
35
|
+
rb_funcall(string, gsub, 2, REGEXP, HASH);
|
36
|
+
}
|
37
|
+
|
38
|
+
VALUE rbs_unquote_string(parserstate *state, range rg, int offset_bytes) {
|
39
|
+
VALUE string = state->lexstate->string;
|
40
|
+
rb_encoding *enc = rb_enc_get(string);
|
41
|
+
|
42
|
+
unsigned int first_char = rb_enc_mbc_to_codepoint(
|
43
|
+
RSTRING_PTR(string) + rg.start.byte_pos + offset_bytes,
|
44
|
+
RSTRING_END(string),
|
45
|
+
enc
|
46
|
+
);
|
47
|
+
|
48
|
+
int byte_length = rg.end.byte_pos - rg.start.byte_pos - offset_bytes;
|
49
|
+
|
50
|
+
if (first_char == '"' || first_char == '\'' || first_char == '`') {
|
51
|
+
int bs = rb_enc_codelen(first_char, enc);
|
52
|
+
offset_bytes += bs;
|
53
|
+
byte_length -= 2 * bs;
|
54
|
+
}
|
55
|
+
|
56
|
+
char *buffer = RSTRING_PTR(state->lexstate->string) + rg.start.byte_pos + offset_bytes;
|
57
|
+
VALUE str = rb_enc_str_new(buffer, byte_length, enc);
|
58
|
+
|
59
|
+
if (first_char == '\"') {
|
60
|
+
rbs_unescape_string(str);
|
61
|
+
}
|
62
|
+
|
63
|
+
return str;
|
64
|
+
}
|
65
|
+
|
data/goodcheck.yml
CHANGED
data/lib/rbs/ast/comment.rb
CHANGED
@@ -22,18 +22,6 @@ module RBS
|
|
22
22
|
def to_json(state = _ = nil)
|
23
23
|
{ string: string, location: location }.to_json(state)
|
24
24
|
end
|
25
|
-
|
26
|
-
def concat(string:, location:)
|
27
|
-
@string.concat string
|
28
|
-
|
29
|
-
if loc = @location
|
30
|
-
loc.concat location
|
31
|
-
else
|
32
|
-
@location = location
|
33
|
-
end
|
34
|
-
|
35
|
-
self
|
36
|
-
end
|
37
25
|
end
|
38
26
|
end
|
39
27
|
end
|
data/lib/rbs/buffer.rb
CHANGED
data/lib/rbs/builtin_names.rb
CHANGED
data/lib/rbs/cli.rb
CHANGED
@@ -6,6 +6,7 @@ module RBS
|
|
6
6
|
class CLI
|
7
7
|
class LibraryOptions
|
8
8
|
attr_accessor :core_root
|
9
|
+
attr_accessor :config_path
|
9
10
|
attr_reader :repos
|
10
11
|
attr_reader :libs
|
11
12
|
attr_reader :dirs
|
@@ -16,6 +17,7 @@ module RBS
|
|
16
17
|
|
17
18
|
@libs = []
|
18
19
|
@dirs = []
|
20
|
+
@config_path = Collection::Config::PATH
|
19
21
|
end
|
20
22
|
|
21
23
|
def loader
|
@@ -25,6 +27,8 @@ module RBS
|
|
25
27
|
end
|
26
28
|
|
27
29
|
loader = EnvironmentLoader.new(core_root: core_root, repository: repository)
|
30
|
+
lock = config_path&.then { |p| Collection::Config.lockfile_of(p) }
|
31
|
+
loader.add_collection(lock) if lock
|
28
32
|
|
29
33
|
dirs.each do |dir|
|
30
34
|
loader.add(path: Pathname(dir))
|
@@ -52,6 +56,14 @@ module RBS
|
|
52
56
|
self.core_root = nil
|
53
57
|
end
|
54
58
|
|
59
|
+
opts.on('--collection PATH', "File path of collection configration (default: #{Collection::Config::PATH})") do |path|
|
60
|
+
self.config_path = Pathname(path).expand_path
|
61
|
+
end
|
62
|
+
|
63
|
+
opts.on('--no-collection', 'Ignore collection configration') do
|
64
|
+
self.config_path = nil
|
65
|
+
end
|
66
|
+
|
55
67
|
opts.on("--repo DIR", "Add RBS repository") do |dir|
|
56
68
|
repos << dir
|
57
69
|
end
|
@@ -68,7 +80,7 @@ module RBS
|
|
68
80
|
@stderr = stderr
|
69
81
|
end
|
70
82
|
|
71
|
-
COMMANDS = [:ast, :list, :ancestors, :methods, :method, :validate, :constant, :paths, :prototype, :vendor, :parse, :test]
|
83
|
+
COMMANDS = [:ast, :list, :ancestors, :methods, :method, :validate, :constant, :paths, :prototype, :vendor, :parse, :test, :collection]
|
72
84
|
|
73
85
|
def parse_logging_options(opts)
|
74
86
|
opts.on("--log-level LEVEL", "Specify log level (defaults to `warn`)") do |level|
|
@@ -737,14 +749,11 @@ Examples:
|
|
737
749
|
args.each do |path|
|
738
750
|
path = Pathname(path)
|
739
751
|
loader.each_file(path, skip_hidden: false, immediate: true) do |file_path|
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
rescue RBS::Parser::SemanticsError => ex
|
746
|
-
loc = ex.location
|
747
|
-
stdout.puts "#{file_path}:#{loc.start_line}:#{loc.start_column}: #{ex.original_message}"
|
752
|
+
RBS.logger.info "Parsing #{file_path}..."
|
753
|
+
buffer = Buffer.new(content: file_path.read, name: file_path)
|
754
|
+
Parser.parse_signature(buffer)
|
755
|
+
rescue RBS::ParsingError => ex
|
756
|
+
stdout.puts ex.message
|
748
757
|
syntax_error = true
|
749
758
|
end
|
750
759
|
end
|
@@ -819,11 +828,90 @@ EOB
|
|
819
828
|
|
820
829
|
# @type var out: String
|
821
830
|
# @type var err: String
|
822
|
-
out, err, status = Open3.capture3(env_hash, *args)
|
831
|
+
out, err, status = __skip__ = Open3.capture3(env_hash, *args)
|
823
832
|
stdout.print(out)
|
824
833
|
stderr.print(err)
|
825
834
|
|
826
835
|
status
|
827
836
|
end
|
837
|
+
|
838
|
+
def run_collection(args, options)
|
839
|
+
warn "warning: rbs collection is experimental, and the behavior may change until RBS v2.0"
|
840
|
+
|
841
|
+
opts = collection_options(args)
|
842
|
+
params = {}
|
843
|
+
opts.order args.drop(1), into: params
|
844
|
+
config_path = options.config_path or raise
|
845
|
+
lock_path = Collection::Config.to_lockfile_path(config_path)
|
846
|
+
|
847
|
+
case args[0]
|
848
|
+
when 'install'
|
849
|
+
unless params[:frozen]
|
850
|
+
Collection::Config.generate_lockfile(config_path: config_path, gemfile_lock_path: Pathname('./Gemfile.lock'))
|
851
|
+
end
|
852
|
+
Collection::Installer.new(lockfile_path: lock_path, stdout: stdout).install_from_lockfile
|
853
|
+
when 'update'
|
854
|
+
# TODO: Be aware of argv to update only specified gem
|
855
|
+
Collection::Config.generate_lockfile(config_path: config_path, gemfile_lock_path: Pathname('./Gemfile.lock'), with_lockfile: false)
|
856
|
+
Collection::Installer.new(lockfile_path: lock_path, stdout: stdout).install_from_lockfile
|
857
|
+
when 'init'
|
858
|
+
if config_path.exist?
|
859
|
+
puts "#{config_path} already exists"
|
860
|
+
exit 1
|
861
|
+
end
|
862
|
+
|
863
|
+
config_path.write(<<~'YAML')
|
864
|
+
# Download sources
|
865
|
+
sources:
|
866
|
+
- name: ruby/gem_rbs_collection
|
867
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
868
|
+
revision: main
|
869
|
+
repo_dir: gems
|
870
|
+
|
871
|
+
# A directory to install the downloaded RBSs
|
872
|
+
path: .gem_rbs_collection
|
873
|
+
|
874
|
+
gems:
|
875
|
+
# Skip loading rbs gem's RBS.
|
876
|
+
# It's unnecessary if you don't use rbs as a library.
|
877
|
+
- name: rbs
|
878
|
+
ignore: true
|
879
|
+
YAML
|
880
|
+
stdout.puts "created: #{config_path}"
|
881
|
+
when 'clean'
|
882
|
+
unless lock_path.exist?
|
883
|
+
puts "#{lock_path} should exist to clean"
|
884
|
+
exit 1
|
885
|
+
end
|
886
|
+
Collection::Cleaner.new(lockfile_path: lock_path)
|
887
|
+
when 'help'
|
888
|
+
puts opts.help
|
889
|
+
else
|
890
|
+
puts opts.help
|
891
|
+
exit 1
|
892
|
+
end
|
893
|
+
end
|
894
|
+
|
895
|
+
def collection_options(args)
|
896
|
+
OptionParser.new do |opts|
|
897
|
+
opts.banner = <<~HELP
|
898
|
+
Usage: rbs collection [install|update|init|clean|help]
|
899
|
+
|
900
|
+
Manage RBS collection, which contains third party RBS.
|
901
|
+
|
902
|
+
Examples:
|
903
|
+
|
904
|
+
# Initialize the configration file
|
905
|
+
$ rbs collection init
|
906
|
+
|
907
|
+
# Generate the lock file and install RBSs from the lock file
|
908
|
+
$ rbs collection install
|
909
|
+
|
910
|
+
# Update the RBSs
|
911
|
+
$ rbs collection update
|
912
|
+
HELP
|
913
|
+
opts.on('--frozen') if args[0] == 'install'
|
914
|
+
end
|
915
|
+
end
|
828
916
|
end
|
829
917
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module RBS
|
2
|
+
module Collection
|
3
|
+
class Cleaner
|
4
|
+
attr_reader :lock
|
5
|
+
|
6
|
+
def initialize(lockfile_path:)
|
7
|
+
@lock = Config.from_path(lockfile_path)
|
8
|
+
end
|
9
|
+
|
10
|
+
def clean
|
11
|
+
lock.repo_path.glob('*/*') do |dir|
|
12
|
+
*_, gem_name, version = dir.to_s.split('/')
|
13
|
+
gem_name or raise
|
14
|
+
version or raise
|
15
|
+
next if needed? gem_name, version
|
16
|
+
|
17
|
+
FileUtils.remove_entry_secure(dir.to_s)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def needed?(gem_name, version)
|
22
|
+
gem = lock.gem(gem_name)
|
23
|
+
return false unless gem
|
24
|
+
|
25
|
+
gem['version'] == version
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module RBS
|
2
|
+
module Collection
|
3
|
+
|
4
|
+
# This class represent the configration file.
|
5
|
+
class Config
|
6
|
+
class LockfileGenerator
|
7
|
+
attr_reader :config, :lock, :gemfile_lock, :lock_path
|
8
|
+
|
9
|
+
def self.generate(config_path:, gemfile_lock_path:, with_lockfile: true)
|
10
|
+
new(config_path: config_path, gemfile_lock_path: gemfile_lock_path, with_lockfile: with_lockfile).generate
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(config_path:, gemfile_lock_path:, with_lockfile:)
|
14
|
+
@config = Config.from_path config_path
|
15
|
+
@lock_path = Config.to_lockfile_path(config_path)
|
16
|
+
@lock = Config.from_path(lock_path) if lock_path.exist? && with_lockfile
|
17
|
+
@gemfile_lock = Bundler::LockfileParser.new(gemfile_lock_path.read)
|
18
|
+
end
|
19
|
+
|
20
|
+
def generate
|
21
|
+
config.gems.each do |gem|
|
22
|
+
assign_gem(gem_name: gem['name'], version: gem['version'])
|
23
|
+
end
|
24
|
+
|
25
|
+
gemfile_lock_gems do |spec|
|
26
|
+
assign_gem(gem_name: spec.name, version: spec.version)
|
27
|
+
end
|
28
|
+
remove_ignored_gems!
|
29
|
+
|
30
|
+
config.dump_to(lock_path)
|
31
|
+
config
|
32
|
+
end
|
33
|
+
|
34
|
+
private def assign_gem(gem_name:, version:)
|
35
|
+
locked = lock&.gem(gem_name)
|
36
|
+
specified = config.gem(gem_name)
|
37
|
+
|
38
|
+
return if specified&.dig('ignore')
|
39
|
+
return if specified&.dig('source') # skip if the source is already filled
|
40
|
+
|
41
|
+
if locked
|
42
|
+
# If rbs_collection.lock.yaml contain the gem, use it.
|
43
|
+
upsert_gem specified, locked
|
44
|
+
else
|
45
|
+
# Find the gem from gem_collection.
|
46
|
+
source = find_source(gem_name: gem_name)
|
47
|
+
return unless source
|
48
|
+
|
49
|
+
installed_version = version
|
50
|
+
best_version = find_best_version(version: installed_version, versions: source.versions({ 'name' => gem_name }))
|
51
|
+
# @type var new_content: RBS::Collection::Config::gem_entry
|
52
|
+
new_content = {
|
53
|
+
'name' => gem_name,
|
54
|
+
'version' => best_version.to_s,
|
55
|
+
'source' => source.to_lockfile,
|
56
|
+
}
|
57
|
+
upsert_gem specified, new_content
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
private def upsert_gem(old, new)
|
62
|
+
if old
|
63
|
+
old.merge! new
|
64
|
+
else
|
65
|
+
config.add_gem new
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
private def remove_ignored_gems!
|
70
|
+
config.gems.reject! { |gem| gem['ignore'] }
|
71
|
+
end
|
72
|
+
|
73
|
+
private def gemfile_lock_gems(&block)
|
74
|
+
gemfile_lock.specs.each do |spec|
|
75
|
+
yield spec
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
private def find_source(gem_name:)
|
80
|
+
sources = config.sources
|
81
|
+
|
82
|
+
sources.find { |c| c.has?({ 'name' => gem_name, 'revision' => nil } ) }
|
83
|
+
end
|
84
|
+
|
85
|
+
private def find_best_version(version:, versions:)
|
86
|
+
candidates = versions.map { |v| Gem::Version.create(v) or raise }
|
87
|
+
return candidates.max || raise unless version
|
88
|
+
|
89
|
+
v = Gem::Version.create(version) or raise
|
90
|
+
Repository.find_best_version(v, candidates)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|