rbs 1.3.3 → 1.6.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.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +10 -0
  3. data/CHANGELOG.md +69 -0
  4. data/Gemfile +2 -0
  5. data/Rakefile +4 -0
  6. data/Steepfile +9 -1
  7. data/core/array.rbs +8 -7
  8. data/core/builtin.rbs +1 -1
  9. data/core/enumerable.rbs +11 -10
  10. data/core/enumerator.rbs +2 -2
  11. data/core/exception.rbs +1 -0
  12. data/core/false_class.rbs +4 -4
  13. data/core/file.rbs +3 -1
  14. data/core/float.rbs +1 -1
  15. data/core/global_variables.rbs +180 -0
  16. data/core/hash.rbs +7 -7
  17. data/core/integer.rbs +1 -2
  18. data/core/io/wait.rbs +37 -0
  19. data/core/io.rbs +11 -5
  20. data/core/kernel.rbs +25 -2
  21. data/core/object.rbs +1 -1
  22. data/core/ractor.rbs +779 -0
  23. data/core/range.rbs +11 -9
  24. data/core/string_io.rbs +3 -5
  25. data/core/true_class.rbs +4 -4
  26. data/docs/collection.md +116 -0
  27. data/lib/rbs/builtin_names.rb +1 -0
  28. data/lib/rbs/cli.rb +94 -2
  29. data/lib/rbs/collection/cleaner.rb +29 -0
  30. data/lib/rbs/collection/config/lockfile_generator.rb +95 -0
  31. data/lib/rbs/collection/config.rb +85 -0
  32. data/lib/rbs/collection/installer.rb +27 -0
  33. data/lib/rbs/collection/sources/git.rb +147 -0
  34. data/lib/rbs/collection/sources/rubygems.rb +40 -0
  35. data/lib/rbs/collection/sources/stdlib.rb +38 -0
  36. data/lib/rbs/collection/sources.rb +22 -0
  37. data/lib/rbs/collection.rb +13 -0
  38. data/lib/rbs/environment_loader.rb +12 -0
  39. data/lib/rbs/errors.rb +18 -0
  40. data/lib/rbs/parser.rb +1 -1
  41. data/lib/rbs/parser.y +1 -1
  42. data/lib/rbs/prototype/rb.rb +8 -1
  43. data/lib/rbs/prototype/runtime.rb +1 -1
  44. data/lib/rbs/repository.rb +13 -7
  45. data/lib/rbs/type_alias_dependency.rb +88 -0
  46. data/lib/rbs/validator.rb +8 -0
  47. data/lib/rbs/version.rb +1 -1
  48. data/lib/rbs.rb +2 -0
  49. data/sig/builtin_names.rbs +1 -0
  50. data/sig/cli.rbs +5 -0
  51. data/sig/collection/cleaner.rbs +13 -0
  52. data/sig/collection/collections.rbs +112 -0
  53. data/sig/collection/config.rbs +69 -0
  54. data/sig/collection/installer.rbs +15 -0
  55. data/sig/collection.rbs +4 -0
  56. data/sig/environment_loader.rbs +3 -0
  57. data/sig/errors.rbs +9 -0
  58. data/sig/polyfill.rbs +12 -3
  59. data/sig/repository.rbs +4 -0
  60. data/sig/type_alias_dependency.rbs +22 -0
  61. data/sig/validator.rbs +2 -0
  62. data/stdlib/digest/0/digest.rbs +418 -0
  63. data/stdlib/objspace/0/objspace.rbs +406 -0
  64. data/stdlib/openssl/0/openssl.rbs +3711 -0
  65. data/stdlib/pathname/0/pathname.rbs +2 -2
  66. data/stdlib/rubygems/0/rubygems.rbs +1 -1
  67. data/stdlib/securerandom/0/securerandom.rbs +3 -1
  68. data/stdlib/tempfile/0/tempfile.rbs +270 -0
  69. data/stdlib/uri/0/generic.rbs +3 -3
  70. data/steep/Gemfile.lock +10 -10
  71. metadata +28 -3
@@ -319,9 +319,16 @@ module RBS
319
319
  const_to_name(node.children[0])
320
320
  end
321
321
 
322
+ value_node = node.children.last
323
+ type = if value_node.nil?
324
+ # Give up type prediction when node is MASGN.
325
+ Types::Bases::Any.new(location: nil)
326
+ else
327
+ node_type(value_node)
328
+ end
322
329
  decls << AST::Declarations::Constant.new(
323
330
  name: const_name,
324
- type: node_type(node.children.last),
331
+ type: type,
325
332
  location: nil,
326
333
  comment: comments[node.first_lineno - 1]
327
334
  )
@@ -87,7 +87,7 @@ module RBS
87
87
  unless const_name(mix)
88
88
  RBS.logger.warn("Skipping anonymous module #{mix} included in #{mod}")
89
89
  else
90
- module_name = module_full_name = to_type_name(const_name(mix))
90
+ module_name = module_full_name = to_type_name(const_name(mix), full_name: true)
91
91
  if module_full_name.namespace == type_name.namespace
92
92
  module_name = TypeName.new(name: module_full_name.name, namespace: Namespace.empty)
93
93
  end
@@ -55,13 +55,8 @@ module RBS
55
55
  end
56
56
 
57
57
  def find_best_version(version)
58
- return latest_version unless version
59
-
60
- if v = version_names.reverse.bsearch {|v| v <= version ? true : false }
61
- versions[v]
62
- else
63
- oldest_version
64
- end
58
+ best_version = Repository.find_best_version(version, version_names)
59
+ versions[best_version]
65
60
  end
66
61
 
67
62
  def empty?
@@ -89,6 +84,17 @@ module RBS
89
84
  end
90
85
  end
91
86
 
87
+ def self.find_best_version(version, candidates)
88
+ candidates = candidates.sort
89
+ return candidates.last || raise unless version
90
+
91
+ if v = candidates.reverse.bsearch {|v| v <= version ? true : false }
92
+ v
93
+ else
94
+ candidates.first or raise
95
+ end
96
+ end
97
+
92
98
  def add(dir)
93
99
  dirs << dir
94
100
 
@@ -0,0 +1,88 @@
1
+ module RBS
2
+ class TypeAliasDependency
3
+ attr_reader :env
4
+
5
+ # Direct dependencies corresponds to a directed graph
6
+ # with vertices as types and directions based on assignment of types
7
+ attr_reader :direct_dependencies
8
+ # A hash which stores the transitive closure
9
+ # of the directed graph
10
+ attr_reader :dependencies
11
+
12
+ def initialize(env:)
13
+ @env = env
14
+ end
15
+
16
+ # Check if an alias type definition is circular & prohibited
17
+ def circular_definition?(alias_name)
18
+ # Construct transitive closure, if not constructed already
19
+ transitive_closure() unless @dependencies
20
+
21
+ # Check for recursive type alias
22
+ @dependencies[alias_name][alias_name]
23
+ end
24
+
25
+ def build_dependencies
26
+ return if @direct_dependencies
27
+
28
+ # Initialize hash(a directed graph)
29
+ @direct_dependencies = {}
30
+ # Initialize dependencies as an empty hash
31
+ @dependencies = {}
32
+ # Iterate over alias declarations inserted into environment
33
+ env.alias_decls.each do |name, entry|
34
+ # Construct a directed graph by recursively extracting type aliases
35
+ @direct_dependencies[name] = direct_dependency(entry.decl.type)
36
+ # Initialize dependencies with an empty hash
37
+ @dependencies[name] = {}
38
+ end
39
+ end
40
+
41
+ def transitive_closure
42
+ # Construct a graph of direct dependencies
43
+ build_dependencies()
44
+ # Construct transitive closure by using DFS(recursive technique)
45
+ @direct_dependencies.each_key do |name|
46
+ dependency(name, name)
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ # Constructs directed graph recursively
53
+ def direct_dependency(type, result = Set[])
54
+ case type
55
+ when RBS::Types::Union, RBS::Types::Intersection, RBS::Types::Optional
56
+ # Iterate over nested types & extract type aliases recursively
57
+ type.each_type do |nested_type|
58
+ direct_dependency(nested_type, result)
59
+ end
60
+ when RBS::Types::Alias
61
+ # Append type name if the type is an alias
62
+ result << type.name
63
+ end
64
+
65
+ result
66
+ end
67
+
68
+ # Recursive function to construct transitive closure
69
+ def dependency(start, vertex, nested = nil)
70
+ if (start == vertex)
71
+ if (@direct_dependencies[start].include?(vertex) || nested)
72
+ # Mark a vertex as connected to itself
73
+ # if it is connected as an edge || a path(traverse multiple edges)
74
+ @dependencies[start][vertex] = true
75
+ end
76
+ else
77
+ # Mark a pair of vertices as connected while recursively performing DFS
78
+ @dependencies[start][vertex] = true
79
+ end
80
+
81
+ # Iterate over the direct dependencies of the vertex
82
+ @direct_dependencies[vertex]&.each do |type_name|
83
+ # Invoke the function unless it is already checked
84
+ dependency(start, type_name, start == type_name) unless @dependencies[start][type_name]
85
+ end
86
+ end
87
+ end
88
+ end
data/lib/rbs/validator.rb CHANGED
@@ -53,5 +53,13 @@ module RBS
53
53
  validate_type(type, context: context)
54
54
  end
55
55
  end
56
+
57
+ def validate_type_alias(entry:)
58
+ @type_alias_dependency ||= TypeAliasDependency.new(env: env)
59
+ if @type_alias_dependency.circular_definition?(entry.decl.name)
60
+ location = entry.decl.location or raise
61
+ raise RecursiveTypeAliasError.new(alias_names: [entry.decl.name], location: location)
62
+ end
63
+ end
56
64
  end
57
65
  end
data/lib/rbs/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module RBS
2
- VERSION = "1.3.3"
2
+ VERSION = "1.6.0"
3
3
  end
data/lib/rbs.rb CHANGED
@@ -44,6 +44,8 @@ require "rbs/factory"
44
44
  require "rbs/repository"
45
45
  require "rbs/ancestor_graph"
46
46
  require "rbs/locator"
47
+ require "rbs/type_alias_dependency"
48
+ require "rbs/collection"
47
49
 
48
50
  begin
49
51
  require "rbs/parser"
@@ -37,5 +37,6 @@ module RBS
37
37
  Regexp: Name
38
38
  TrueClass: Name
39
39
  FalseClass: Name
40
+ Numeric: Name
40
41
  end
41
42
  end
data/sig/cli.rbs CHANGED
@@ -2,6 +2,7 @@ module RBS
2
2
  class CLI
3
3
  class LibraryOptions
4
4
  attr_accessor core_root: Pathname?
5
+ attr_accessor config_path: Pathname?
5
6
 
6
7
  attr_reader libs: Array[String]
7
8
  attr_reader dirs: Array[String]
@@ -63,6 +64,10 @@ module RBS
63
64
 
64
65
  def run_test: (Array[String], LibraryOptions) -> void
65
66
 
67
+ def run_collection: (Array[String], LibraryOptions) -> void
68
+
66
69
  def test_opt: (LibraryOptions) -> String?
70
+
71
+ def collection_options: (Array[String]) -> OptionParser
67
72
  end
68
73
  end
@@ -0,0 +1,13 @@
1
+ module RBS
2
+ module Collection
3
+ class Cleaner
4
+ attr_reader lock: Config
5
+
6
+ def initialize: (lockfile_path: Pathname) -> void
7
+
8
+ def clean: () -> void
9
+
10
+ def needed?: (String gem_name, String version) -> bool
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,112 @@
1
+ module RBS
2
+ module Collection
3
+ module Sources
4
+ def self.from_config_entry: (source_entry) -> _Source
5
+
6
+ interface _Source
7
+ def has?: (Config::gem_entry) -> boolish
8
+ def versions: (Config::gem_entry) -> Array[String]
9
+ def install: (dest: Pathname, config_entry: Config::gem_entry, stdout: CLI::_IO) -> void
10
+ def to_lockfile: () -> source_entry
11
+ end
12
+
13
+ type source_entry = Git::source_entry
14
+ | Stdlib::source_entry
15
+ | Rubygems::source_entry
16
+
17
+ class Git
18
+ METADATA_FILENAME: String
19
+
20
+ type source_entry = {
21
+ 'type' => 'git',
22
+ 'name' => String,
23
+ 'remote' => String,
24
+ 'revision' => String,
25
+ 'repo_dir' => String?,
26
+ }
27
+
28
+ class CommandError < StandardError
29
+ end
30
+
31
+ attr_reader name: String
32
+ attr_reader remote: String
33
+ attr_reader repo_dir: String
34
+
35
+ def initialize: (name: String, revision: String, remote: String, repo_dir: String?) -> untyped
36
+
37
+ def has?: (Config::gem_entry) -> bool
38
+
39
+ def versions: (Config::gem_entry) -> Array[String]
40
+
41
+ def install: (dest: Pathname, config_entry: Config::gem_entry, stdout: CLI::_IO) -> void
42
+
43
+ def to_lockfile: () -> source_entry
44
+
45
+ private
46
+
47
+ def _install: (dest: Pathname , config_entry: Config::gem_entry) -> void
48
+
49
+ def setup!: (revision: String) -> void
50
+
51
+ def need_to_fetch?: (String revision ) -> bool
52
+
53
+ def git_dir: () -> Pathname
54
+
55
+ def gem_repo_dir: () -> Pathname
56
+
57
+ def with_revision: [T] () { () -> T } -> T
58
+
59
+ def resolved_revision: () -> String
60
+
61
+ def resolve_revision: () -> String
62
+
63
+ def git: (*String cmd) -> String
64
+
65
+ def sh!: (*String cmd) -> String
66
+
67
+ def format_config_entry: (Config::gem_entry) -> String
68
+ end
69
+
70
+ # signatures that are bundled in rbs gem under the stdlib/ directory
71
+ class Stdlib
72
+ type source_entry = {
73
+ 'type' => 'stdlib',
74
+ }
75
+
76
+ # polyfill of singleton module
77
+ def self.instance: () -> instance
78
+
79
+ def has?: (Config::gem_entry) -> bool
80
+
81
+ def versions: (Config::gem_entry) -> Array[String]
82
+
83
+ def install: (dest: Pathname, config_entry: Config::gem_entry, stdout: CLI::_IO) -> void
84
+
85
+ def to_lockfile: () -> source_entry
86
+
87
+ private
88
+
89
+ def gem_dir: (Config::gem_entry) -> Pathname
90
+ end
91
+
92
+ # sig/ directory
93
+ class Rubygems
94
+ type source_entry = {
95
+ 'type' => 'rubygems',
96
+ }
97
+
98
+ # polyfill of singleton module
99
+ def self.instance: () -> instance
100
+
101
+ def has?: (Config::gem_entry) -> boolish
102
+ def versions: (Config::gem_entry) -> Array[String]
103
+ def install: (dest: Pathname, config_entry: Config::gem_entry, stdout: CLI::_IO) -> void
104
+ def to_lockfile: () -> source_entry
105
+
106
+ private
107
+
108
+ def gem_sig_path: (Config::gem_entry) -> [Gem::Specification, Pathname]?
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,69 @@
1
+ module RBS
2
+ module Collection
3
+ # This class represent the configration file.
4
+ class Config
5
+ class LockfileGenerator
6
+ attr_reader config: Config
7
+ attr_reader lock: Config?
8
+ attr_reader lock_path: Pathname
9
+ attr_reader gemfile_lock: Bundler::LockfileParser
10
+
11
+ def self.generate: (config_path: Pathname, gemfile_lock_path: Pathname, ?with_lockfile: boolish) -> Config
12
+
13
+ def initialize: (config_path: Pathname, gemfile_lock_path: Pathname, with_lockfile: boolish) -> void
14
+
15
+ def generate: () -> Config
16
+
17
+ private
18
+
19
+ def assign_gem: (gem_name: String, version: String?) -> void
20
+
21
+ def upsert_gem: (gem_entry? old, gem_entry new) -> void
22
+
23
+ def gemfile_lock_gems: () { (untyped) -> void } -> void
24
+
25
+ def remove_ignored_gems!: () -> void
26
+
27
+ def find_source: (gem_name: String) -> untyped
28
+
29
+ def find_best_version: (version: String?, versions: Array[String]) -> Gem::Version
30
+ end
31
+
32
+ PATH: Pathname
33
+
34
+ type gem_entry = {
35
+ 'name' => String,
36
+ 'version' => String?,
37
+ 'ignore' => boolish,
38
+ 'source' => Sources::source_entry?
39
+ }
40
+
41
+ @config_path: Pathname
42
+
43
+ def self.generate_lockfile: (config_path: Pathname, gemfile_lock_path: Pathname, ?with_lockfile: boolish) -> Config
44
+
45
+ def self.from_path: (Pathname path) -> Config
46
+
47
+ def self.lockfile_of: (Pathname config_path) -> Config?
48
+
49
+ def self.to_lockfile_path: (Pathname config_path) -> Pathname
50
+
51
+ # config_path is necessary to resolve relative repo_path
52
+ def initialize: (untyped data, config_path: Pathname) -> void
53
+
54
+ def add_gem: (untyped gem) -> untyped
55
+
56
+ def gem: (String gem_name) -> untyped
57
+
58
+ def repo_path: () -> Pathname
59
+
60
+ def sources: () -> Array[Sources::_Source]
61
+
62
+ def dump_to: (Pathname) -> void
63
+
64
+ def gems: () -> Array[untyped]
65
+
66
+ def check_rbs_availability!: () -> void
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,15 @@
1
+ module RBS
2
+ module Collection
3
+ class Installer
4
+ attr_reader lockfile: Config
5
+ attr_reader stdout: CLI::_IO
6
+
7
+ def initialize: (lockfile_path: Pathname, ?stdout: CLI::_IO) -> void
8
+ def install_from_lockfile: () -> void
9
+
10
+ private
11
+
12
+ def source_for: (Config::gem_entry) -> Sources::_Source
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,4 @@
1
+ module RBS
2
+ module Collection
3
+ end
4
+ end
@@ -78,6 +78,9 @@ module RBS
78
78
  def add: (path: Pathname) -> void
79
79
  | (library: String, version: String?) -> void
80
80
 
81
+ # Add repository path and libraries via rbs_collection.lock.yaml.
82
+ def add_collection: (Collection::Config collection_config) -> void
83
+
81
84
  # This is helper function to test if RBS for a library is available or not.
82
85
  #
83
86
  def has_library?: (library: String, version: String?) -> bool
data/sig/errors.rbs CHANGED
@@ -196,4 +196,13 @@ module RBS
196
196
 
197
197
  def mixin_name: () -> String
198
198
  end
199
+
200
+ class RecursiveTypeAliasError < LoadingError
201
+ attr_reader alias_names: Array[TypeName]
202
+ attr_reader location: Location
203
+
204
+ def initialize: (alias_names: Array[TypeName], location: Location) -> void
205
+
206
+ def name: () -> String
207
+ end
199
208
  end