Skip to content

Commit 131ad1d

Browse files
special syntax for Data subclasses
allows declaring and typing variables, inject inherited methods OTTB
1 parent 36a3d5f commit 131ad1d

File tree

4 files changed

+359
-25
lines changed

4 files changed

+359
-25
lines changed

ext/rbs_extension/parser.c

+8-1
Original file line numberDiff line numberDiff line change
@@ -1747,6 +1747,7 @@ VALUE parse_member_def(parserstate *state, bool instance_only, bool accept_overl
17471747

17481748
/**
17491749
* class_instance_name ::= {} <class_name>
1750+
* | {} Data `[` kwarg args `]`
17501751
* | {} class_name `[` type args <`]`>
17511752
*
17521753
* @param kind
@@ -1756,7 +1757,13 @@ void class_instance_name(parserstate *state, TypeNameKind kind, VALUE *name, VAL
17561757

17571758
*name = parse_type_name(state, kind, name_range);
17581759

1759-
if (state->next_token.type == pLBRACKET) {
1760+
if (CLASS_OF(*name) == RBS_TypeName && rb_funcall(*name, rb_intern("data?"), 0) == Qtrue) {
1761+
parser_advance_assert(state, pLPAREN);
1762+
args_range->start = state->current_token.range.start;
1763+
*args = parse_record_attributes(state);
1764+
parser_advance_assert(state, pRPAREN);
1765+
args_range->end = state->current_token.range.end;
1766+
} else if (state->next_token.type == pLBRACKET) {
17601767
parser_advance(state);
17611768
args_range->start = state->current_token.range.start;
17621769
parse_type_list(state, pRBRACKET, args);

lib/rbs/ast/declarations.rb

+314
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,320 @@ def to_json(state = _ = nil)
8181
location: location
8282
}.to_json(state)
8383
end
84+
85+
def self.new(name: , args:, location:)
86+
87+
return super unless name.data?
88+
89+
superklass = super(name: name, args: [], location: location)
90+
91+
args.transform_values! do |(type, required)|
92+
required ? type : Types::Optional.new(type: type, location: type.location)
93+
end
94+
95+
# attribute readers
96+
members = args.map do |k, type|
97+
Members::AttrReader.new(
98+
name: k,
99+
type: type,
100+
ivar_name: :"@#{type}",
101+
kind: :instance,
102+
location: location,
103+
comment: nil,
104+
annotations: nil
105+
)
106+
end
107+
108+
# initialize
109+
members << Members::MethodDefinition.new(
110+
name: :initialize,
111+
kind: :instance,
112+
location: location,
113+
overloading: false,
114+
comment: nil,
115+
annotations: nil,
116+
visibility: nil,
117+
overloads: [
118+
Members::MethodDefinition::Overload.new(
119+
method_type: MethodType.new(
120+
type_params: [],
121+
type: Types::Function.new(
122+
required_keywords: args.to_h { |k, type|
123+
[
124+
k,
125+
# set param
126+
Types::Function::Param.new(
127+
name: nil,
128+
type: type,
129+
location: location
130+
)
131+
]
132+
},
133+
required_positionals: [],
134+
optional_keywords: {},
135+
optional_positionals: [],
136+
rest_keywords: nil,
137+
rest_positionals: nil,
138+
trailing_positionals: [],
139+
return_type: RBS::Types::Bases::Void.new(location: location),
140+
),
141+
location: location,
142+
block: nil,
143+
),
144+
annotations: []
145+
),
146+
Members::MethodDefinition::Overload.new(
147+
method_type: MethodType.new(
148+
type_params: [],
149+
type: Types::Function.new(
150+
required_positionals: args.map { |k, type|
151+
# set param
152+
Types::Function::Param.new(
153+
name: k,
154+
type: type,
155+
location: location
156+
)
157+
},
158+
required_keywords: [],
159+
optional_keywords: {},
160+
optional_positionals: [],
161+
rest_keywords: nil,
162+
rest_positionals: nil,
163+
trailing_positionals: [],
164+
return_type: RBS::Types::Bases::Void.new(location: location),
165+
),
166+
location: location,
167+
block: nil,
168+
),
169+
annotations: []
170+
)
171+
]
172+
)
173+
174+
# members
175+
members << Members::MethodDefinition.new(
176+
name: :members,
177+
kind: :instance,
178+
location: location,
179+
overloading: false,
180+
comment: nil,
181+
annotations: nil,
182+
visibility: nil,
183+
overloads: [
184+
Members::MethodDefinition::Overload.new(
185+
method_type: MethodType.new(
186+
type_params: [],
187+
type: Types::Function.new(
188+
required_keywords: {},
189+
required_positionals: [],
190+
optional_keywords: {},
191+
optional_positionals: [],
192+
rest_keywords: nil,
193+
rest_positionals: nil,
194+
trailing_positionals: [],
195+
return_type: RBS::Types::ClassInstance.new(
196+
name: BuiltinNames::Array,
197+
args: [RBS::Types::ClassInstance.new(name: BuiltinNames::Symbol, args: [], location: location)],
198+
location: location
199+
),
200+
),
201+
location: location,
202+
block: nil,
203+
),
204+
annotations: []
205+
)
206+
]
207+
)
208+
209+
# deconstruct
210+
members << Members::MethodDefinition.new(
211+
name: :deconstruct,
212+
kind: :instance,
213+
location: location,
214+
overloading: false,
215+
comment: nil,
216+
annotations: nil,
217+
visibility: nil,
218+
overloads: [
219+
Members::MethodDefinition::Overload.new(
220+
method_type: MethodType.new(
221+
type_params: [],
222+
type: Types::Function.new(
223+
required_keywords: {},
224+
required_positionals: [],
225+
optional_keywords: {},
226+
optional_positionals: [],
227+
rest_keywords: nil,
228+
rest_positionals: nil,
229+
trailing_positionals: [],
230+
return_type: RBS::Types::Tuple.new(
231+
types: args.values.map do |type|
232+
RBS::Types::ClassInstance.new(name:type, args: [], location: location)
233+
end,
234+
location: location
235+
),
236+
),
237+
location: location,
238+
block: nil,
239+
),
240+
annotations: []
241+
)
242+
]
243+
)
244+
245+
# deconstruct_keys
246+
members << Members::MethodDefinition.new(
247+
name: :deconstruct_keys,
248+
kind: :instance,
249+
location: location,
250+
overloading: false,
251+
comment: nil,
252+
annotations: nil,
253+
visibility: nil,
254+
overloads: [
255+
Members::MethodDefinition::Overload.new(
256+
method_type: MethodType.new(
257+
type_params: [],
258+
type: Types::Function.new(
259+
required_keywords: {},
260+
required_positionals: [
261+
Types::Function::Param.new(
262+
name: nil,
263+
type: RBS::Types::Bases::Nil.new(location: location),
264+
location: location
265+
)
266+
],
267+
optional_keywords: {},
268+
optional_positionals: [],
269+
rest_keywords: nil,
270+
rest_positionals: nil,
271+
trailing_positionals: [],
272+
return_type: RBS::Types::Record.new(
273+
all_fields: args.to_h do |k, v|
274+
[
275+
k,
276+
[
277+
RBS::Types::ClassInstance.new(name: v, args: [], location: location),
278+
true
279+
]
280+
]
281+
end,
282+
location: location
283+
),
284+
),
285+
location: location,
286+
block: nil,
287+
),
288+
annotations: []
289+
),
290+
Members::MethodDefinition::Overload.new(
291+
method_type: MethodType.new(
292+
type_params: [],
293+
type: Types::Function.new(
294+
required_keywords: {},
295+
required_positionals: [
296+
Types::Function::Param.new(
297+
name: nil,
298+
type: RBS::Types::ClassInstance.new(
299+
name: BuiltinNames::Array,
300+
location: location,
301+
args: [
302+
RBS::Types::ClassInstance.new(
303+
name: BuiltinNames::Symbol,
304+
args: [],
305+
location: location
306+
)
307+
]
308+
),
309+
location: location
310+
)
311+
],
312+
optional_keywords: {},
313+
optional_positionals: [],
314+
rest_keywords: nil,
315+
rest_positionals: nil,
316+
trailing_positionals: [],
317+
return_type: RBS::Types::ClassInstance.new(
318+
name: BuiltinNames::Hash,
319+
location: location,
320+
args: [
321+
RBS::Types::ClassInstance.new(
322+
name: BuiltinNames::Symbol,
323+
args: [],
324+
location: location
325+
),
326+
RBS::Types::ClassInstance.new(
327+
name: RBS::Types::Bases::Any.new(location: location),
328+
args: [],
329+
location: location
330+
)
331+
]
332+
),
333+
),
334+
location: location,
335+
block: nil,
336+
),
337+
annotations: []
338+
)
339+
]
340+
)
341+
342+
# with
343+
members << Members::MethodDefinition.new(
344+
name: :with,
345+
kind: :instance,
346+
location: location,
347+
overloading: false,
348+
comment: nil,
349+
annotations: nil,
350+
visibility: nil,
351+
overloads: [
352+
Members::MethodDefinition::Overload.new(
353+
method_type: MethodType.new(
354+
type_params: [],
355+
type: Types::Function.new(
356+
required_keywords: {},
357+
required_positionals: [],
358+
optional_keywords: args.to_h do |k, v|
359+
[
360+
k,
361+
RBS::Types::Function::Param.new(
362+
name: nil,
363+
type: RBS::Types::ClassInstance.new(
364+
name: v,
365+
args: [],
366+
location: location
367+
),
368+
location: location
369+
)
370+
]
371+
end,
372+
optional_positionals: [],
373+
rest_keywords: nil,
374+
rest_positionals: nil,
375+
trailing_positionals: [],
376+
return_type: RBS::Types::Bases::Instance.new(
377+
location: location
378+
),
379+
),
380+
location: location,
381+
block: nil,
382+
),
383+
annotations: []
384+
)
385+
]
386+
)
387+
388+
Class.new(
389+
name: nil,
390+
type_params: nil,
391+
super_class: superklass,
392+
annotations: nil,
393+
comment: nil,
394+
location: location,
395+
members: members
396+
)
397+
end
84398
end
85399

86400
include NestedDeclarationHelper

lib/rbs/type_name.rb

+4
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ def alias?
5252
kind == :alias
5353
end
5454

55+
def data?
56+
class? && namespace.empty? && name == :Data
57+
end
58+
5559
def absolute!
5660
self.class.new(namespace: namespace.absolute!, name: name)
5761
end

0 commit comments

Comments
 (0)