3939
4040total_files_size = Dir . glob ( "#{ project . base_dir } /lib/**/*.rb" ) . size
4141
42+ def stats_item ( path , line , line_content , comparison_key )
43+ {
44+ path : path . to_s ,
45+ line : line ,
46+ line_content : line_content ,
47+ comparison_key : comparison_key
48+ } . compact
49+ end
50+
51+ # Include the ignore comment and ignored source so line-only moves stay matched.
52+ def ignore_item ( path , line , comment_source , ignored_source )
53+ stats_item ( path , line , nil , { type : "steep_ignore" , path : path . to_s , source : comment_source , ignored_source : ignored_source } )
54+ end
55+
56+ # Include the enclosing namespace so equivalent RBS declarations in different owners stay distinct.
57+ def rbs_item ( path , line , source , context )
58+ stats_item ( path , line , source , { type : "rbs_declaration" , path : path . to_s , context : context , source : source } )
59+ end
60+
4261# steep:ignore comments stats
4362ignore_comments = loader . each_path_in_patterns ( datadog_target . source_pattern ) . each_with_object ( [ ] ) do |path , result |
44- buffer = ::Parser ::Source ::Buffer . new ( path . to_s , 1 , source : path . read )
63+ source = path . read
64+ source_lines = source . lines
65+ buffer = ::Parser ::Source ::Buffer . new ( path . to_s , 1 , source : source )
4566 _ , comments = ::Parser ::Ruby25 . new . parse_with_comments ( buffer )
46- rbs_buffer = ::RBS ::Buffer . new ( name : path , content : path . read )
67+ rbs_buffer = ::RBS ::Buffer . new ( name : path , content : source )
4768 comments . each do |comment |
4869 ignore = ::Steep ::AST ::Ignore . parse ( comment , rbs_buffer )
4970 next if ignore . nil? || ignore . is_a? ( ::Steep ::AST ::Ignore ::IgnoreEnd )
5071
51- result << {
52- path : path . to_s ,
53- line : ignore . line
54- }
72+ ignored_source = source_lines [ ignore . line - 1 ] &.strip
73+ result << ignore_item ( path , ignore . line , comment . loc . expression . source , ignored_source )
5574 end
5675end
5776
58- def ast_traversal ( declarations , result = { } )
77+ # Collects declarations with their enclosing RBS namespace for stable comparison keys.
78+ # @param declarations [Array<RBS::AST::Declarations::Base, RBS::AST::Members::Base>]
79+ # @param result [Hash] accumulated methods and other declarations
80+ # @param context [Array<String>] enclosing Ruby namespace, e.g. ["Datadog", "Core"]
81+ def ast_traversal ( declarations , result = { } , context = [ ] )
5982 result [ :methods ] ||= [ ]
6083 result [ :others ] ||= [ ]
6184 declarations . each do |declaration |
6285 case declaration
6386 when ::RBS ::AST ::Declarations ::Module ,
6487 ::RBS ::AST ::Declarations ::Class ,
6588 ::RBS ::AST ::Declarations ::Interface
66- ast_traversal ( declaration . members , result )
89+ ast_traversal ( declaration . members , result , context + [ declaration . name . to_s ] )
6790 when ::RBS ::AST ::Declarations ::TypeAlias ,
6891 ::RBS ::AST ::Declarations ::Constant ,
6992 ::RBS ::AST ::Declarations ::Global ,
7093 ::RBS ::AST ::Members ::Var ,
7194 ::RBS ::AST ::Members ::Attribute
72- result [ :others ] << declaration
95+ result [ :others ] << { declaration : declaration , context : context }
7396 # Only this one does not have a type field
7497 when ::RBS ::AST ::Members ::MethodDefinition
75- result [ :methods ] << declaration
98+ result [ :methods ] << { declaration : declaration , context : context }
7699 end
77100 end
78101 result
@@ -177,7 +200,9 @@ def is_typed?(type, initialize: false)
177200 _ , _directives , declarations = ::RBS ::Parser . parse_signature ( buffer )
178201 filtered_declarations = ast_traversal ( declarations )
179202
180- filtered_declarations [ :methods ] . each do |method |
203+ filtered_declarations [ :methods ] . each do |entry |
204+ method = entry [ :declaration ]
205+
181206 # Skip definitions with last comment line being `untyped:accept`
182207 if method . comment &.string &.end_with? ( "untyped:accept\n " )
183208 typed_methods_size += 1
@@ -192,13 +217,15 @@ def is_typed?(type, initialize: false)
192217 when :typed
193218 typed_methods_size += 1
194219 when :untyped
195- untyped_methods << { path : sig_path . to_s , line : method . location . start_line , line_content : method . location . source }
220+ untyped_methods << rbs_item ( sig_path , method . location . start_line , method . location . source , entry [ :context ] )
196221 when :partial
197- partially_typed_methods << { path : sig_path . to_s , line : method . location . start_line , line_content : method . location . source }
222+ partially_typed_methods << rbs_item ( sig_path , method . location . start_line , method . location . source , entry [ :context ] )
198223 end
199224 end
200225
201- filtered_declarations [ :others ] . each do |declaration |
226+ filtered_declarations [ :others ] . each do |entry |
227+ declaration = entry [ :declaration ]
228+
202229 # Skip definitions with last comment line being `untyped:accept`
203230 if declaration . comment &.string &.end_with? ( "untyped:accept\n " )
204231 typed_others_size += 1
@@ -209,9 +236,9 @@ def is_typed?(type, initialize: false)
209236 when :typed , nil
210237 typed_others_size += 1
211238 when :untyped
212- untyped_others << { path : sig_path . to_s , line : declaration . location . start_line , line_content : declaration . location . source }
239+ untyped_others << rbs_item ( sig_path , declaration . location . start_line , declaration . location . source , entry [ :context ] )
213240 when :partial
214- partially_typed_others << { path : sig_path . to_s , line : declaration . location . start_line , line_content : declaration . location . source }
241+ partially_typed_others << rbs_item ( sig_path , declaration . location . start_line , declaration . location . source , entry [ :context ] )
215242 end
216243 end
217244end
0 commit comments