orthoses 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +11 -0
- data/LICENSE.txt +21 -0
- data/README.md +123 -0
- data/lib/orthoses/builder.rb +55 -0
- data/lib/orthoses/call_tracer.rb +53 -0
- data/lib/orthoses/constant.rb +47 -0
- data/lib/orthoses/content.rb +113 -0
- data/lib/orthoses/create_file_by_name.rb +44 -0
- data/lib/orthoses/delegate_class.rb +45 -0
- data/lib/orthoses/filter.rb +24 -0
- data/lib/orthoses/include_extend_prepend.rb +58 -0
- data/lib/orthoses/load_rbs.rb +89 -0
- data/lib/orthoses/object_space_all.rb +25 -0
- data/lib/orthoses/pp.rb +15 -0
- data/lib/orthoses/store.rb +16 -0
- data/lib/orthoses/tap.rb +19 -0
- data/lib/orthoses/utils.rb +166 -0
- data/lib/orthoses/version.rb +5 -0
- data/lib/orthoses/walk.rb +25 -0
- data/lib/orthoses.rb +46 -0
- data/orthoses.gemspec +36 -0
- data/sig/orthoses/_call.rbs +5 -0
- data/sig/orthoses/_middle_ware.rbs +5 -0
- data/sig/orthoses/builder/call_logable.rbs +4 -0
- data/sig/orthoses/builder.rbs +5 -0
- data/sig/orthoses/call_tracer.rbs +5 -0
- data/sig/orthoses/const_load_error.rbs +8 -0
- data/sig/orthoses/constant.rbs +7 -0
- data/sig/orthoses/content.rbs +11 -0
- data/sig/orthoses/create_file_by_name.rbs +7 -0
- data/sig/orthoses/delegate_class.rbs +4 -0
- data/sig/orthoses/filter.rbs +7 -0
- data/sig/orthoses/include_extend_prepend.rbs +4 -0
- data/sig/orthoses/load_rbs.rbs +4 -0
- data/sig/orthoses/name_space_error.rbs +4 -0
- data/sig/orthoses/object_space_all.rbs +4 -0
- data/sig/orthoses/pp.rbs +4 -0
- data/sig/orthoses/store.rbs +4 -0
- data/sig/orthoses/tap.rbs +4 -0
- data/sig/orthoses/utils.rbs +27 -0
- data/sig/orthoses/walk.rbs +8 -0
- data/sig/orthoses.rbs +9 -0
- metadata +102 -0
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Orthoses
|
4
|
+
class LoadRBS
|
5
|
+
# use Orthoses::LoadRBS,
|
6
|
+
# paths: Dir.glob("known_sig/**/*.rbs")
|
7
|
+
def initialize(loader, paths:)
|
8
|
+
@loader = loader
|
9
|
+
@paths = paths
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
@loader.call.tap do |store|
|
14
|
+
tmp_env = RBS::Environment.new
|
15
|
+
|
16
|
+
@paths.each do |path|
|
17
|
+
Orthoses.logger.debug("Load #{path}")
|
18
|
+
buffer = RBS::Buffer.new(name: path.to_s, content: File.read(path.to_s, encoding: "UTF-8"))
|
19
|
+
decls = RBS::Parser.parse_signature(buffer)
|
20
|
+
decls.each { |decl| tmp_env << decl }
|
21
|
+
end
|
22
|
+
|
23
|
+
tmp_env.class_decls.each do |type_name, m_entry|
|
24
|
+
name = type_name.relative!.to_s
|
25
|
+
content = store[name]
|
26
|
+
case decl = m_entry.decls.first.decl
|
27
|
+
when RBS::AST::Declarations::Module
|
28
|
+
self_types = decl.self_types.empty? ? nil : " : #{decl.self_types.join(', ')}"
|
29
|
+
content.header = "module #{name_and_params(name, decl.type_params)}#{self_types}"
|
30
|
+
when RBS::AST::Declarations::Class
|
31
|
+
super_class = decl.super_class.nil? ? nil : " < #{name_and_args(decl.super_class.name, decl.super_class.args)}"
|
32
|
+
content.header = "class #{name_and_params(name, decl.type_params)}#{super_class}"
|
33
|
+
end
|
34
|
+
decls_to_lines(m_entry.decls.map(&:decl)).each do |line|
|
35
|
+
content << line
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
tmp_env.interface_decls.each do |type_name, s_entry|
|
40
|
+
name = type_name.relative!.to_s
|
41
|
+
content = store[name]
|
42
|
+
decl = s_entry.decl
|
43
|
+
content.header = "interface #{name_and_params(name, decl.type_params)}"
|
44
|
+
decls_to_lines([decl]).each do |line|
|
45
|
+
content << line
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def name_and_params(name, params)
|
54
|
+
if params.empty?
|
55
|
+
"#{name}"
|
56
|
+
else
|
57
|
+
ps = params.each.map do |param|
|
58
|
+
param.to_s
|
59
|
+
end
|
60
|
+
|
61
|
+
"#{name}[#{ps.join(", ")}]"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def name_and_args(name, args)
|
66
|
+
if name && args
|
67
|
+
if args.empty?
|
68
|
+
"#{name}"
|
69
|
+
else
|
70
|
+
"#{name}[#{args.join(", ")}]"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def decls_to_lines(decls)
|
76
|
+
out = StringIO.new
|
77
|
+
writer = RBS::Writer.new(out: out)
|
78
|
+
decls.each do |decl|
|
79
|
+
if decl.respond_to?(:members)
|
80
|
+
decl.members.each do |member|
|
81
|
+
next if member.respond_to?(:members)
|
82
|
+
writer.write_member(member)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
out.string.each_line(chomp: true).to_a
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Orthoses
|
4
|
+
class ObjectSpaceAll
|
5
|
+
def initialize(loader, if: nil)
|
6
|
+
@loader = loader
|
7
|
+
@if = binding.local_variable_get(:if)
|
8
|
+
end
|
9
|
+
|
10
|
+
def call
|
11
|
+
store = @loader.call
|
12
|
+
|
13
|
+
after_modules = ObjectSpace.each_object(Module).to_a
|
14
|
+
after_modules.each do |mod|
|
15
|
+
mod_name = Utils.module_name(mod)
|
16
|
+
next if mod_name.nil?
|
17
|
+
next unless @if.nil? || @if.call(mod)
|
18
|
+
|
19
|
+
store[mod_name]
|
20
|
+
end
|
21
|
+
|
22
|
+
store
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/orthoses/pp.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Orthoses
|
4
|
+
# Internal middleware for return store object
|
5
|
+
# Builder set this middleware on last stack by default
|
6
|
+
class Store
|
7
|
+
def initialize(loader)
|
8
|
+
@loader = loader
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
@loader.call
|
13
|
+
Utils.new_store
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/orthoses/tap.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Orthoses
|
4
|
+
# use Orthoses::Tap do |store|
|
5
|
+
# store["Foo::Bar"] << "def baz: () -> void"
|
6
|
+
# end
|
7
|
+
class Tap
|
8
|
+
def initialize(loader, &block)
|
9
|
+
@loader = loader
|
10
|
+
@block = block
|
11
|
+
end
|
12
|
+
|
13
|
+
def call
|
14
|
+
@loader.call.tap do |store|
|
15
|
+
@block.call(store)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Orthoses
|
4
|
+
module Utils
|
5
|
+
def self.unautoload!
|
6
|
+
ObjectSpace.each_object(Module) do |mod|
|
7
|
+
each_const_recursive(mod)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.each_const_recursive(root, cache: {}, on_error: nil, &block)
|
12
|
+
root.constants(false).each do |const|
|
13
|
+
val = root.const_get(const)
|
14
|
+
next if cache[const].equal?(val)
|
15
|
+
cache[const] = val
|
16
|
+
next if val.equal?(root)
|
17
|
+
block.call(root, const, val) if block
|
18
|
+
if val.respond_to?(:constants)
|
19
|
+
each_const_recursive(val, cache: cache, on_error: on_error, &block)
|
20
|
+
end
|
21
|
+
rescue LoadError, StandardError => err
|
22
|
+
Orthoses.logger.warn("Orthoses::Utils.each_const_recursive: #{err.class}: #{err.message} on #{err.backtrace.first}")
|
23
|
+
if on_error
|
24
|
+
on_error.call(ConstLoadError.new(root: root, const: const, error: err))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.rbs_defined_const?(name, library: nil, collection: false)
|
30
|
+
return false if name.start_with?("#<")
|
31
|
+
env = rbs_environment(library: library, collection: collection)
|
32
|
+
name = name.sub(/Object::/, '')
|
33
|
+
target = rbs_type_name(name)
|
34
|
+
env.constant_decls.has_key?(target)
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.rbs_defined_class?(name, library: nil, collection: false)
|
38
|
+
return false if name.start_with?("#<")
|
39
|
+
env = rbs_environment(library: library, collection: collection)
|
40
|
+
target = rbs_type_name(name)
|
41
|
+
env.class_decls.has_key?(target)
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.rbs_type_name(name)
|
45
|
+
name = "::#{name}" if !name.start_with?("::")
|
46
|
+
RBS::Namespace.parse(name).to_type_name
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.rbs_environment(library: nil, collection: false)
|
50
|
+
@env_cache ||= {}
|
51
|
+
if hit = @env_cache[[library, collection]]
|
52
|
+
return hit
|
53
|
+
end
|
54
|
+
|
55
|
+
loader = RBS::EnvironmentLoader.new
|
56
|
+
|
57
|
+
if collection
|
58
|
+
lock = RBS::Collection::Config::PATH&.then { |p| RBS::Collection::Config.lockfile_of(p) }
|
59
|
+
loader.add_collection(lock) if lock
|
60
|
+
end
|
61
|
+
|
62
|
+
case library
|
63
|
+
when "stdlib"
|
64
|
+
RBS::Repository::DEFAULT_STDLIB_ROOT.each_entry do |path|
|
65
|
+
lib = path.to_s
|
66
|
+
loader.add(library: lib.to_s) unless lib == "." || lib == ".."
|
67
|
+
end
|
68
|
+
else
|
69
|
+
Array(library).each do |lib|
|
70
|
+
loader.add(library: lib.to_s)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
environment = RBS::Environment.from_loader(loader).resolve_type_names
|
75
|
+
@env_cache[[library, collection]] = environment
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.object_to_rbs(object, strict:)
|
79
|
+
case object
|
80
|
+
when Class, Module
|
81
|
+
"singleton(#{object})"
|
82
|
+
when Integer, Symbol, String
|
83
|
+
if strict
|
84
|
+
object.inspect
|
85
|
+
else
|
86
|
+
Utils.module_name(object.class) || 'untyped'
|
87
|
+
end
|
88
|
+
when true, false, nil
|
89
|
+
object.inspect
|
90
|
+
when Set
|
91
|
+
if object.empty?
|
92
|
+
"Set[untyped]"
|
93
|
+
else
|
94
|
+
ary = object.map do |o|
|
95
|
+
object_to_rbs(o, strict: strict)
|
96
|
+
end
|
97
|
+
"Set[#{ary.uniq.join(' | ')}]"
|
98
|
+
end
|
99
|
+
when Array
|
100
|
+
if object.empty?
|
101
|
+
"Array[untyped]"
|
102
|
+
else
|
103
|
+
ary = object.map do |o|
|
104
|
+
object_to_rbs(o, strict: strict)
|
105
|
+
end
|
106
|
+
if strict
|
107
|
+
"[#{ary.join(', ')}]"
|
108
|
+
else
|
109
|
+
"Array[#{ary.uniq.join(' | ')}]"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
when Hash
|
113
|
+
if object.empty?
|
114
|
+
"Hash[untyped, untyped]"
|
115
|
+
else
|
116
|
+
if strict && object.keys.all? { |key| key.is_a?(Symbol) && /\A\w+\z/.match?(key) }
|
117
|
+
"{ #{object.map { |k, v| "#{k}: #{object_to_rbs(v, strict: strict)}" }.join(', ')} }"
|
118
|
+
else
|
119
|
+
keys = object.keys.map { |k| object_to_rbs(k, strict: strict) }.uniq
|
120
|
+
values = object.values.map { |k| object_to_rbs(k, strict: strict) }.uniq
|
121
|
+
"Hash[#{keys.join(' | ')}, #{values.join(' | ')}]"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
else
|
125
|
+
Utils.module_name(object.class) || 'untyped'
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
UNBOUND_NAME_METHOD = Module.instance_method(:name)
|
130
|
+
|
131
|
+
# Want to get the module name even if the method is overwritten.
|
132
|
+
# e.g.) Rails::Info
|
133
|
+
def self.module_name(mod)
|
134
|
+
return nil unless mod
|
135
|
+
UNBOUND_NAME_METHOD.bind(mod).call
|
136
|
+
end
|
137
|
+
|
138
|
+
def self.module_to_type_name(mod)
|
139
|
+
name = Utils.module_name(mod)
|
140
|
+
if name && !name.empty?
|
141
|
+
TypeName(name)
|
142
|
+
else
|
143
|
+
nil
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def self.known_type_params(name)
|
148
|
+
type_name =
|
149
|
+
case name
|
150
|
+
when String
|
151
|
+
TypeName(name).absolute!
|
152
|
+
when Module
|
153
|
+
module_to_type_name(name)
|
154
|
+
else
|
155
|
+
raise TypeError
|
156
|
+
end
|
157
|
+
rbs_environment(collection: true).class_decls[type_name]&.then do |entry|
|
158
|
+
entry.decls.first.decl.type_params
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def self.new_store
|
163
|
+
Hash.new { |h, k| h[k] = Content.new(name: k) }
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Orthoses
|
4
|
+
class Walk
|
5
|
+
def initialize(loader, root:)
|
6
|
+
@loader = loader
|
7
|
+
@root = root
|
8
|
+
end
|
9
|
+
|
10
|
+
def call
|
11
|
+
@loader.call.tap do |store|
|
12
|
+
root = Object.const_get(@root) if @root.instance_of?(String)
|
13
|
+
Utils.module_name(root)&.then { |root_name| store[root_name] }
|
14
|
+
Orthoses::Utils.each_const_recursive(root) do |current, const, val|
|
15
|
+
if val.kind_of?(Module)
|
16
|
+
Utils.module_name(val)&.then do |val_name|
|
17
|
+
Orthoses.logger.debug("Add [#{val_name}] on #{__FILE__}:#{__LINE__}")
|
18
|
+
store[val_name]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/orthoses.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rbs'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
require_relative 'orthoses/builder'
|
7
|
+
require_relative 'orthoses/call_tracer'
|
8
|
+
require_relative 'orthoses/constant'
|
9
|
+
require_relative 'orthoses/content'
|
10
|
+
require_relative 'orthoses/create_file_by_name'
|
11
|
+
require_relative 'orthoses/delegate_class'
|
12
|
+
require_relative 'orthoses/filter'
|
13
|
+
require_relative 'orthoses/include_extend_prepend'
|
14
|
+
require_relative 'orthoses/load_rbs'
|
15
|
+
require_relative 'orthoses/object_space_all'
|
16
|
+
require_relative 'orthoses/pp'
|
17
|
+
require_relative 'orthoses/store'
|
18
|
+
require_relative 'orthoses/tap'
|
19
|
+
require_relative 'orthoses/utils'
|
20
|
+
require_relative 'orthoses/version'
|
21
|
+
require_relative 'orthoses/walk'
|
22
|
+
|
23
|
+
module Orthoses
|
24
|
+
class ConstLoadError < StandardError
|
25
|
+
attr_reader :root
|
26
|
+
attr_reader :const
|
27
|
+
attr_reader :error
|
28
|
+
def initialize(root:, const:, error:)
|
29
|
+
@root = root
|
30
|
+
@const = const
|
31
|
+
@error = error
|
32
|
+
end
|
33
|
+
|
34
|
+
def message
|
35
|
+
"root=#{root}, const=#{const}, error=#{error.inspect}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class NameSpaceError < StandardError
|
40
|
+
end
|
41
|
+
|
42
|
+
class << self
|
43
|
+
attr_accessor :logger
|
44
|
+
end
|
45
|
+
self.logger = ::Logger.new($stdout, level: :info)
|
46
|
+
end
|
data/orthoses.gemspec
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/orthoses/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "orthoses"
|
7
|
+
spec.version = Orthoses::VERSION
|
8
|
+
spec.authors = ["ksss"]
|
9
|
+
spec.email = ["co000ri@gmail.com"]
|
10
|
+
|
11
|
+
spec.summary = "Framework for Generate RBS"
|
12
|
+
spec.description = "Build RBS by Rack base architecture"
|
13
|
+
spec.homepage = "https://github.com/ksss/orthoses"
|
14
|
+
spec.license = "MIT"
|
15
|
+
spec.required_ruby_version = ">= 2.6.0"
|
16
|
+
|
17
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
18
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
19
|
+
|
20
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
21
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
22
|
+
next true if (f == __FILE__)
|
23
|
+
next true if f.match?(%r{\A(?:bin|known_sig)/}) # dir
|
24
|
+
next true if f.match?(%r{\A\.(?:git)}) # git
|
25
|
+
next true if f.match?(%r{\A(?:rbs_collection|Steepfile|Rakefile)}) # top file
|
26
|
+
next true if f.match?(%r{_test\.rb\z}) # test
|
27
|
+
false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
spec.bindir = "exe"
|
32
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
33
|
+
spec.require_paths = ["lib"]
|
34
|
+
|
35
|
+
spec.add_dependency "rbs", "~> 2.0"
|
36
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# THIS IS GENERATED CODE from `$ rake generate_self_sig`
|
2
|
+
|
3
|
+
class Orthoses::ConstLoadError < StandardError
|
4
|
+
attr_reader root: Module
|
5
|
+
attr_reader const: Symbol
|
6
|
+
attr_reader error: untyped
|
7
|
+
def initialize: (root: Module, const: Symbol, error: untyped) -> void
|
8
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# THIS IS GENERATED CODE from `$ rake generate_self_sig`
|
2
|
+
|
3
|
+
class Orthoses::Constant
|
4
|
+
@loader: Orthoses::_Call
|
5
|
+
include Orthoses::_MiddleWare
|
6
|
+
def initialize: (Orthoses::_Call loader, ?if: ^(Module, Symbol, untyped) -> boolish, ?on_error: ^(Orthoses::ConstLoadError) -> void) -> void
|
7
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# THIS IS GENERATED CODE from `$ rake generate_self_sig`
|
2
|
+
|
3
|
+
class Orthoses::Content
|
4
|
+
attr_reader name: String
|
5
|
+
attr_reader body: Array[String]
|
6
|
+
attr_accessor header: String?
|
7
|
+
def initialize: (name: String) -> void
|
8
|
+
def <<: (String) -> void
|
9
|
+
def concat: (Array[String]) -> void
|
10
|
+
def to_rbs: () -> String
|
11
|
+
end
|
data/sig/orthoses/pp.rbs
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# THIS IS GENERATED CODE from `$ rake generate_self_sig`
|
2
|
+
|
3
|
+
module Orthoses::Utils
|
4
|
+
UNBOUND_NAME_METHOD: UnboundMethod
|
5
|
+
|
6
|
+
def self.unautoload!: () -> void
|
7
|
+
|
8
|
+
def self.each_const_recursive: (Module root, ?cache: Hash[untyped, true], ?on_error: ^(Orthoses::ConstLoadError) -> void?) ?{ (Module, Symbol, untyped) -> void } -> void
|
9
|
+
|
10
|
+
def self.rbs_defined_const?: (String name, ?library: (String | Array[String])?, ?collection: boolish) -> bool
|
11
|
+
|
12
|
+
def self.rbs_defined_class?: (String name, ?library: (String | Array[String])?, ?collection: boolish) -> bool
|
13
|
+
|
14
|
+
def self.rbs_type_name: (String) -> RBS::TypeName
|
15
|
+
|
16
|
+
def self.rbs_environment: (?library: String | Array[String] | nil, ?collection: boolish) -> RBS::Environment
|
17
|
+
|
18
|
+
def self.object_to_rbs: (untyped object, strict: bool) -> String
|
19
|
+
|
20
|
+
def self.module_name: (Module mod) -> String?
|
21
|
+
|
22
|
+
def self.module_to_type_name: (Module) -> RBS::TypeName?
|
23
|
+
|
24
|
+
def self.known_type_params: (Module | String) -> Array[RBS::AST::TypeParam]
|
25
|
+
|
26
|
+
def self.new_store: () -> Orthoses::store
|
27
|
+
end
|