@@ -17,19 +17,211 @@ def initialize(buffer)
1717 class MethodTypeAnnotation
1818 class DocStyle
1919 attr_accessor :return_type_annotation
20+ attr_reader :required_positionals
21+ attr_reader :optional_positionals
22+ attr_accessor :rest_positionals
23+ attr_reader :trailing_positionals
24+ attr_reader :required_keywords
25+ attr_reader :optional_keywords
26+ attr_accessor :rest_keywords
2027
2128 def initialize
2229 @return_type_annotation = nil
30+ @required_positionals = [ ] #: Array[Annotations::ParamTypeAnnotation?]
31+ @optional_positionals = [ ] #: Array[Annotations::ParamTypeAnnotation?]
32+ @rest_positionals = nil #: Annotations::ParamTypeAnnotation?
33+ @trailing_positionals = [ ] #: Array[Annotations::ParamTypeAnnotation?]
34+ @required_keywords = { } #: Hash[Symbol, Annotations::ParamTypeAnnotation]
35+ @optional_keywords = { } #: Hash[Symbol, Annotations::ParamTypeAnnotation]
36+ @rest_keywords = nil #: Annotations::ParamTypeAnnotation?
37+ end
38+
39+ def self . build ( param_type_annotations , return_type_annotation , node )
40+ doc = DocStyle . new
41+ doc . return_type_annotation = return_type_annotation
42+
43+ unused = param_type_annotations . dup
44+
45+ if node . parameters
46+ params = node . parameters #: Prism::ParametersNode
47+
48+ params . requireds . each do |param |
49+ if param . is_a? ( Prism ::RequiredParameterNode )
50+ annotation = unused . find { _1 . name_location . source . to_sym == param . name }
51+ if annotation
52+ unused . delete ( annotation )
53+ doc . required_positionals << annotation
54+ else
55+ doc . required_positionals << param . name
56+ end
57+ end
58+ end
59+
60+ params . optionals . each do |param |
61+ if param . is_a? ( Prism ::OptionalParameterNode )
62+ annotation = unused . find { _1 . name_location . source . to_sym == param . name }
63+ if annotation
64+ unused . delete ( annotation )
65+ doc . optional_positionals << annotation
66+ else
67+ doc . optional_positionals << param . name
68+ end
69+ end
70+ end
71+
72+ if ( rest = params . rest ) && rest . is_a? ( Prism ::RestParameterNode ) && rest . name
73+ annotation = unused . find { _1 . name_location . source . to_sym == rest . name }
74+ if annotation
75+ unused . delete ( annotation )
76+ doc . rest_positionals = annotation
77+ else
78+ doc . rest_positionals = rest . name
79+ end
80+ end
81+
82+ params . posts . each do |param |
83+ if param . is_a? ( Prism ::RequiredParameterNode )
84+ annotation = unused . find { _1 . name_location . source . to_sym == param . name }
85+ if annotation
86+ unused . delete ( annotation )
87+ doc . trailing_positionals << annotation
88+ else
89+ doc . trailing_positionals << param . name
90+ end
91+ end
92+ end
93+
94+ params . keywords . each do |param |
95+ case param
96+ when Prism ::RequiredKeywordParameterNode
97+ annotation = unused . find { _1 . name_location . source . to_sym == param . name }
98+ if annotation
99+ unused . delete ( annotation )
100+ doc . required_keywords [ param . name ] = annotation
101+ else
102+ doc . required_keywords [ param . name ] = param . name
103+ end
104+ when Prism ::OptionalKeywordParameterNode
105+ annotation = unused . find { _1 . name_location . source . to_sym == param . name }
106+ if annotation
107+ unused . delete ( annotation )
108+ doc . optional_keywords [ param . name ] = annotation
109+ else
110+ doc . optional_keywords [ param . name ] = param . name
111+ end
112+ end
113+ end
114+
115+ if ( kw_rest = params . keyword_rest ) && kw_rest . is_a? ( Prism ::KeywordRestParameterNode ) && kw_rest . name
116+ annotation = unused . find { _1 . name_location . source . to_sym == kw_rest . name }
117+ if annotation
118+ unused . delete ( annotation )
119+ doc . rest_keywords = annotation
120+ else
121+ doc . rest_keywords = kw_rest . name
122+ end
123+ end
124+ end
125+
126+ [ doc , unused ]
127+ end
128+
129+ def all_param_annotations
130+ annotations = [ ] #: Array[param_type_annotation | Symbol | nil]
131+ #
132+ required_positionals . each { |a | annotations << a }
133+ optional_positionals . each { |a | annotations << a }
134+ annotations << rest_positionals
135+ trailing_positionals . each { |a | annotations << a }
136+ required_keywords . each_value { |a | annotations << a }
137+ optional_keywords . each_value { |a | annotations << a }
138+ annotations << rest_keywords
139+
140+ annotations
23141 end
24142
25143 def map_type_name ( &block )
26144 DocStyle . new . tap do |new |
27145 new . return_type_annotation = return_type_annotation &.map_type_name ( &block )
146+ new . required_positionals . replace (
147+ required_positionals . map do |a |
148+ case a
149+ when Annotations ::ParamTypeAnnotation
150+ a . map_type_name ( &block )
151+ else
152+ a
153+ end
154+ end
155+ )
156+ new . optional_positionals . replace (
157+ optional_positionals . map do |a |
158+ case a
159+ when Annotations ::ParamTypeAnnotation
160+ a . map_type_name ( &block )
161+ else
162+ a
163+ end
164+ end
165+ )
166+ new . rest_positionals =
167+ case rest_positionals
168+ when Annotations ::ParamTypeAnnotation
169+ rest_positionals . map_type_name ( &block )
170+ else
171+ rest_positionals
172+ end
173+ new . trailing_positionals . replace (
174+ trailing_positionals . map do |a |
175+ case a
176+ when Annotations ::ParamTypeAnnotation
177+ a . map_type_name ( &block )
178+ else
179+ a
180+ end
181+ end
182+ )
183+ new . required_keywords . replace (
184+ required_keywords . transform_values do |a |
185+ case a
186+ when Annotations ::ParamTypeAnnotation
187+ a . map_type_name ( &block )
188+ else
189+ a
190+ end
191+ end
192+ )
193+ new . optional_keywords . replace (
194+ optional_keywords . transform_values do |a |
195+ case a
196+ when Annotations ::ParamTypeAnnotation
197+ a . map_type_name ( &block )
198+ else
199+ a
200+ end
201+ end
202+ )
203+ new . rest_keywords =
204+ case rest_keywords
205+ when Annotations ::ParamTypeAnnotation
206+ rest_keywords . map_type_name ( &block )
207+ else
208+ rest_keywords
209+ end
28210 end #: self
29211 end
30212
31213 def type_fingerprint
32- return_type_annotation &.type_fingerprint
214+ [
215+ return_type_annotation &.type_fingerprint ,
216+ all_param_annotations . map do |param |
217+ case param
218+ when Annotations ::ParamTypeAnnotation
219+ param . type_fingerprint
220+ else
221+ param
222+ end
223+ end
224+ ]
33225 end
34226
35227 def method_type
@@ -43,14 +235,77 @@ def method_type
43235 Types ::Bases ::Any . new ( location : nil )
44236 end
45237
238+ any = -> { Types ::Bases ::Any . new ( location : nil ) }
239+
240+ req_pos = required_positionals . map do |a |
241+ case a
242+ when Annotations ::ParamTypeAnnotation
243+ Types ::Function ::Param . new ( type : a . param_type , name : a . name_location . source . to_sym )
244+ else
245+ Types ::Function ::Param . new ( type : any . call , name : a )
246+ end
247+ end
248+ opt_pos = optional_positionals . map do |a |
249+ case a
250+ when Annotations ::ParamTypeAnnotation
251+ Types ::Function ::Param . new ( type : a . param_type , name : a . name_location . source . to_sym )
252+ else
253+ Types ::Function ::Param . new ( type : any . call , name : a )
254+ end
255+ end
256+ rest_pos =
257+ case rest_positionals
258+ when Annotations ::ParamTypeAnnotation
259+ Types ::Function ::Param . new ( type : rest_positionals . param_type , name : rest_positionals . name_location . source . to_sym )
260+ when Symbol
261+ Types ::Function ::Param . new ( type : any . call , name : rest_positionals )
262+ else
263+ nil
264+ end
265+ trail_pos = trailing_positionals . map do |a |
266+ case a
267+ when Annotations ::ParamTypeAnnotation
268+ Types ::Function ::Param . new ( type : a . param_type , name : a . name_location . source . to_sym )
269+ else
270+ Types ::Function ::Param . new ( type : any . call , name : a )
271+ end
272+ end
273+
274+ req_kw = required_keywords . transform_values do |a |
275+ case a
276+ when Annotations ::ParamTypeAnnotation
277+ Types ::Function ::Param . new ( type : a . param_type , name : nil )
278+ else
279+ Types ::Function ::Param . new ( type : any . call , name : nil )
280+ end
281+ end
282+ opt_kw = optional_keywords . transform_values do |a |
283+ case a
284+ when Annotations ::ParamTypeAnnotation
285+ Types ::Function ::Param . new ( type : a . param_type , name : nil )
286+ else
287+ Types ::Function ::Param . new ( type : any . call , name : nil )
288+ end
289+ end
290+
291+ rest_kw =
292+ case rest_keywords
293+ when Annotations ::ParamTypeAnnotation
294+ Types ::Function ::Param . new ( type : rest_keywords . param_type , name : nil )
295+ when Symbol
296+ Types ::Function ::Param . new ( type : any . call , name : nil )
297+ else
298+ nil
299+ end
300+
46301 type = Types ::Function . new (
47- required_positionals : [ ] ,
48- optional_positionals : [ ] ,
49- rest_positionals : nil ,
50- trailing_positionals : [ ] ,
51- required_keywords : { } ,
52- optional_keywords : { } ,
53- rest_keywords : nil ,
302+ required_positionals : req_pos ,
303+ optional_positionals : opt_pos ,
304+ rest_positionals : rest_pos ,
305+ trailing_positionals : trail_pos ,
306+ required_keywords : req_kw ,
307+ optional_keywords : opt_kw ,
308+ rest_keywords : rest_kw ,
54309 return_type : return_type
55310 )
56311
@@ -82,17 +337,18 @@ def map_type_name(&block)
82337 MethodTypeAnnotation . new ( type_annotations : updated_annots ) #: self
83338 end
84339
85- def self . build ( leading_block , trailing_block , variables )
340+ def self . build ( leading_block , trailing_block , variables , node )
86341 unused_annotations = [ ] #: Array[Annotations::leading_annotation | CommentBlock::AnnotationSyntaxError]
87342 unused_trailing_annotation = nil #: Annotations::trailing_annotation | CommentBlock::AnnotationSyntaxError | nil
88343
89344 type_annotations = nil #: type_annotations
345+ return_annotation = nil #: Annotations::ReturnTypeAnnotation | Annotations::NodeTypeAssertion | nil
346+ param_annotations = [ ] #: Array[Annotations::ParamTypeAnnotation]
90347
91348 if trailing_block
92349 case annotation = trailing_block . trailing_annotation ( variables )
93350 when Annotations ::NodeTypeAssertion
94- type_annotations = DocStyle . new ( )
95- type_annotations . return_type_annotation = annotation
351+ return_annotation = annotation
96352 else
97353 unused_trailing_annotation = annotation
98354 end
@@ -116,25 +372,30 @@ def self.build(leading_block, trailing_block, variables)
116372 end
117373 when Annotations ::ReturnTypeAnnotation
118374 unless type_annotations
119- type_annotations = DocStyle . new ( )
120- end
121-
122- if type_annotations . is_a? ( DocStyle )
123- unless type_annotations . return_type_annotation
124- type_annotations . return_type_annotation = paragraph
375+ unless return_annotation
376+ return_annotation = paragraph
125377 next
126378 end
127379 end
380+ when Annotations ::ParamTypeAnnotation
381+ unless type_annotations
382+ param_annotations << paragraph
383+ next
384+ end
128385 end
129386
130387 unused_annotations << paragraph
131388 end
132389 end
133390
391+ if !type_annotations && ( return_annotation || !param_annotations . empty? )
392+ doc_style , unused_params = DocStyle . build ( param_annotations , return_annotation , node )
393+ type_annotations = doc_style
394+ unused_annotations . concat ( unused_params )
395+ end
396+
134397 [
135- MethodTypeAnnotation . new (
136- type_annotations : type_annotations
137- ) ,
398+ MethodTypeAnnotation . new ( type_annotations : type_annotations ) ,
138399 unused_annotations ,
139400 unused_trailing_annotation
140401 ]
0 commit comments