Class: Rice::Rbs

Inherits:
Object
  • Object
show all
Defined in:
lib/rice/rbs.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(extension, output) ⇒ Rbs

Returns a new instance of Rbs.



8
9
10
11
# File 'lib/rice/rbs.rb', line 8

def initialize(extension, output)
  @extension = extension
  @output = output
end

Instance Attribute Details

#extensionObject (readonly)

Returns the value of attribute extension.



6
7
8
# File 'lib/rice/rbs.rb', line 6

def extension
  @extension
end

#outputObject (readonly)

Returns the value of attribute output.



6
7
8
# File 'lib/rice/rbs.rb', line 6

def output
  @output
end

Instance Method Details

#attribute_sig(native_attributes) ⇒ Object



49
50
51
52
53
54
55
56
57
58
# File 'lib/rice/rbs.rb', line 49

def attribute_sig(native_attributes)
  attr_type = if native_attributes.size == 2
               "attr_accessor"
             elsif native_attributes.first.kind == Rice::NativeKind::AttributeReader
               "attr_reader"
             else
               "attr_writer"
             end
  "#{attr_type} #{native_attributes.first.name}: #{native_attributes.first.return_klass}"
end

#generateObject



13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/rice/rbs.rb', line 13

def generate
  STDOUT << "Writing rbs files to #{@output}" << "\n"

  # Add the extension directory the path in case it ships with extra libraries
  ENV["PATH"] = "#{File.dirname(self.extension)}#{File::PATH_SEPARATOR}#{ENV["PATH"]}"
  require self.extension

  types = Registries.instance.types
  types.klasses.each do |klass|
    process_class(klass)
  end
end

#method_sig(native) ⇒ Object



68
69
70
71
72
73
# File 'lib/rice/rbs.rb', line 68

def method_sig(native)
  params = native.parameters.map do |parameter|
    "#{parameter.arg.name}: #{parameter.klass}"
  end.join(", ")
  "(#{params}) -> #{native.return_klass}"
end

#method_sigs(native_methods, indent = 0) ⇒ Object



60
61
62
63
64
65
66
# File 'lib/rice/rbs.rb', line 60

def method_sigs(native_methods, indent = 0)
  join_string = "\n" + (" " * indent) + "| "
  a = native_methods.map do |native_method|
    method_sig(native_method)
  end
  a.join(join_string)
end

#process_class(klass) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/rice/rbs.rb', line 26

def process_class(klass)
  STDOUT << "  " << klass << "\n"

  native_attributes = Registries.instance.natives.native_attributes(klass).sort.group_by(&:name)
  native_functions = Registries.instance.natives.native_functions(klass).sort.group_by(&:name)
  native_methods = Registries.instance.natives.native_methods(klass).sort.group_by(&:name)
  content = render_template("class", :klass => klass,
                            :native_attributes => native_attributes,
                            :native_functions => native_functions,
                            :native_methods => native_methods)
  write_file(klass, content)
end

#render_template(template, local_variables = {}) ⇒ Object



75
76
77
78
79
80
81
82
# File 'lib/rice/rbs.rb', line 75

def render_template(template, local_variables = {})
  template = ERB.new(self.template, :trim_mode => '-')
  b = self.binding
  local_variables.each do |key, value|
    b.local_variable_set(key, value)
  end
  template.result(b)
end

#templateObject



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/rice/rbs.rb', line 84

def template
  <<~EOS
    module <%= klass.name.split("::")[0..-2].join("::") %>
      class <%= klass.name.split("::").last %>
      <%- native_functions.each do |name, functions| -%>
        def self.<%= name %>: <%= method_sigs(functions, name.length + 5) %>
      <%- end -%>
    <%= native_functions.empty? ? "" : "\n" -%>
      <%- native_attributes.each do |name, attributes| -%>
        <%= attribute_sig(attributes) %>
      <%- end -%>
    <%= native_attributes.empty? ? "" : "\n" -%>
      <%- native_methods.each do |name, methods| -%>
        def <%= name %>: <%= method_sigs(methods, name.length + 5) %>
      <%- end -%>
      end
    end
  EOS
end

#write_file(klass, content) ⇒ Object



39
40
41
42
43
44
45
46
47
# File 'lib/rice/rbs.rb', line 39

def write_file(klass, content)
  parts = klass.name.split("::")
  file_name = "#{parts.pop}.rbs"
  dir = File.join(self.output, *parts)
  FileUtils.mkdir_p(dir)

  path = File.join(dir, file_name)
  File.write(path, content, mode: "wb")
end