/
symbol_table_parser.rb
65 lines (52 loc) · 1.67 KB
/
symbol_table_parser.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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
59
60
61
62
63
64
65
# typed: strict
# frozen_string_literal: true
require "json"
require "tempfile"
module Tapioca
module Static
class SymbolTableParser
extend T::Sig
sig { params(json_string: String).returns(T::Set[String]) }
def self.parse_json(json_string)
obj = JSON.parse(json_string)
parser = SymbolTableParser.new
parser.parse_object(obj)
parser.symbols
rescue JSON::ParserError
Set.new
end
sig { returns(T::Set[String]) }
attr_reader :symbols
sig { void }
def initialize
@symbols = T.let(Set.new, T::Set[String])
@parents = T.let([], T::Array[String])
end
sig { params(object: T::Hash[String, T.untyped]).void }
def parse_object(object)
children = object.fetch("children", [])
children.each do |child|
kind = child.fetch("kind")
name = child.fetch("name")
name = name.fetch("name") if name.is_a?(Hash)
next if kind.nil? || name.nil?
# TODO: CLASS is removed since v0.4.4730 of Sorbet
# but keeping here for backward compatibility. Remove
# once the minimum version is moved past that.
next unless ["CLASS", "CLASS_OR_MODULE", "STATIC_FIELD"].include?(kind)
next if name =~ /[<>()$]/
next if name =~ /^[0-9]+$/
next if name == "T::Helpers"
@symbols.add(fully_qualified_name(name))
@parents << name
parse_object(child)
@parents.pop
end
end
sig { params(name: String).returns(String) }
def fully_qualified_name(name)
[*@parents, name].join("::")
end
end
end
end