Class: Sorbet::Private::GemGeneratorTracepoint::TracepointSerializer

Inherits:
Object
  • Object
show all
Defined in:
lib/gem-generator-tracepoint/tracepoint_serializer.rb

Constant Summary collapse

SPECIAL_METHOD_NAMES =
%w[! ~ +@ ** -@ * / % + - << >> & | ^ < <= => > >= == === != =~ !~ <=> [] []= `]
BAD_METHODS =
[
  # These methods don't match the signatures of their parents, so if we let
  # them monkeypatch, they won't be subtypes anymore. Just don't support the
  # bad monkeypatches.
  ['activesupport', 'Time', :to_s],
  ['activesupport', 'Time', :initialize],

  # These methods cause TracepointSerializer to hang the Ruby process when
  # running Ruby 2.3. See https://github.com/sorbet/sorbet/issues/1145
  ['activesupport', 'ActiveSupport::Deprecation', :new],
  ['activesupport', 'ActiveSupport::Deprecation', :allocate],
]
HEADER =
Sorbet::Private::Serialize.header('true', 'gems')

Instance Method Summary collapse

Constructor Details

#initialize(files:, delegate_classes:) ⇒ TracepointSerializer

Returns a new instance of TracepointSerializer.



35
36
37
38
39
40
41
# File 'lib/gem-generator-tracepoint/tracepoint_serializer.rb', line 35

def initialize(files:, delegate_classes:)
  @files = files
  @delegate_classes = delegate_classes

  @anonymous_map = {}
  @prev_anonymous_id = 0
end

Instance Method Details

#serialize(output_dir) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/gem-generator-tracepoint/tracepoint_serializer.rb', line 44

def serialize(output_dir)
  gem_class_defs = preprocess(@files)

  FileUtils.mkdir_p(output_dir) unless gem_class_defs.empty?

  gem_class_defs.each do |gem, klass_ids|
    File.open("#{File.join(output_dir, gem[:gem])}.rbi", 'w') do |f|
      f.write(HEADER)
      f.write("#
# If you would like to make changes to this file, great! Please create the gem's shim here:
#
#   https://github.com/sorbet/sorbet-typed/new/master?filename=lib/#{gem[:gem]}/all/#{gem[:gem]}.rbi
#
")
      f.write("# #{gem[:gem]}-#{gem[:version]}\n\n")
      klass_ids.each do |klass_id, class_def|
        klass = class_def.klass

        f.write("#{Sorbet::Private::RealStdlib.real_is_a?(klass, Class) ? 'class' : 'module'} #{class_name(klass)}")
        f.write(" < #{class_name(klass.superclass)}") if Sorbet::Private::RealStdlib.real_is_a?(klass, Class) && ![Object, nil].include?(klass.superclass)
        f.write("\n")

        rows = class_def.defs.map do |item|
          case item[:type]
          when :method
            if !valid_method_name?(item[:method])
              # warn("Invalid method name: #{klass}.#{item[:method]}")
              next
            end
            if BAD_METHODS.include?([gem[:gem], class_name(klass), item[:method]])
              next
            end
            begin
              method = item[:singleton] ? Sorbet::Private::RealStdlib.real_method(klass, item[:method]) : klass.instance_method(item[:method])

              "#{generate_method(method, !item[:singleton])}"
            rescue NameError
            end
          when :include, :extend
            name = class_name(item[item[:type]])
            "  #{item[:type]} #{name}"
          end
        end
        rows = rows.compact.sort
        f.write(rows.join("\n"))
        f.write("\n") if !rows.empty?
        f.write("end\n")
      end
    end
  end
end