orthoses 0.1.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 64cbbb058a7d4dc7c5f6f0d8cc66a23a1b2026253ad20add3cc63777a1c42227
4
- data.tar.gz: 15742e8389d7fc4e129bca6ab48203f13dad5b2338eff73a2b4c530ba239d327
3
+ metadata.gz: 0e53d784825b1c759916988c4aaca8e6942fd89e0de4c73dff022f40ca265027
4
+ data.tar.gz: 7e6fdb9ac599274b713a9930d15bb8b81267c3afcc4a7ed3a6c747a13c711201
5
5
  SHA512:
6
- metadata.gz: 276874fcb60ce45b3b2ffe3388e963b596f65a466c4f36f5b3986b561f756f721d797e8217a27b6a292f988343fe8f4209886b876ba03e4512466b51903e4996
7
- data.tar.gz: 73b2a614b599980d20d2d0334d87f4f508b163beff9a766979d67f39f49213a634c9e907725efd1f7a51e1552b5db90e80f3d766bba024ff050d50c5d5522b5c
6
+ metadata.gz: 61b9855a1f2744de78e9993d4adb024133aa08eeefa4541f9371bbb9598c500b8e4af2618ff9904039bbb086a2fde61b714c6ae20bc466077b1b46601f9d6735
7
+ data.tar.gz: 6a2eaea1e8da4d1231dbcf4ebb4b4b92e228a03656a89385a439ff651b5dc204a9fb5071e8fb11a0fec35e95e85e6e1c332cc341ecb72302bd3d2623e3779585
data/Gemfile.lock ADDED
@@ -0,0 +1,61 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ orthoses (0.4.0)
5
+ rbs (~> 2.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activesupport (7.0.3)
11
+ concurrent-ruby (~> 1.0, >= 1.0.2)
12
+ i18n (>= 1.6, < 2)
13
+ minitest (>= 5.1)
14
+ tzinfo (~> 2.0)
15
+ ast (2.4.2)
16
+ concurrent-ruby (1.1.10)
17
+ ffi (1.15.5)
18
+ i18n (1.10.0)
19
+ concurrent-ruby (~> 1.0)
20
+ language_server-protocol (3.16.0.3)
21
+ listen (3.7.1)
22
+ rb-fsevent (~> 0.10, >= 0.10.3)
23
+ rb-inotify (~> 0.9, >= 0.9.10)
24
+ minitest (5.15.0)
25
+ parallel (1.22.1)
26
+ parser (3.1.2.0)
27
+ ast (~> 2.4.1)
28
+ rainbow (3.1.1)
29
+ rake (13.0.6)
30
+ rb-fsevent (0.11.1)
31
+ rb-inotify (0.10.1)
32
+ ffi (~> 1.0)
33
+ rbs (2.5.0)
34
+ rgot (1.1.0)
35
+ steep (1.0.0)
36
+ activesupport (>= 5.1)
37
+ language_server-protocol (>= 3.15, < 4.0)
38
+ listen (~> 3.0)
39
+ parallel (>= 1.0.0)
40
+ parser (>= 3.0)
41
+ rainbow (>= 2.2.2, < 4.0)
42
+ rbs (>= 2.3.2)
43
+ terminal-table (>= 2, < 4)
44
+ terminal-table (3.0.2)
45
+ unicode-display_width (>= 1.1.1, < 3)
46
+ tzinfo (2.0.4)
47
+ concurrent-ruby (~> 1.0)
48
+ unicode-display_width (2.1.0)
49
+
50
+ PLATFORMS
51
+ ruby
52
+
53
+ DEPENDENCIES
54
+ activesupport
55
+ orthoses!
56
+ rake (~> 13.0)
57
+ rgot (~> 1.1)
58
+ steep
59
+
60
+ BUNDLED WITH
61
+ 2.3.9
data/README.md CHANGED
@@ -31,7 +31,7 @@ Orthoses::Builder.new do
31
31
  %r{app/models}.match?(path)
32
32
  }
33
33
  use YourCustom::Middleware
34
- use Orthoses::IncludeExtendPrepend
34
+ use Orthoses::Mixin
35
35
  use Orthoses::Constant
36
36
  use Orthoses::Walk,
37
37
  root: "Foo"
@@ -48,7 +48,7 @@ end.call
48
48
  Add constant signature to class/module.
49
49
  Signatures are predicted from constant values.
50
50
 
51
- ### Orthoses::IncludeExtendPrepend
51
+ ### Orthoses::Mixin
52
52
 
53
53
  Add module include/extend/prepend definition.
54
54
  It use `Module#{includeed,extended,prepended}` for capture.
@@ -103,6 +103,22 @@ class Tempfile < File
103
103
  end
104
104
  ```
105
105
 
106
+ ### Orthoses::Writer
107
+
108
+ Write output RBS to `io` option object.
109
+ `io` should be able to call `#write` method.
110
+ This is useful when you want to combine outputs into a single output.
111
+
112
+ ### Orthoses::RBSPrototypeRB
113
+
114
+ Run `rbs prototype rb` command process to `paths` option files.
115
+ `content_filter` option could filter with content decl.
116
+ `mixin_filter` option could filter with mixin(include, extend, prepend) decl.
117
+
118
+ ### Orthoses::AvoidRecursiveAncestorError
119
+
120
+ Mixin a module into an Object class raises `RBS::RecursiveAncestorError` when validation.
121
+ Please add this middleware then.
106
122
 
107
123
  ## Development
108
124
 
@@ -0,0 +1,48 @@
1
+ file :src do
2
+ sh "git clone https://github.com/minitest/minitest.git src"
3
+ end
4
+
5
+ desc "generate minitest"
6
+ task :minitest => :src do
7
+ $:.unshift(File.expand_path("src/lib"))
8
+
9
+ out = Pathname('out')
10
+ out.rmtree rescue nil
11
+ require 'orthoses'
12
+
13
+ Orthoses::Builder.new do
14
+ use Orthoses::CreateFileByName,
15
+ base_dir: out.to_s
16
+ use Orthoses::Filter, if: ->(name, content) {
17
+ name.start_with?("Minitest") || name == "Kernel"
18
+ }
19
+ use Orthoses::Constant,
20
+ strict: false,
21
+ if: ->(current, const, val, rbs){
22
+ !Orthoses::Utils.rbs_defined_const?("#{current}::#{const}")
23
+ }
24
+ use Orthoses::Mixin
25
+ use Orthoses::RBSPrototypeRB,
26
+ paths: Dir.glob('src/lib/minitest{.rb,/*.rb}'),
27
+ constant_filter: ->(_) { false },
28
+ mixin_filter: ->(_) { false }
29
+ run ->(){
30
+ require_relative 'src/lib/minitest'
31
+ require_relative 'src/lib/minitest/test'
32
+ require_relative 'src/lib/minitest/spec'
33
+ require_relative 'src/lib/minitest/parallel'
34
+ require_relative 'src/lib/minitest/mock'
35
+ require_relative 'src/lib/minitest/benchmark'
36
+
37
+ require_relative 'src/lib/minitest/pride_plugin'
38
+ }
39
+ end.call
40
+
41
+ sh "rbs -r mutex_m -I #{out} validate --silent"
42
+ out.join("manifest.yaml").write <<~YAML
43
+ dependencies:
44
+ - name: mutex_m
45
+ YAML
46
+ end
47
+
48
+ task default: :minitest
@@ -0,0 +1,11 @@
1
+ module Orthoses
2
+ class Simple
3
+ def initialize(loader)
4
+ @loader = loader
5
+ end
6
+
7
+ def call
8
+ @loader.call
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ module Orthoses
2
+ class Simple
3
+ @loader: Orthoses::_Call
4
+ include Orthoses::_MiddleWare
5
+ def initialize: (Orthoses::_Call loader) -> void
6
+ end
7
+ end
@@ -0,0 +1,22 @@
1
+ module Orthoses
2
+ class AvoidRecursiveAncestorError
3
+ def initialize(loader)
4
+ @loader = loader
5
+ end
6
+
7
+ def call
8
+ @loader.call.tap do |store|
9
+ object_mixins = {}
10
+ store["Object"].to_decl.members.each do |member|
11
+ case member
12
+ when RBS::AST::Members::Mixin
13
+ object_mixins[member.name.relative!.to_s] = true
14
+ end
15
+ end
16
+ object_mixins.each_key do |object_mixin|
17
+ store[object_mixin].header = "module #{object_mixin} : BasicObject"
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -5,7 +5,7 @@ module Orthoses
5
5
  # Builder.new do
6
6
  # use Orthoses::CreateFileByName
7
7
  # use Orthoses::Constant
8
- # use Orthoses::IncludeExtendPrepend
8
+ # use Orthoses::Mixin
9
9
  # use Orthoses::Walk,
10
10
  # root: "Foo"
11
11
  # run ->() { require 'foo' }
@@ -20,7 +20,7 @@ module Orthoses
20
20
  end
21
21
 
22
22
  def trace(target, &block)
23
- TracePoint.new(:call) do |tp|
23
+ t = TracePoint.new(:call) do |tp|
24
24
  called_method = tp.self.method(tp.method_id)
25
25
  argument = tp.parameters.each_with_object({}) do |op_name, hash|
26
26
  name = op_name[1]
@@ -47,7 +47,8 @@ module Orthoses
47
47
  end
48
48
  end
49
49
  @result << [called_method, argument]
50
- end.enable(target: target, &block)
50
+ end
51
+ t.enable(target: target, &block)
51
52
  end
52
53
  end
53
54
  end
@@ -0,0 +1,60 @@
1
+ module Orthoses
2
+ class Content
3
+ # Check and drop duplication method, const etc...
4
+ class DuplicationChecker
5
+ def initialize(decl)
6
+ @decl = decl
7
+ end
8
+
9
+ def update_decl
10
+ uniq_map = {}
11
+ @decl.members.reverse_each do |member|
12
+ key = member_key(member)
13
+ if uniq_map.key?(key)
14
+ Orthoses.logger.warn("#{@decl.name}::#{member_to_s(member)} was droped since duplication")
15
+ else
16
+ uniq_map[key] = member
17
+ end
18
+ end
19
+ drop_known_method_definition(uniq_map)
20
+ @decl.members.replace(uniq_map.values.reverse)
21
+ end
22
+
23
+ private
24
+
25
+ def drop_known_method_definition(uniq_map)
26
+ env = Utils.rbs_environment(collection: true)
27
+ if m_entry = env.class_decls[@decl.name.absolute!]
28
+ m_entry.decls.each do |d|
29
+ d.decl.members.each do |member|
30
+ case member
31
+ when RBS::AST::Members::MethodDefinition, RBS::AST::Members::Alias
32
+ uniq_map.delete(member_key(member))
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ def member_to_s(member)
40
+ out = StringIO.new
41
+ RBS::Writer.new(out: out).write_member(member)
42
+ out.string.chomp
43
+ end
44
+
45
+ def member_key(member)
46
+ case member
47
+ when RBS::AST::Members::MethodDefinition
48
+ # member.types.hash is different
49
+ [member.class, member.name, member.kind]
50
+ when RBS::AST::Members::LocationOnly
51
+ [member.class]
52
+ when RBS::AST::Members::Alias
53
+ [RBS::AST::Members::MethodDefinition, member.new_name, member.kind]
54
+ else
55
+ [member.class, member.name]
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,72 @@
1
+ module Orthoses
2
+ class Content
3
+ class Environment
4
+ def initialize(constant_filter: nil, mixin_filter: nil)
5
+ @load_env = RBS::Environment.new
6
+ @known_env = Utils.rbs_environment(collection: true)
7
+ @constant_filter = constant_filter
8
+ @mixin_filter = mixin_filter
9
+ end
10
+
11
+ def <<(decl)
12
+ if known_class_entry = @known_env.class_decls[decl.name.absolute!]
13
+ decl.type_params.replace(known_class_entry.primary.decl.type_params)
14
+ end
15
+ @load_env << decl
16
+ rescue RBS::DuplicatedDeclarationError => err
17
+ Orthoses.logger.warn(err.inspect)
18
+ end
19
+
20
+ def write_to(store:)
21
+ each do |add_content|
22
+ content = store[add_content.name]
23
+ content.header ||= add_content.header
24
+ content.concat(add_content.body)
25
+ end
26
+ end
27
+
28
+ def each
29
+ header_builder = HeaderBuilder.new(env: @load_env)
30
+
31
+ @load_env.class_decls.each do |type_name, m_entry|
32
+ name = type_name.relative!.to_s
33
+ content = Content.new(name: name)
34
+ content.header = header_builder.build(entry: m_entry, name_hint: name)
35
+ decls_to_lines(m_entry.decls.map(&:decl)).each do |line|
36
+ content << line
37
+ end
38
+ yield content
39
+ end
40
+
41
+ @load_env.interface_decls.each do |type_name, s_entry|
42
+ name = type_name.relative!.to_s
43
+ content = Content.new(name: name)
44
+ content.header = header_builder.build(entry: s_entry)
45
+ decls_to_lines([s_entry.decl]).each do |line|
46
+ content << line
47
+ end
48
+ yield content
49
+ end
50
+ end
51
+
52
+ def decls_to_lines(decls)
53
+ out = StringIO.new
54
+ writer = RBS::Writer.new(out: out)
55
+ decls.each do |decl|
56
+ next unless decl.respond_to?(:members)
57
+ decl.members.each do |member|
58
+ next if member.respond_to?(:members)
59
+ case member
60
+ when RBS::AST::Declarations::Constant
61
+ next unless @constant_filter.nil? || @constant_filter.call(member)
62
+ when RBS::AST::Members::Mixin
63
+ next unless @mixin_filter.nil? || @mixin_filter.call(member)
64
+ end
65
+ writer.write_member(member)
66
+ end
67
+ end
68
+ out.string.each_line(chomp: true).to_a
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,93 @@
1
+ module Orthoses
2
+ class Content
3
+ class HeaderBuilder
4
+ def initialize(env:)
5
+ @env = env
6
+ @resolver = RBS::TypeNameResolver.from_env(env)
7
+ end
8
+
9
+ def build(entry:, name_hint: nil)
10
+ case entry
11
+ when RBS::Environment::ModuleEntry
12
+ build_module(entry: entry, name_hint: name_hint)
13
+ when RBS::Environment::ClassEntry
14
+ build_class(entry: entry, name_hint: name_hint)
15
+ when RBS::Environment::SingleEntry
16
+ build_interface(entry: entry, name_hint: name_hint)
17
+ else
18
+ raise
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def build_module(entry:, name_hint: nil)
25
+ primary = entry.primary
26
+ full_name = name_hint || primary.decl.name.relative!
27
+
28
+ self_types =
29
+ if primary.decl.self_types.empty?
30
+ nil
31
+ else
32
+ " : #{primary.decl.self_types.join(', ')}"
33
+ end
34
+
35
+ "module #{name_and_params(full_name, primary.decl.type_params)}#{self_types}"
36
+ end
37
+
38
+ def build_class(entry:, name_hint: nil)
39
+ primary = entry.primary
40
+ full_name = name_hint || primary.decl.name.relative!
41
+
42
+ "class #{name_and_params(full_name, primary.decl.type_params)}#{build_super_class(primary)}"
43
+ end
44
+
45
+ def build_super_class(primary)
46
+ return nil if primary.decl.super_class.then { |s| s.nil? || s.name.relative!.to_s.then { |n| n == "Object" || n == "Random::Base" } }
47
+
48
+ context = primary.outer.length.times.map do |i|
49
+ primary.outer[0, i + 1].map(&:name).inject(:+).to_namespace.absolute!
50
+ end
51
+
52
+ super_class_name = @resolver.resolve(primary.decl.super_class.name, context: context) || primary.decl.super_class.name
53
+ if primary.decl.super_class.args.empty?
54
+ if super_class_entry = @env.class_decls[super_class_name.absolute!]
55
+ super_primary = super_class_entry.primary
56
+ " < #{name_and_args(super_class_name, super_primary.decl.type_params.map { :untyped })}"
57
+ else
58
+ " < #{name_and_args(super_class_name, [])}"
59
+ end
60
+ else
61
+ " < #{name_and_args(super_class_name, primary.decl.super_class.args)}"
62
+ end
63
+ end
64
+
65
+ def build_interface(entry:, name_hint: nil)
66
+ full_name = name_hint || entry.decl.name.relative!
67
+ "interface #{name_and_params(full_name, entry.decl.type_params)}"
68
+ end
69
+
70
+ def name_and_params(name, params)
71
+ if params.empty?
72
+ "#{name}"
73
+ else
74
+ ps = params.each.map do |param|
75
+ param.to_s
76
+ end
77
+
78
+ "#{name}[#{ps.join(", ")}]"
79
+ end
80
+ end
81
+
82
+ def name_and_args(name, args)
83
+ if name && args
84
+ if args.empty?
85
+ "#{name}"
86
+ else
87
+ "#{name}[#{args.join(", ")}]"
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -1,5 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'orthoses/content/duplication_checker'
4
+ require 'orthoses/content/environment'
5
+ require 'orthoses/content/header_builder'
6
+
3
7
  module Orthoses
4
8
  # Common interface for output.
5
9
  # Orthoses::Content expect to use result of middleware.
@@ -17,31 +21,79 @@ module Orthoses
17
21
  attr_accessor :header
18
22
 
19
23
  def initialize(name:)
24
+ Orthoses.logger.debug("Create Orthoses::Content for #{name}")
20
25
  @name = name
21
26
  @body = []
22
27
  @header = nil
23
28
  end
24
29
 
25
30
  def <<(line)
26
- Orthoses.logger.debug("[#{name}] << #{line} on #{__FILE__}:#{__LINE__}")
27
31
  @body << line
28
32
  end
29
33
 
30
34
  def concat(other)
31
- Orthoses.logger.debug("[#{name}] concat #{other} on #{__FILE__}:#{__LINE__}")
32
35
  @body.concat(other)
33
36
  end
34
37
 
35
38
  def to_rbs
36
- if @header.nil?
37
- auto_header
38
- end
39
- body_uniq("#{@header}\n#{@body.map { |b| " #{b}\n" }.join}end\n")
39
+ auto_header
40
+ uniqed_body_string
41
+ end
42
+
43
+ def to_decl
44
+ auto_header
45
+ uniqed_body_decl
40
46
  end
41
47
 
42
48
  private
43
49
 
50
+ def original_rbs
51
+ <<~RBS
52
+ #{@header}
53
+ #{@body.join("\n")}
54
+ end
55
+ RBS
56
+ end
57
+
58
+ def uniqed_body_string
59
+ out = StringIO.new
60
+ writer = RBS::Writer.new(out: out)
61
+ writer.write_decl(uniqed_body_decl)
62
+ out.string
63
+ end
64
+
65
+ def uniqed_body_decl
66
+ buffer = RBS::Buffer.new(
67
+ name: "orthoses/content.rb",
68
+ content: original_rbs
69
+ )
70
+ parsed_decls = RBS::Parser.parse_signature(buffer)
71
+ unless parsed_decls.length == 1
72
+ raise "expect decls.length == 1, but got #{parsed_decls.length}"
73
+ end
74
+ parsed_decl = parsed_decls.first or raise
75
+ parsed_decl.tap do |decl|
76
+ DuplicationChecker.new(decl).update_decl
77
+ end
78
+ rescue RBS::ParsingError
79
+ Orthoses.logger.error "```rbs\n#{original_rbs}```"
80
+ raise
81
+ end
82
+
44
83
  def auto_header
84
+ if name.split('::').last.start_with?('_')
85
+ self.header = "interface #{name}"
86
+ return
87
+ end
88
+
89
+ env = Utils.rbs_environment(collection: true)
90
+ if entry = env.class_decls[TypeName(name).absolute!]
91
+ @header = Content::HeaderBuilder.new(env: env).build(entry: entry)
92
+ return
93
+ end
94
+
95
+ return unless @header.nil?
96
+
45
97
  val = Object.const_get(name)
46
98
 
47
99
  case val
@@ -85,29 +137,5 @@ module Orthoses
85
137
  end
86
138
  end
87
139
  end
88
-
89
- def body_uniq(rbs)
90
- buffer = RBS::Buffer.new(
91
- name: "orthoses/content.rb",
92
- content: rbs
93
- )
94
- out = StringIO.new
95
- writer = RBS::Writer.new(out: out)
96
- decls = RBS::Parser.parse_signature(buffer).map do |parsed_decl|
97
- before_members = parsed_decl.members.dup
98
- parsed_decl.members.uniq! { |m| [m.class, m.respond_to?(:name) ? m.name : nil] }
99
- (before_members - parsed_decl.members).each do |droped_member|
100
- Orthoses.logger.warn("#{parsed_decl.name}::#{droped_member.name.to_s}: #{droped_member.to_s} was droped since duplication")
101
- end
102
- parsed_decl
103
- end
104
- writer.write(decls)
105
- out.string
106
- rescue RBS::ParsingError
107
- puts "```rbs"
108
- puts rbs
109
- puts "```"
110
- raise
111
- end
112
140
  end
113
141
  end
@@ -28,6 +28,12 @@ module Orthoses
28
28
  store = @loader.call
29
29
 
30
30
  store.each do |name, content|
31
+ rbs = begin
32
+ content.to_rbs
33
+ rescue NameError, LoadError => err
34
+ Orthoses.logger.error(err.inspect)
35
+ next
36
+ end
31
37
  file_path = Pathname("#{@base_dir}/#{name.to_s.split('::').map(&:underscore).join('/')}.rbs")
32
38
  file_path.dirname.mkpath
33
39
  file_path.open('w+') do |out|
@@ -35,7 +41,7 @@ module Orthoses
35
41
  out.puts @header
36
42
  out.puts
37
43
  end
38
- out.puts content.to_rbs
44
+ out.puts rbs
39
45
  end
40
46
  Orthoses.logger.info("Generate file to #{file_path.to_s}")
41
47
  end
@@ -29,17 +29,22 @@ module Orthoses
29
29
  next unless subclass_name
30
30
  delegate_to_class_name = Utils.module_name(delegate_to_class)
31
31
  next unless delegate_to_class_name
32
- store[subclass_name].header = "class #{subclass_name} < #{delegate_to_class_name}"
32
+
33
+ header = "class #{subclass_name} < ::#{delegate_to_class_name}#{temporary_type_params(delegate_to_class_name)}"
34
+ store[subclass_name].header = header
33
35
  end
34
36
  end
35
37
  store
36
38
  end
37
39
 
38
- def from_DelegateClass?(klass)
39
- klass.name.nil? &&
40
- klass.superclass == Delegator &&
41
- klass.instance_methods.include?(:__setobj__) &&
42
- klass.instance_method(:__setobj__).source_location.first.end_with?("delegate.rb")
40
+ def temporary_type_params(name)
41
+ Utils.known_type_params(name)&.then do |params|
42
+ if params.empty?
43
+ nil
44
+ else
45
+ "[#{params.map { :untyped }.join(', ')}]"
46
+ end
47
+ end
43
48
  end
44
49
  end
45
50
  end
@@ -11,79 +11,16 @@ module Orthoses
11
11
 
12
12
  def call
13
13
  @loader.call.tap do |store|
14
- tmp_env = RBS::Environment.new
15
-
14
+ env = Content::Environment.new
16
15
  @paths.each do |path|
17
16
  Orthoses.logger.debug("Load #{path}")
18
17
  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)
18
+ RBS::Parser.parse_signature(buffer).each do |decl|
19
+ env << decl
83
20
  end
84
21
  end
22
+ env.write_to(store: store)
85
23
  end
86
- out.string.each_line(chomp: true).to_a
87
24
  end
88
25
  end
89
26
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Orthoses
4
- class IncludeExtendPrepend
4
+ class Mixin
5
5
  def initialize(loader, if: nil)
6
6
  @loader = loader
7
7
  @if = binding.local_variable_get(:if)
@@ -37,15 +37,7 @@ module Orthoses
37
37
  next unless known_type_params.nil? || known_type_params.empty?
38
38
  next unless @if.nil? || @if.call(base_mod, how, mod)
39
39
 
40
- if base_mod_name == "Object"
41
- # avoid RecursiveAncestorError
42
- content = store[mod_name]
43
- if content.header.nil?
44
- content.header = "module #{Utils.module_to_type_name(mod)} : ::BasicObject"
45
- end
46
- else
47
- store[mod_name]
48
- end
40
+ store[mod_name]
49
41
 
50
42
  "#{how} #{mod_name}"
51
43
  end
@@ -0,0 +1,35 @@
1
+ module Orthoses
2
+ # Call `rbs prototype rb` and add to store
3
+ # use Orthoses::RBSPrototypeRB,
4
+ # paths: Dir.glob("lib/**/*.rb")
5
+ class RBSPrototypeRB
6
+ def initialize(loader, paths:, constant_filter: nil, mixin_filter: nil)
7
+ @loader = loader
8
+ @paths = paths
9
+ @constant_filter = constant_filter
10
+ @mixin_filter = mixin_filter
11
+ end
12
+
13
+ def call
14
+ @loader.call.tap do |store|
15
+ parser = RBS::Prototype::RB.new
16
+ @paths.each do |path|
17
+ begin
18
+ Orthoses.logger.debug("parse #{path} by RBS::Prototype::RB")
19
+ parser.parse File.read(path.to_s)
20
+ rescue => err
21
+ Orthoses.logger.error("Parse error #{err.inspect} by RBS::Prototype::RB #{path}")
22
+ end
23
+ end
24
+ env = Orthoses::Content::Environment.new(
25
+ constant_filter: @constant_filter,
26
+ mixin_filter: @mixin_filter,
27
+ )
28
+ parser.decls.each do |decl|
29
+ env << decl
30
+ end
31
+ env.write_to(store: store)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -63,11 +63,11 @@ module Orthoses
63
63
  when "stdlib"
64
64
  RBS::Repository::DEFAULT_STDLIB_ROOT.each_entry do |path|
65
65
  lib = path.to_s
66
- loader.add(library: lib.to_s) unless lib == "." || lib == ".."
66
+ loader.add(library: lib.to_s, version: nil) unless lib == "." || lib == ".."
67
67
  end
68
68
  else
69
69
  Array(library).each do |lib|
70
- loader.add(library: lib.to_s)
70
+ loader.add(library: lib.to_s, version: nil)
71
71
  end
72
72
  end
73
73
 
@@ -117,10 +117,13 @@ module Orthoses
117
117
  "{ #{object.map { |k, v| "#{k}: #{object_to_rbs(v, strict: strict)}" }.join(', ')} }"
118
118
  else
119
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
120
+ values = object.values.map { |v| object_to_rbs(v, strict: strict) }.uniq
121
121
  "Hash[#{keys.join(' | ')}, #{values.join(' | ')}]"
122
122
  end
123
123
  end
124
+ when ARGF
125
+ # see also https://github.com/ruby/rbs/pull/975
126
+ 'untyped'
124
127
  else
125
128
  Utils.module_name(object.class) || 'untyped'
126
129
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Orthoses
4
- VERSION = "0.1.0"
4
+ VERSION = "0.4.0"
5
5
  end
@@ -0,0 +1,16 @@
1
+ module Orthoses
2
+ class Writer
3
+ def initialize(loader, io:)
4
+ @loader = loader
5
+ @io = io
6
+ end
7
+
8
+ def call
9
+ @loader.call.tap do |store|
10
+ store.each do |name, content|
11
+ @io.write content.to_rbs
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
data/lib/orthoses.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require 'rbs'
4
4
  require 'pathname'
5
5
 
6
+ require_relative 'orthoses/avoid_recursive_ancestor_error'
6
7
  require_relative 'orthoses/builder'
7
8
  require_relative 'orthoses/call_tracer'
8
9
  require_relative 'orthoses/constant'
@@ -10,15 +11,17 @@ require_relative 'orthoses/content'
10
11
  require_relative 'orthoses/create_file_by_name'
11
12
  require_relative 'orthoses/delegate_class'
12
13
  require_relative 'orthoses/filter'
13
- require_relative 'orthoses/include_extend_prepend'
14
+ require_relative 'orthoses/mixin'
14
15
  require_relative 'orthoses/load_rbs'
15
16
  require_relative 'orthoses/object_space_all'
16
17
  require_relative 'orthoses/pp'
18
+ require_relative 'orthoses/rbs_prototype_rb'
17
19
  require_relative 'orthoses/store'
18
20
  require_relative 'orthoses/tap'
19
21
  require_relative 'orthoses/utils'
20
22
  require_relative 'orthoses/version'
21
23
  require_relative 'orthoses/walk'
24
+ require_relative 'orthoses/writer'
22
25
 
23
26
  module Orthoses
24
27
  class ConstLoadError < StandardError
@@ -0,0 +1,7 @@
1
+ # THIS IS GENERATED CODE from `$ rake generate_self_sig`
2
+
3
+ class Orthoses::AvoidRecursiveAncestorError
4
+ @loader: Orthoses::_Call
5
+ include Orthoses::_MiddleWare
6
+ def initialize: (Orthoses::_Call loader) -> void
7
+ end
@@ -2,4 +2,5 @@
2
2
 
3
3
  class Orthoses::CallTracer
4
4
  attr_accessor result: Array[[ Method, Hash[Symbol, untyped] ]]
5
+ def trace: [T] (Method | UnboundMethod) ?{ () -> T } -> T
5
6
  end
@@ -0,0 +1,4 @@
1
+ # THIS IS GENERATED CODE from `$ rake generate_self_sig`
2
+
3
+ class Orthoses::Content::DuplicationChecker
4
+ end
@@ -0,0 +1,13 @@
1
+ # THIS IS GENERATED CODE from `$ rake generate_self_sig`
2
+
3
+ class Orthoses::Content::Environment
4
+ type constant_filter = ^(RBS::AST::Declarations::Constant) -> boolish
5
+ type mixin_filter = ^(RBS::AST::Members::Mixin) -> boolish
6
+ @env: RBS::Environment
7
+ @constant_filter: constant_filter?
8
+ @mixin_filter: mixin_filter?
9
+ def initialize: (?constant_filter: constant_filter?, ?mixin_filter: mixin_filter?) -> void
10
+ def <<: (RBS::AST::Declarations::t decl) -> RBS::Environment
11
+ def write_to: (store: Orthoses::store) -> void
12
+ def each: () { (Orthoses::Content) -> void } -> void
13
+ end
@@ -8,4 +8,7 @@ class Orthoses::Content
8
8
  def <<: (String) -> void
9
9
  def concat: (Array[String]) -> void
10
10
  def to_rbs: () -> String
11
+ private
12
+ def uniqed_body_string: () -> String
13
+ def uniqed_body_decl: () -> RBS::AST::Declarations::t
11
14
  end
@@ -1,4 +1,7 @@
1
1
  # THIS IS GENERATED CODE from `$ rake generate_self_sig`
2
2
 
3
3
  class Orthoses::DelegateClass
4
+ @loader: Orthoses::_Call
5
+ include Orthoses::_MiddleWare
6
+ def initialize: (Orthoses::_Call loader) -> void
4
7
  end
@@ -1,4 +1,8 @@
1
1
  # THIS IS GENERATED CODE from `$ rake generate_self_sig`
2
2
 
3
3
  class Orthoses::LoadRBS
4
+ @loader: Orthoses::_Call
5
+ @paths: Array[_ToS]
6
+ include Orthoses::_MiddleWare
7
+ def initialize: (Orthoses::_Call loader, paths: Array[_ToS]) -> void
4
8
  end
@@ -1,4 +1,4 @@
1
1
  # THIS IS GENERATED CODE from `$ rake generate_self_sig`
2
2
 
3
- class Orthoses::IncludeExtendPrepend
3
+ class Orthoses::Mixin
4
4
  end
@@ -1,4 +1,7 @@
1
1
  # THIS IS GENERATED CODE from `$ rake generate_self_sig`
2
2
 
3
3
  class Orthoses::ObjectSpaceAll
4
+ @loader: Orthoses::_Call
5
+ include Orthoses::_MiddleWare
6
+ def initialize: (Orthoses::_Call loader, ?if: ^(Module) -> boolish) -> void
4
7
  end
@@ -0,0 +1,10 @@
1
+ # THIS IS GENERATED CODE from `$ rake generate_self_sig`
2
+
3
+ class Orthoses::RBSPrototypeRB
4
+ @loader: Orthoses::_Call
5
+ include Orthoses::_MiddleWare
6
+ def initialize: (Orthoses::_Call loader, paths: Array[_ToS], ?constant_filter: Orthoses::Content::Environment::constant_filter?, ?mixin_filter: Orthoses::Content::Environment::mixin_filter?) -> void
7
+ @paths: Array[_ToS]
8
+ @constant_filter: Orthoses::Content::Environment::constant_filter?
9
+ @mixin_filter: Orthoses::Content::Environment::mixin_filter?
10
+ end
data/sig/orthoses/tap.rbs CHANGED
@@ -1,4 +1,7 @@
1
1
  # THIS IS GENERATED CODE from `$ rake generate_self_sig`
2
2
 
3
3
  class Orthoses::Tap
4
+ @loader: Orthoses::_Call
5
+ include Orthoses::_MiddleWare
6
+ def initialize: (Orthoses::_Call loader) -> void
4
7
  end
@@ -0,0 +1,7 @@
1
+ # THIS IS GENERATED CODE from `$ rake generate_self_sig`
2
+
3
+ class Orthoses::Writer
4
+ @loader: Orthoses::_Call
5
+ include Orthoses::_MiddleWare
6
+ def initialize: (Orthoses::_Call loader, io: _Writer) -> void
7
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: orthoses
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ksss
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-05-08 00:00:00.000000000 Z
11
+ date: 2022-05-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rbs
@@ -33,47 +33,62 @@ extra_rdoc_files: []
33
33
  files:
34
34
  - CODE_OF_CONDUCT.md
35
35
  - Gemfile
36
+ - Gemfile.lock
36
37
  - LICENSE.txt
37
38
  - README.md
39
+ - examples/minitest/Rakefile
40
+ - examples/simple_middleware.rb
41
+ - examples/simple_middleware.rbs
38
42
  - lib/orthoses.rb
43
+ - lib/orthoses/avoid_recursive_ancestor_error.rb
39
44
  - lib/orthoses/builder.rb
40
45
  - lib/orthoses/call_tracer.rb
41
46
  - lib/orthoses/constant.rb
42
47
  - lib/orthoses/content.rb
48
+ - lib/orthoses/content/duplication_checker.rb
49
+ - lib/orthoses/content/environment.rb
50
+ - lib/orthoses/content/header_builder.rb
43
51
  - lib/orthoses/create_file_by_name.rb
44
52
  - lib/orthoses/delegate_class.rb
45
53
  - lib/orthoses/filter.rb
46
- - lib/orthoses/include_extend_prepend.rb
47
54
  - lib/orthoses/load_rbs.rb
55
+ - lib/orthoses/mixin.rb
48
56
  - lib/orthoses/object_space_all.rb
49
57
  - lib/orthoses/pp.rb
58
+ - lib/orthoses/rbs_prototype_rb.rb
50
59
  - lib/orthoses/store.rb
51
60
  - lib/orthoses/tap.rb
52
61
  - lib/orthoses/utils.rb
53
62
  - lib/orthoses/version.rb
54
63
  - lib/orthoses/walk.rb
64
+ - lib/orthoses/writer.rb
55
65
  - orthoses.gemspec
56
66
  - sig/orthoses.rbs
57
67
  - sig/orthoses/_call.rbs
58
68
  - sig/orthoses/_middle_ware.rbs
69
+ - sig/orthoses/avoid_recursive_ancestor_error.rbs
59
70
  - sig/orthoses/builder.rbs
60
71
  - sig/orthoses/builder/call_logable.rbs
61
72
  - sig/orthoses/call_tracer.rbs
62
73
  - sig/orthoses/const_load_error.rbs
63
74
  - sig/orthoses/constant.rbs
64
75
  - sig/orthoses/content.rbs
76
+ - sig/orthoses/content/duplication_checker.rbs
77
+ - sig/orthoses/content/environment.rbs
65
78
  - sig/orthoses/create_file_by_name.rbs
66
79
  - sig/orthoses/delegate_class.rbs
67
80
  - sig/orthoses/filter.rbs
68
- - sig/orthoses/include_extend_prepend.rbs
69
81
  - sig/orthoses/load_rbs.rbs
82
+ - sig/orthoses/mixin.rbs
70
83
  - sig/orthoses/name_space_error.rbs
71
84
  - sig/orthoses/object_space_all.rbs
72
85
  - sig/orthoses/pp.rbs
86
+ - sig/orthoses/rbs_prototype_rb.rbs
73
87
  - sig/orthoses/store.rbs
74
88
  - sig/orthoses/tap.rbs
75
89
  - sig/orthoses/utils.rbs
76
90
  - sig/orthoses/walk.rbs
91
+ - sig/orthoses/writer.rbs
77
92
  homepage: https://github.com/ksss/orthoses
78
93
  licenses:
79
94
  - MIT
@@ -95,7 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
110
  - !ruby/object:Gem::Version
96
111
  version: '0'
97
112
  requirements: []
98
- rubygems_version: 3.4.0.dev
113
+ rubygems_version: 3.3.7
99
114
  signing_key:
100
115
  specification_version: 4
101
116
  summary: Framework for Generate RBS