Class: RbsActivesupport::Generator

Inherits:
Object
  • Object
show all
Includes:
AST
Defined in:
lib/rbs_activesupport/generator.rb,
sig/rbs_activesupport/generator.rbs

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from AST

#eval_args_with_options, #eval_include_args, #eval_node

Constructor Details

#initialize(pathname, rbs_builder) ⇒ Generator

Returns a new instance of Generator.

Parameters:

  • pathname (Pathname)
  • rbs_builder (RBS::DefinitionBuilder)


20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/rbs_activesupport/generator.rb', line 20

def initialize(pathname, rbs_builder) #: void
  @pathname = pathname

  method_searcher = MethodSearcher.new(rbs_builder)
  resolver = if Gem::Version.new("3.10.0") <= Gem::Version.new(RBS::VERSION)
               RBS::Resolver::TypeNameResolver.build(rbs_builder.env)
             else
               # TypeNameResolver.new was deprecated in RBS 3.10.0
               RBS::Resolver::TypeNameResolver.new(rbs_builder.env) # steep:ignore
             end
  @declaration_builder = DeclarationBuilder.new(resolver, method_searcher)
end

Instance Attribute Details

#declaration_builderDeclarationBuilder (readonly)

: DeclarationBuilder

Returns:



16
17
18
# File 'lib/rbs_activesupport/generator.rb', line 16

def declaration_builder
  @declaration_builder
end

#pathnamePathname (readonly)

: Pathname

Returns:

  • (Pathname)


15
16
17
# File 'lib/rbs_activesupport/generator.rb', line 15

def pathname
  @pathname
end

Class Method Details

.generate(pathname, rbs_builder) ⇒ String?

Parameters:

  • pathname (Pathname)
  • rbs_builder (RBS::DefinitionBuilder)

Returns:

  • (String, nil)


7
8
9
10
11
# File 'lib/rbs_activesupport/generator.rb', line 7

def self.generate(pathname, rbs_builder) #: String?
  new(pathname, rbs_builder).generate
rescue StandardError
  warn "Failed to generate RBS for #{pathname}"
end

Instance Method Details

Parameters:

  • namespace (RBS::Namespace)

Returns:

  • (String)


95
96
97
# File 'lib/rbs_activesupport/generator.rb', line 95

def footer(namespace) #: String
  "end\n" * namespace.path.size
end

#format(rbs) ⇒ String

Parameters:

  • rbs (String)

Returns:

  • (String)


63
64
65
66
67
68
# File 'lib/rbs_activesupport/generator.rb', line 63

def format(rbs) #: String
  parsed = RBS::Parser.parse_signature(rbs)
  StringIO.new.tap do |out|
    RBS::Writer.new(out:).write(parsed[1] + parsed[2])
  end.string
end

#generateString?

: String?

Returns:

  • (String, nil)


33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/rbs_activesupport/generator.rb', line 33

def generate #: String?
  declarations = parse_source_code
  return if declarations.empty?

  definition = declarations.map do |namespace, method_calls|
    public_decls, private_decls = declaration_builder.build(namespace, method_calls)
    next if public_decls.empty? && private_decls.empty?

    "      # resolve-type-names: false\n\n      \#{header(namespace)}\n      \#{public_decls.join(\"\\n\")}\n\n      \#{\"private\" if private_decls.any?}\n\n      \#{private_decls.join(\"\\n\")}\n\n      \#{footer(namespace)}\n    RBS\n  end.compact.join(\"\\n\")\n\n  return if definition.empty?\n\n  format(definition)\nend\n"

#header(namespace) ⇒ String

Parameters:

  • namespace (RBS::Namespace)

Returns:

  • (String)


77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/rbs_activesupport/generator.rb', line 77

def header(namespace) #: String
  namespace_to_names(namespace).map do |name|
    mod_object = Object.const_get(name.to_s)
    case mod_object
    when Class
      superclass = mod_object.superclass
      superclass_name = superclass&.name || "::Object"

      "class #{name} < ::#{superclass_name}"
    when Module
      "module #{name}"
    else
      raise "unreachable"
    end
  end.join("\n")
end

#namespace_to_names(namespace) ⇒ Array[RBS::TypeName]

Parameters:

  • namespace (RBS::Namespace)

Returns:

  • (Array[RBS::TypeName])


100
101
102
103
104
105
106
107
# File 'lib/rbs_activesupport/generator.rb', line 100

def namespace_to_names(namespace) #: Array[RBS::TypeName]
  names = [] #: Array[RBS::TypeName]
  until namespace.empty?
    names << namespace.to_type_name
    namespace = namespace.parent
  end
  names.reverse
end

#parse_source_codeHash[RBS::Namespace, Array[Parser::MethodCall]]

: Hash[RBS::Namespace, Array[Parser::MethodCall]]

Returns:



70
71
72
73
74
# File 'lib/rbs_activesupport/generator.rb', line 70

def parse_source_code #: Hash[RBS::Namespace, Array[Parser::MethodCall]]
  parser = Parser.new
  parser.parse(pathname.read)
  parser.method_calls
end