@@ -5,6 +5,7 @@ module Tapioca
55 module Commands
66 # @abstract
77 class AbstractDsl < CommandWithoutTracker
8+ include FileHelper
89 include SorbetHelper
910 include RBIFilesHelper
1011
@@ -26,7 +27,8 @@ class AbstractDsl < CommandWithoutTracker
2627 #| ?app_root: String,
2728 #| ?halt_upon_load_error: bool,
2829 #| ?compiler_options: Hash[String, untyped],
29- #| ?lsp_addon: bool
30+ #| ?lsp_addon: bool,
31+ #| ?max_diff_lines: Integer
3032 #| ) -> void
3133 def initialize (
3234 requested_constants :,
@@ -46,7 +48,8 @@ def initialize(
4648 app_root : "." ,
4749 halt_upon_load_error : true ,
4850 compiler_options : { } ,
49- lsp_addon : false
51+ lsp_addon : false ,
52+ max_diff_lines : DEFAULT_MAX_DIFF_LINES
5053 )
5154 @requested_constants = requested_constants
5255 @requested_paths = requested_paths
@@ -66,6 +69,7 @@ def initialize(
6669 @skip_constant = skip_constant
6770 @compiler_options = compiler_options
6871 @lsp_addon = lsp_addon
72+ @max_diff_lines = max_diff_lines
6973
7074 super ( )
7175 end
@@ -247,7 +251,7 @@ def compile_dsl_rbi(constant_name, rbi, outpath: @outpath, quiet: false)
247251 def perform_dsl_verification ( dir )
248252 diff = verify_dsl_rbi ( tmp_dir : dir )
249253
250- report_diff_and_exit_if_out_of_date ( diff , :dsl )
254+ report_diff_and_exit_if_out_of_date ( diff , tmp_dir : dir , command : :dsl )
251255 ensure
252256 FileUtils . remove_entry ( dir )
253257 end
@@ -269,7 +273,7 @@ def dsl_rbi_filename(constant_name)
269273 @outpath / "#{ underscore ( constant_name ) } .rbi"
270274 end
271275
272- #: (tmp_dir: Pathname) -> Hash[String , Symbol]
276+ #: (tmp_dir: Pathname) -> Hash[Pathname , Symbol]
273277 def verify_dsl_rbi ( tmp_dir :)
274278 diff = { }
275279
@@ -301,7 +305,7 @@ def verify_dsl_rbi(tmp_dir:)
301305 diff
302306 end
303307
304- #: (Symbol cause, Array[String ] files) -> String
308+ #: (Symbol cause, Array[Pathname ] files) -> String
305309 def build_error_for_files ( cause , files )
306310 filenames = files . map do |file |
307311 @outpath / file
@@ -310,26 +314,71 @@ def build_error_for_files(cause, files)
310314 " File(s) #{ cause } :\n - #{ filenames } "
311315 end
312316
313- #: (Hash[String , Symbol] diff, Symbol command) -> void
314- def report_diff_and_exit_if_out_of_date ( diff , command )
317+ #: (Hash[Pathname , Symbol] diff, tmp_dir: Pathname, command: Symbol ) -> void
318+ def report_diff_and_exit_if_out_of_date ( diff , tmp_dir : , command : )
315319 if diff . empty?
316320 say ( "Nothing to do, all RBIs are up-to-date." )
317- else
318- reasons = diff . group_by ( &:last ) . sort . map do |cause , diff_for_cause |
319- build_error_for_files ( cause , diff_for_cause . map ( &:first ) )
320- end . join ( "\n " )
321+ return
322+ end
323+
324+ reasons = diff . group_by ( &:last ) . sort . map do |cause , diff_for_cause |
325+ build_error_for_files ( cause , diff_for_cause . map ( &:first ) )
326+ end . join ( "\n " )
327+
328+ diff_output , diff_truncated = build_diff_output ( diff , tmp_dir )
329+
330+ diff_section =
331+ if diff_truncated
332+ "#{ set_color ( "Diff truncated to #{ @max_diff_lines } lines.\n Change the number of displayed lines using the `--max-diff-lines` flag." , :red ) } \n #{ diff_output . rstrip } "
333+ elsif !diff_output . empty?
334+ "#{ set_color ( "Diff:" , :red ) } \n #{ diff_output . rstrip } "
335+ else
336+ ""
337+ end
338+
339+ raise Tapioca ::Error , <<~ERROR . rstrip
340+ #{ set_color ( "RBI files are out-of-date. In your development environment, please run:" , :green ) }
341+ #{ set_color ( "`#{ default_command ( command ) } `" , :green , :bold ) }
342+ #{ set_color ( "Once it is complete, be sure to commit and push any changes" , :green ) }
343+ If you don't observe any changes after running the command locally, ensure your database is in a good
344+ state e.g. run `bin/rails db:reset`
321345
322- raise Tapioca ::Error , <<~ERROR
323- #{ set_color ( "RBI files are out-of-date. In your development environment, please run:" , :green ) }
324- #{ set_color ( "`#{ default_command ( command ) } `" , :green , :bold ) }
325- #{ set_color ( "Once it is complete, be sure to commit and push any changes" , :green ) }
326- If you don't observe any changes after running the command locally, ensure your database is in a good
327- state e.g. run `bin/rails db:reset`
346+ #{ set_color ( "Reason:" , :red ) }
347+ #{ reasons }
328348
329- #{ set_color ( "Reason:" , :red ) }
330- #{ reasons }
331- ERROR
349+ #{ diff_section }
350+ ERROR
351+ end
352+
353+ #: (Hash[Pathname, Symbol] diff, Pathname tmp_dir) -> [String, bool]
354+ def build_diff_output ( diff , tmp_dir )
355+ out = String . new
356+ truncated = false #: bool
357+ line_count = 0
358+
359+ diff . each do |file , status |
360+ old_path = ( @outpath / file )
361+ new_path = ( tmp_dir / file )
362+
363+ chunk = case status
364+ when :added then file_diff ( file , File ::NULL , new_path )
365+ when :removed then file_diff ( file , old_path , File ::NULL )
366+ when :changed then file_diff ( file , old_path , new_path )
367+ else ""
368+ end
369+
370+ remaining_lines = @max_diff_lines - line_count
371+ if chunk . lines . count > remaining_lines
372+ out << chunk . lines . first ( remaining_lines ) . join
373+ truncated = true
374+ break
375+ end
376+
377+ out << chunk
378+ line_count += chunk . lines . count
332379 end
380+
381+ [ out , truncated ]
333382 end
334383
335384 #: (Pathname path) -> Array[Pathname]
0 commit comments