-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparser.rb
More file actions
163 lines (145 loc) · 7.03 KB
/
parser.rb
File metadata and controls
163 lines (145 loc) · 7.03 KB
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
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# frozen_string_literal: true
require 'rbs'
module RBS
module RDocPlugin
class Parser
attr_accessor :top_level, :content
def initialize(top_level, content)
@top_level = top_level
@content = content
end
def scan
_, _, decls = ::RBS::Parser.parse_signature(@content)
decls.each do |decl|
parse_member(decl: decl, context: @top_level)
end
@top_level
end
def parse_member(decl:, context:, outer_name: nil)
case decl
when ::RBS::AST::Declarations::Class
parse_class_decl(decl: decl, context: context, outer_name: outer_name)
when ::RBS::AST::Declarations::Module
parse_module_decl(decl: decl, context: context, outer_name: outer_name)
when ::RBS::AST::Declarations::Constant
context = @top_level.find_class_or_module outer_name.to_s if outer_name
parse_constant_decl(decl: decl, context: context, outer_name: outer_name)
when ::RBS::AST::Declarations::Interface
parse_module_decl(decl: decl, context: context, outer_name: outer_name)
when ::RBS::AST::Members::MethodDefinition
context = @top_level.find_class_or_module outer_name.to_s if outer_name
parse_method_decl(decl: decl, context: context, outer_name: outer_name)
when ::RBS::AST::Members::Alias
context = @top_level.find_class_or_module outer_name.to_s if outer_name
parse_method_alias_decl(decl: decl, context: context, outer_name: outer_name)
when ::RBS::AST::Members::AttrReader, ::RBS::AST::Members::AttrWriter, ::RBS::AST::Members::AttrAccessor
context = @top_level.find_class_or_module outer_name.to_s if outer_name
parse_attr_decl(decl: decl, context: context, outer_name: outer_name)
when ::RBS::AST::Members::Include
context = @top_level.find_class_or_module outer_name.to_s if outer_name
parse_include_decl(decl: decl, context: context, outer_name: outer_name)
when ::RBS::AST::Members::Extend
context = @top_level.find_class_or_module outer_name.to_s if outer_name
parse_extend_decl(decl: decl, context: context, outer_name: outer_name)
end
end
def parse_class_decl(decl:, context:, outer_name: nil)
full_name = fully_qualified_name(outer_name: outer_name, decl: decl)
klass = context.add_class(RDoc::NormalClass, full_name.to_s, decl.super_class&.name&.to_s || "::Object")
klass.add_comment(construct_comment(context: context, comment: comment_string(decl)), context) if decl.comment
decl.members.each { |member| parse_member(decl: member, context: context, outer_name: full_name) }
end
def parse_module_decl(decl:, context:, outer_name: nil)
full_name = fully_qualified_name(outer_name: outer_name, decl: _ = decl)
kmodule = context.add_module(RDoc::NormalModule, full_name.to_s)
kmodule.add_comment(construct_comment(context: context, comment: comment_string(decl)), context) if decl.comment
decl.members.each { |member| parse_member(decl: member, context: context, outer_name: full_name) }
end
def parse_constant_decl(decl:, context:, outer_name: nil)
comment = decl.comment ? construct_comment(context: context, comment: comment_string(decl)) : nil
constant = RDoc::Constant.new(decl.name.to_s, decl.type.to_s, comment)
context.add_constant(constant)
end
def parse_method_decl(decl:, context:, outer_name: nil)
method = RDoc::AnyMethod.new(nil, decl.name.to_s)
method.singleton = decl.singleton?
method.visibility = decl.visibility
method.call_seq = decl.overloads.map {|overload| "#{decl.name.to_s}#{overload.method_type.to_s}" }.join("\n")
if loc = decl.location
method.start_collecting_tokens
method.add_token({ line_no: 1, char_no: 1, kind: :on_comment, text: "# File #{@top_level.relative_name}, line(s) #{loc.start_line}:#{loc.end_line}\n" })
method.add_token({ line_no: 1, char_no: 1, text: loc.source })
method.line = loc.start_line
end
method.comment = construct_comment(context: context, comment: comment_string(decl)) if decl.comment
context.add_method(method)
end
def parse_method_alias_decl(decl:, context:, outer_name: nil)
alias_def = RDoc::Alias.new(nil, decl.old_name.to_s, decl.new_name.to_s, nil, singleton: decl.kind == :singleton)
alias_def.comment = construct_comment(context: context, comment: comment_string(decl)) if decl.comment
context.add_alias(alias_def)
end
def parse_attr_decl(decl:, context:, outer_name: nil)
rw = case decl
when ::RBS::AST::Members::AttrReader
'R'
when ::RBS::AST::Members::AttrWriter
'W'
when ::RBS::AST::Members::AttrAccessor
'RW'
end
attribute = RDoc::Attr.new(nil, decl.name.to_s, rw, nil, singleton: decl.kind == :singleton)
attribute.visibility = decl.visibility
attribute.comment = construct_comment(context: context, comment: comment_string(decl)) if decl.comment
context.add_attribute(attribute)
end
def parse_include_decl(decl:, context:, outer_name: nil)
name = decl.name.to_s
outer_names = outer_name ? outer_name.to_s.split("::") : [] #: Array[String]
qualified_name = ''
outer_names.each do |namespace|
qualified_name += namespace
if (module_name = @top_level.find_module_named((qualified_name += "::") + name))
name = module_name.full_name
break
end
end
include_decl = RDoc::Include.new(name, nil)
include_decl.comment = construct_comment(context: context, comment: comment_string(decl)) if decl.comment
context.add_include(include_decl)
end
def parse_extend_decl(decl:, context:, outer_name: nil)
name = decl.name.to_s
outer_names = outer_name ? outer_name.to_s.split("::") : [] #: Array[String]
qualified_name = ''
outer_names.each do |namespace|
qualified_name += namespace
if (module_name = @top_level.find_module_named((qualified_name += "::") + name))
name = module_name.full_name
break
end
end
extend_decl = RDoc::Extend.new(name, nil)
extend_decl.comment = construct_comment(context: context, comment: comment_string(decl)) if decl.comment
context.add_extend(extend_decl)
end
private
def construct_comment(context:, comment:)
comment = RDoc::Comment.new(comment, context)
comment.format = "markdown"
comment
end
def comment_string(with_comment)
comment = with_comment.comment or raise "Object with `#comment` returning a object is expected"
comment.string
end
def fully_qualified_name(outer_name:, decl:)
if outer_name
(outer_name + decl.name)
else
decl.name
end
end
end
end
end