Skip to content

Commit bd25765

Browse files
committed
Support A = Data.define(:a, :b, :c)
1 parent efb33b5 commit bd25765

File tree

3 files changed

+68
-2
lines changed

3 files changed

+68
-2
lines changed

lib/yard/handlers/ruby/constant_handler.rb

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ class YARD::Handlers::Ruby::ConstantHandler < YARD::Handlers::Ruby::Base
99
if statement[1].call? && statement[1][0][0] == s(:const, "Struct") &&
1010
statement[1][2] == s(:ident, "new")
1111
process_structclass(statement)
12+
elsif statement[1].call? && statement[1][0][0] == s(:const, "Data") &&
13+
statement[1][2] == s(:ident, "define")
14+
process_dataclass(statement)
1215
elsif statement[0].type == :var_field && statement[0][0].type == :const
1316
process_constant(statement)
1417
elsif statement[0].type == :const_path_field
@@ -41,10 +44,24 @@ def process_structclass(statement)
4144
end
4245
end
4346

44-
# Extract the parameters from the Struct.new AST node, returning them as a list
47+
def process_dataclass(statement)
48+
lhs = statement[0]
49+
if (lhs.type == :var_field && lhs[0].type == :const) || lhs.type == :const_path_field
50+
klass = create_class(lhs.source, P(:Data))
51+
extract_parameters(statement[1]).each do |member|
52+
klass.attributes[:instance][member] = SymbolHash[:read => nil, :write => nil]
53+
create_reader(klass, member)
54+
end
55+
parse_block(statement[1].block[1], :namespace => klass) unless statement[1].block.nil?
56+
else
57+
raise YARD::Parser::UndocumentableError, "Data assignment to #{lhs.source}"
58+
end
59+
end
60+
61+
# Extract the parameters from the Struct.new or Data.define AST node, returning them as a list
4562
# of strings
4663
#
47-
# @param [MethodCallNode] superclass the AST node for the Struct.new call
64+
# @param [MethodCallNode] superclass the AST node for the Struct.new or Data.define call
4865
# @return [Array<String>] the member names to generate methods for
4966
def extract_parameters(superclass)
5067
return [] unless superclass.parameters

spec/handlers/constant_handler_spec.rb

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,48 @@
7373
expect(a3.tag(:return).types).to eq ["Symbol"]
7474
end
7575

76+
it "turns Const = Data.define(:sym) into class Const with attr reader :sym" do
77+
obj = Registry.at("MyData")
78+
expect(obj).to be_kind_of(CodeObjects::ClassObject)
79+
expect(obj.superclass).to eq P(:Data)
80+
attrs = obj.attributes[:instance]
81+
[:a, :b, :c].each do |key|
82+
expect(attrs).to have_key(key)
83+
expect(attrs[key][:read]).not_to be nil
84+
expect(attrs[key][:write]).to be nil
85+
end
86+
end
87+
88+
it "turns Const = Data.define into empty data class" do
89+
obj = Registry.at("MyEmptyData")
90+
expect(obj).to be_kind_of(CodeObjects::ClassObject)
91+
expect(obj.superclass).to eq P(:Data)
92+
expect(obj.attributes[:instance]).to be_empty
93+
end
94+
95+
it "turns A::Const = Data.define(:sym) into class A::Const with attr reader :sym" do
96+
obj = Registry.at("A::NestedCompactData")
97+
expect(obj).to be_kind_of(CodeObjects::ClassObject)
98+
attrs = obj.attributes[:instance]
99+
[:b, :c].each do |key|
100+
expect(attrs).to have_key(key)
101+
expect(attrs[key][:read]).not_to be nil
102+
expect(attrs[key][:write]).to be nil
103+
end
104+
end
105+
106+
it "documents block for Data.define if present" do
107+
obj = Registry.at("MyDataWithMethods")
108+
expect(obj).to be_kind_of(CodeObjects::ClassObject)
109+
attrs = obj.attributes[:instance]
110+
[:c, :d].each do |key|
111+
expect(attrs).to have_key(key)
112+
expect(attrs[key][:read]).not_to be nil
113+
expect(attrs[key][:write]).to be nil
114+
end
115+
expect(obj.meths).to include(P("MyDataWithMethods#foo"))
116+
end
117+
76118
it "raises undocumentable error in 1.9 parser for Struct.new assignment to non-const" do
77119
undoc_error "nonconst = Struct.new"
78120
end unless LEGACY_PARSER

spec/handlers/examples/constant_handler_001.rb.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,10 @@ end
3333
# Attribute defined with the new syntax
3434
# @return [Symbol] something useful
3535
DocstringStruct = Struct.new(:bar, :baz, :new_syntax)
36+
37+
MyData = Data.define(:a, :b, :c)
38+
MyEmptyData = Data.define
39+
A::NestedCompactData = Data.define(:b, :c)
40+
MyDataWithMethods = Data.define(:c, :d) do
41+
def foo; end
42+
end

0 commit comments

Comments
 (0)