hank 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. checksums.yaml +7 -0
  2. data/.clodignore +32 -0
  3. data/.rubocop.yml +59 -0
  4. data/CLAUDE.md +22 -0
  5. data/Gemfile +11 -0
  6. data/LICENSE +21 -0
  7. data/README.md +70 -0
  8. data/Rakefile +17 -0
  9. data/bin/hank +7 -0
  10. data/hank.gemspec +55 -0
  11. data/lib/hank/cli.rb +162 -0
  12. data/lib/hank/file_selector.rb +204 -0
  13. data/lib/hank/hankfile.rb +70 -0
  14. data/lib/hank/path_utils.rb +47 -0
  15. data/lib/hank/symlink_manager.rb +94 -0
  16. data/lib/hank/validator.rb +65 -0
  17. data/lib/hank/version.rb +6 -0
  18. data/lib/hank.rb +25 -0
  19. data/sorbet/config +5 -0
  20. data/sorbet/rbi/annotations/.gitattributes +1 -0
  21. data/sorbet/rbi/annotations/colorize.rbi +121 -0
  22. data/sorbet/rbi/annotations/minitest.rbi +119 -0
  23. data/sorbet/rbi/annotations/rainbow.rbi +269 -0
  24. data/sorbet/rbi/gems/.gitattributes +1 -0
  25. data/sorbet/rbi/gems/ansi.rbi +398 -0
  26. data/sorbet/rbi/gems/ansi@1.5.0.rbi +688 -0
  27. data/sorbet/rbi/gems/ast.rbi +49 -0
  28. data/sorbet/rbi/gems/ast@2.4.3.rbi +585 -0
  29. data/sorbet/rbi/gems/benchmark@0.4.0.rbi +618 -0
  30. data/sorbet/rbi/gems/builder.rbi +58 -0
  31. data/sorbet/rbi/gems/builder@3.3.0.rbi +502 -0
  32. data/sorbet/rbi/gems/citrus.rbi +238 -0
  33. data/sorbet/rbi/gems/citrus@3.0.2.rbi +1234 -0
  34. data/sorbet/rbi/gems/colorize.rbi +82 -0
  35. data/sorbet/rbi/gems/colorize@0.8.1.rbi +152 -0
  36. data/sorbet/rbi/gems/curses.rbi +327 -0
  37. data/sorbet/rbi/gems/curses@1.4.7.rbi +894 -0
  38. data/sorbet/rbi/gems/diffy.rbi +56 -0
  39. data/sorbet/rbi/gems/diffy@3.4.3.rbi +184 -0
  40. data/sorbet/rbi/gems/docile.rbi +36 -0
  41. data/sorbet/rbi/gems/docile@1.4.1.rbi +377 -0
  42. data/sorbet/rbi/gems/erubi@1.13.1.rbi +155 -0
  43. data/sorbet/rbi/gems/fiddle.rbi +120 -0
  44. data/sorbet/rbi/gems/fiddle@1.1.6.rbi +9 -0
  45. data/sorbet/rbi/gems/hank.rbi +15 -0
  46. data/sorbet/rbi/gems/json@2.10.2.rbi +2112 -0
  47. data/sorbet/rbi/gems/language_server-protocol.rbi +2868 -0
  48. data/sorbet/rbi/gems/language_server-protocol@3.17.0.4.rbi +9 -0
  49. data/sorbet/rbi/gems/lint_roller.rbi +75 -0
  50. data/sorbet/rbi/gems/lint_roller@1.1.0.rbi +86 -0
  51. data/sorbet/rbi/gems/logger.rbi +94 -0
  52. data/sorbet/rbi/gems/logger@1.7.0.rbi +963 -0
  53. data/sorbet/rbi/gems/minitest-reporters.rbi +104 -0
  54. data/sorbet/rbi/gems/minitest-reporters@1.7.1.rbi +1018 -0
  55. data/sorbet/rbi/gems/minitest.rbi +440 -0
  56. data/sorbet/rbi/gems/minitest@5.25.5.rbi +1547 -0
  57. data/sorbet/rbi/gems/netrc@0.11.0.rbi +159 -0
  58. data/sorbet/rbi/gems/parallel.rbi +88 -0
  59. data/sorbet/rbi/gems/parallel@1.26.3.rbi +291 -0
  60. data/sorbet/rbi/gems/parser.rbi +1545 -0
  61. data/sorbet/rbi/gems/parser@3.3.7.4.rbi +5535 -0
  62. data/sorbet/rbi/gems/prism.rbi +4090 -0
  63. data/sorbet/rbi/gems/prism@1.4.0.rbi +41732 -0
  64. data/sorbet/rbi/gems/racc.rbi +41 -0
  65. data/sorbet/rbi/gems/racc@1.8.1.rbi +160 -0
  66. data/sorbet/rbi/gems/rainbow.rbi +122 -0
  67. data/sorbet/rbi/gems/rainbow@3.1.1.rbi +403 -0
  68. data/sorbet/rbi/gems/rake.rbi +649 -0
  69. data/sorbet/rbi/gems/rake@13.2.1.rbi +3033 -0
  70. data/sorbet/rbi/gems/rbi@0.3.1.rbi +6599 -0
  71. data/sorbet/rbi/gems/rbs@3.9.2.rbi +6978 -0
  72. data/sorbet/rbi/gems/regexp_parser.rbi +1039 -0
  73. data/sorbet/rbi/gems/regexp_parser@2.10.0.rbi +3795 -0
  74. data/sorbet/rbi/gems/rubocop-ast.rbi +1470 -0
  75. data/sorbet/rbi/gems/rubocop-ast@1.44.0.rbi +7716 -0
  76. data/sorbet/rbi/gems/rubocop.rbi +10557 -0
  77. data/sorbet/rbi/gems/rubocop@1.75.2.rbi +61860 -0
  78. data/sorbet/rbi/gems/ruby-filemagic.rbi +46 -0
  79. data/sorbet/rbi/gems/ruby-filemagic@0.7.3.rbi +168 -0
  80. data/sorbet/rbi/gems/ruby-progressbar.rbi +321 -0
  81. data/sorbet/rbi/gems/ruby-progressbar@1.13.0.rbi +1318 -0
  82. data/sorbet/rbi/gems/simplecov-html.rbi +36 -0
  83. data/sorbet/rbi/gems/simplecov-html@0.13.1.rbi +225 -0
  84. data/sorbet/rbi/gems/simplecov.rbi +435 -0
  85. data/sorbet/rbi/gems/simplecov@0.22.0.rbi +2149 -0
  86. data/sorbet/rbi/gems/simplecov_json_formatter.rbi +47 -0
  87. data/sorbet/rbi/gems/simplecov_json_formatter@0.1.4.rbi +9 -0
  88. data/sorbet/rbi/gems/spoom@1.6.1.rbi +7274 -0
  89. data/sorbet/rbi/gems/tapioca@0.16.11.rbi +3628 -0
  90. data/sorbet/rbi/gems/thor.rbi +583 -0
  91. data/sorbet/rbi/gems/thor@1.3.2.rbi +4378 -0
  92. data/sorbet/rbi/gems/toml-rb.rbi +136 -0
  93. data/sorbet/rbi/gems/toml-rb@2.2.0.rbi +419 -0
  94. data/sorbet/rbi/gems/unicode-display_width.rbi +28 -0
  95. data/sorbet/rbi/gems/unicode-display_width@3.1.4.rbi +132 -0
  96. data/sorbet/rbi/gems/unicode-emoji.rbi +18 -0
  97. data/sorbet/rbi/gems/unicode-emoji@4.0.4.rbi +251 -0
  98. data/sorbet/rbi/gems/yard-sorbet@0.9.0.rbi +435 -0
  99. data/sorbet/rbi/gems/yard@0.9.37.rbi +18379 -0
  100. data/sorbet/tapioca/config.yml +13 -0
  101. data/sorbet/tapioca/require.rb +4 -0
  102. metadata +399 -0
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+ # typed: strict
3
+
4
+ module Hank
5
+ # Manages the Hankfile configuration
6
+ class Hankfile
7
+ extend T::Sig
8
+
9
+ sig { returns(T::Hash[String, String]) }
10
+ attr_reader :mappings
11
+
12
+ sig { void }
13
+ def initialize
14
+ @mappings = T.let({}, T::Hash[String, String])
15
+ end
16
+
17
+ sig { params(source_path: String, target_path: String).void }
18
+ def add_mapping(source_path, target_path)
19
+ @mappings[source_path] = target_path
20
+ end
21
+
22
+ sig { params(source_path: String).void }
23
+ def remove_mapping(source_path)
24
+ @mappings.delete(source_path)
25
+ end
26
+
27
+ sig { params(selected_files: T::Array[String]).void }
28
+ def update_mappings(selected_files)
29
+ # Keep mappings for selected files, add new ones
30
+ new_mappings = {}
31
+
32
+ selected_files.each do |source_path|
33
+ new_mappings[source_path] = if @mappings.key?(source_path)
34
+ @mappings[source_path]
35
+ else
36
+ PathUtils.flatten_path(source_path)
37
+ end
38
+ end
39
+
40
+ @mappings = new_mappings
41
+ save
42
+ end
43
+
44
+ sig { void }
45
+ def save
46
+ path = ENV['HANKFILE'] || 'Hankfile'
47
+ File.write(path, to_s)
48
+ end
49
+
50
+ sig { returns(String) }
51
+ def to_s
52
+ TomlRB.dump({ 'mappings' => @mappings })
53
+ end
54
+
55
+ sig { params(file_path: Pathname).returns(Hankfile) }
56
+ def self.from_file(file_path)
57
+ content = File.read(file_path)
58
+ data = TomlRB.parse(content)
59
+
60
+ hankfile = Hankfile.new
61
+ if data['mappings'].is_a?(Hash)
62
+ data['mappings'].each do |source_path, target_path|
63
+ hankfile.add_mapping(source_path, target_path.to_s)
64
+ end
65
+ end
66
+
67
+ hankfile
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+ # typed: strict
3
+
4
+ module Hank
5
+ # Utilities for path manipulation and file type detection
6
+ class PathUtils
7
+ extend T::Sig
8
+
9
+ sig { params(path: String).returns(String) }
10
+ def self.flatten_path(path)
11
+ pathname = Pathname.new(path)
12
+
13
+ # Handle dotfiles
14
+ basename = pathname.basename.to_s
15
+ basename = "dot--#{basename[1..]}" if basename.start_with?('.')
16
+
17
+ # Flatten directory structure
18
+ if pathname.dirname.to_s == '.'
19
+ basename
20
+ else
21
+ dirname = pathname.dirname.to_s.gsub(%r{^/}, '').gsub('/', '-')
22
+ "#{dirname}-#{basename}"
23
+ end
24
+ end
25
+
26
+ sig { params(path: String).returns(T::Boolean) }
27
+ def self.text_file?(path)
28
+ return false unless File.file?(path)
29
+
30
+ # Use libmagic to determine if file is text
31
+ begin
32
+ # Create a new instance for each call to avoid allocator warnings
33
+ magic = FileMagic.open(FileMagic::MAGIC_MIME)
34
+ mime_type = magic.file(path)
35
+ magic.close
36
+ mime_type.start_with?('text/') ||
37
+ mime_type.include?('xml') ||
38
+ mime_type.include?('json') ||
39
+ mime_type.include?('script')
40
+ rescue StandardError => e
41
+ puts "Warning: Error detecting file type: #{e.message}".yellow
42
+ # Fall back to simple text check
43
+ File.open(path) { |f| T.must(f.read(1024)).valid_encoding? }
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+ # typed: strict
3
+
4
+ module Hank
5
+ # Manages creation and removal of symlinks
6
+ class SymlinkManager
7
+ extend T::Sig
8
+
9
+ sig { returns(Pathname) }
10
+ attr_reader :base_dir
11
+
12
+ sig { params(hankfile: Hankfile).void }
13
+ def initialize(hankfile)
14
+ @hankfile = T.let(hankfile, Hankfile)
15
+ @base_dir = T.let(Pathname.new(Dir.pwd), Pathname)
16
+ end
17
+
18
+ sig { void }
19
+ def install_all
20
+ @hankfile.mappings.each do |source_path, target_path|
21
+ create_symlink(source_path, target_path)
22
+ end
23
+ @hankfile.save
24
+ end
25
+
26
+ sig { params(source: Pathname, target: Pathname).void }
27
+ def create_empty_target(source, target)
28
+ if source.directory?
29
+ FileUtils.mkdir_p(target)
30
+ else
31
+ FileUtils.touch(target)
32
+ end
33
+ end
34
+
35
+ sig { params(source_path: String, target_path: String, force: T::Boolean).returns(T::Boolean) }
36
+ def create_symlink(source_path, target_path, force: false)
37
+ source = Pathname.new(source_path)
38
+ target = @base_dir.join(target_path)
39
+
40
+ # Ensure the source path directory exists
41
+ FileUtils.mkdir_p(source.dirname) unless source.dirname.directory?
42
+
43
+ # Ensure the target exists
44
+ unless target.exist?
45
+ if source.exist?
46
+ if source.directory? || (!source.symlink? && source.file?)
47
+ # Move the entire directory or file to the target location
48
+ FileUtils.mv(source, target)
49
+ else
50
+ # Create empty file or directory as needed
51
+ create_empty_target(source, target)
52
+ end
53
+ elsif source_path.end_with?('/')
54
+ # Create empty file or directory based on the source path name
55
+ # (If we can infer it's supposed to be a directory)
56
+ FileUtils.mkdir_p(target)
57
+ else
58
+ FileUtils.touch(target)
59
+ end
60
+ end
61
+
62
+ # Handle existing destination
63
+ if source.exist?
64
+ if source.symlink? && !force
65
+ return false
66
+
67
+ # Remove existing symlink if force is specified
68
+
69
+ # Skip if symlink already exists and force is not specified
70
+
71
+ end
72
+
73
+ FileUtils.rm_rf(source)
74
+ end
75
+
76
+ # Create the symlink
77
+ begin
78
+ FileUtils.ln_s(target.to_s, source.to_s)
79
+ puts "Created symlink: #{source} -> #{target}".green
80
+ true
81
+ rescue StandardError => e
82
+ puts "⚠️ Failed to create symlink: #{source} -> #{target}: #{e.message}".red
83
+ false
84
+ end
85
+ end
86
+
87
+ sig { params(source_path: String).void }
88
+ def remove_mapping(source_path)
89
+ @hankfile.remove_mapping(source_path)
90
+ @hankfile.save
91
+ puts "Removed #{source_path} from Hankfile".green
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+ # typed: strict
3
+
4
+ module Hank
5
+ # Validates the integrity of symlinks
6
+ class Validator
7
+ extend T::Sig
8
+
9
+ # Represents a validation issue with a symlink
10
+ class Issue < T::Struct
11
+ const :type, Symbol # :missing, :wrong_target, :not_symlink
12
+ const :source_path, String
13
+ const :target_path, String
14
+ const :current_target, T.nilable(String)
15
+ end
16
+
17
+ sig { params(hankfile: Hankfile).void }
18
+ def initialize(hankfile)
19
+ @hankfile = T.let(hankfile, Hankfile)
20
+ @base_dir = T.let(Pathname.new(Dir.pwd), Pathname)
21
+ end
22
+
23
+ sig { returns(T::Array[Issue]) }
24
+ def validate
25
+ issues = []
26
+
27
+ @hankfile.mappings.each do |source_path, target_path|
28
+ source = Pathname.new(source_path)
29
+ target = @base_dir.join(target_path)
30
+
31
+ if !source.exist?
32
+ # Source path doesn't exist
33
+ issues << Issue.new(
34
+ type: :missing,
35
+ source_path: source_path,
36
+ target_path: target_path,
37
+ current_target: nil
38
+ )
39
+ elsif !source.symlink?
40
+ # Source path exists but is not a symlink
41
+ issues << Issue.new(
42
+ type: :not_symlink,
43
+ source_path: source_path,
44
+ target_path: target_path,
45
+ current_target: nil
46
+ )
47
+ else
48
+ # Source path is a symlink, check if it points to the correct target
49
+ actual_target = Pathname.new(File.readlink(source.to_s))
50
+
51
+ if actual_target != target && actual_target.expand_path != target.expand_path
52
+ issues << Issue.new(
53
+ type: :wrong_target,
54
+ source_path: source_path,
55
+ target_path: target_path,
56
+ current_target: actual_target.to_s
57
+ )
58
+ end
59
+ end
60
+ end
61
+
62
+ issues
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+ # typed: strict
3
+
4
+ module Hank
5
+ VERSION = '0.1.0'
6
+ end
data/lib/hank.rb ADDED
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+ # typed: strict
3
+
4
+ require 'sorbet-runtime'
5
+ require 'thor'
6
+ require 'toml-rb'
7
+ require 'filemagic'
8
+ require 'diffy'
9
+ require 'colorize'
10
+ require 'pathname'
11
+ require 'fileutils'
12
+ require 'curses'
13
+
14
+ require_relative 'hank/version'
15
+ require_relative 'hank/hankfile'
16
+ require_relative 'hank/path_utils'
17
+ require_relative 'hank/symlink_manager'
18
+ require_relative 'hank/file_selector'
19
+ require_relative 'hank/validator'
20
+ require_relative 'hank/cli'
21
+
22
+ module Hank
23
+ class Error < StandardError; end
24
+ # Your code goes here...
25
+ end
data/sorbet/config ADDED
@@ -0,0 +1,5 @@
1
+ --dir
2
+ .
3
+ --ignore=/tmp/
4
+ --ignore=/vendor/bundle
5
+ --ignore=sorbet/rbi/gems/thor@1.3.2.rbi
@@ -0,0 +1 @@
1
+ **/*.rbi linguist-vendored=true
@@ -0,0 +1,121 @@
1
+ # typed: true
2
+
3
+ # DO NOT EDIT MANUALLY
4
+ # This file was pulled from a central RBI files repository.
5
+ # Please run `bin/tapioca annotations` to update it.
6
+
7
+ class String
8
+ extend Colorize::ClassMethods
9
+ include Colorize::InstanceMethods
10
+
11
+ sig { returns(String) }
12
+ def black; end
13
+
14
+ sig { returns(String) }
15
+ def blink; end
16
+
17
+ sig { returns(String) }
18
+ def blue; end
19
+
20
+ sig { returns(String) }
21
+ def bold; end
22
+
23
+ sig { returns(String) }
24
+ def cyan; end
25
+
26
+ sig { returns(String) }
27
+ def green; end
28
+
29
+ sig { returns(String) }
30
+ def hide; end
31
+
32
+ sig { returns(String) }
33
+ def italic; end
34
+
35
+ sig { returns(String) }
36
+ def light_black; end
37
+
38
+ sig { returns(String) }
39
+ def light_blue; end
40
+
41
+ sig { returns(String) }
42
+ def light_cyan; end
43
+
44
+ sig { returns(String) }
45
+ def light_green; end
46
+
47
+ sig { returns(String) }
48
+ def light_magenta; end
49
+
50
+ sig { returns(String) }
51
+ def light_red; end
52
+
53
+ sig { returns(String) }
54
+ def light_white; end
55
+
56
+ sig { returns(String) }
57
+ def light_yellow; end
58
+
59
+ sig { returns(String) }
60
+ def magenta; end
61
+
62
+ sig { returns(String) }
63
+ def on_black; end
64
+
65
+ sig { returns(String) }
66
+ def on_blue; end
67
+
68
+ sig { returns(String) }
69
+ def on_cyan; end
70
+
71
+ sig { returns(String) }
72
+ def on_green; end
73
+
74
+ sig { returns(String) }
75
+ def on_light_black; end
76
+
77
+ sig { returns(String) }
78
+ def on_light_blue; end
79
+
80
+ sig { returns(String) }
81
+ def on_light_cyan; end
82
+
83
+ sig { returns(String) }
84
+ def on_light_green; end
85
+
86
+ sig { returns(String) }
87
+ def on_light_magenta; end
88
+
89
+ sig { returns(String) }
90
+ def on_light_red; end
91
+
92
+ sig { returns(String) }
93
+ def on_light_white; end
94
+
95
+ sig { returns(String) }
96
+ def on_light_yellow; end
97
+
98
+ sig { returns(String) }
99
+ def on_magenta; end
100
+
101
+ sig { returns(String) }
102
+ def on_red; end
103
+
104
+ sig { returns(String) }
105
+ def on_white; end
106
+
107
+ sig { returns(String) }
108
+ def on_yellow; end
109
+
110
+ sig { returns(String) }
111
+ def red; end
112
+
113
+ sig { returns(String) }
114
+ def underline; end
115
+
116
+ sig { returns(String) }
117
+ def white; end
118
+
119
+ sig { returns(String) }
120
+ def yellow; end
121
+ end
@@ -0,0 +1,119 @@
1
+ # typed: true
2
+
3
+ # DO NOT EDIT MANUALLY
4
+ # This file was pulled from a central RBI files repository.
5
+ # Please run `bin/tapioca annotations` to update it.
6
+
7
+ module Minitest::Assertions
8
+ sig { params(test: T.anything, msg: T.anything).returns(TrueClass) }
9
+ def assert(test, msg = nil); end
10
+
11
+ sig { params(obj: T.anything, msg: T.anything).returns(TrueClass) }
12
+ def assert_empty(obj, msg = nil); end
13
+
14
+ sig { params(exp: T.anything, act: T.anything, msg: T.anything).returns(TrueClass) }
15
+ def assert_equal(exp, act, msg = nil); end
16
+
17
+ sig { params(exp: T.anything, act: T.anything, delta: Numeric, msg: T.anything).returns(TrueClass) }
18
+ def assert_in_delta(exp, act, delta = T.unsafe(nil), msg = nil); end
19
+
20
+ sig { params(a: T.anything, b: T.anything, epsilon: Numeric, msg: T.anything).returns(TrueClass) }
21
+ def assert_in_epsilon(a, b, epsilon = T.unsafe(nil), msg = nil); end
22
+
23
+ sig { params(collection: T.anything, obj: T.anything, msg: T.anything).returns(TrueClass) }
24
+ def assert_includes(collection, obj, msg = nil); end
25
+
26
+ sig { params(cls: T.anything, obj: T.anything, msg: T.anything).returns(TrueClass) }
27
+ def assert_instance_of(cls, obj, msg = nil); end
28
+
29
+ sig { params(cls: T.anything, obj: T.anything, msg: T.anything).returns(TrueClass) }
30
+ def assert_kind_of(cls, obj, msg = nil); end
31
+
32
+ sig { params(matcher: T.any(String, Regexp), obj: T.anything, msg: T.anything).returns(MatchData) }
33
+ def assert_match(matcher, obj, msg = nil); end
34
+
35
+ sig { params(obj: T.anything, msg: T.anything).returns(TrueClass) }
36
+ def assert_nil(obj, msg = nil); end
37
+
38
+ sig { params(o1: T.anything, op: T.any(Symbol, String), o2: T.anything, msg: T.anything).returns(TrueClass) }
39
+ def assert_operator(o1, op, o2 = T.unsafe(nil), msg = nil); end
40
+
41
+ sig { params(stdout: T.nilable(T.any(String, Regexp)), stderr: T.nilable(T.any(String, Regexp)), block: T.proc.void).returns(T::Boolean) }
42
+ def assert_output(stdout = nil, stderr = nil, &block); end
43
+
44
+ sig { params(path: T.any(String, Pathname), msg: T.anything).returns(TrueClass) }
45
+ def assert_path_exists(path, msg = nil); end
46
+
47
+ sig { params(block: T.proc.void).returns(TrueClass) }
48
+ def assert_pattern(&block); end
49
+
50
+ sig { params(o1: T.anything, op: T.any(String, Symbol), msg: T.anything).returns(TrueClass) }
51
+ def assert_predicate(o1, op, msg = nil); end
52
+
53
+ sig { params(exp: NilClass, block: T.proc.void).returns(StandardError) }
54
+ sig { type_parameters(:T).params(exp: T.any(T::Class[T.type_parameter(:T)], Regexp, String), block: T.proc.void).returns(T.type_parameter(:T)) }
55
+ def assert_raises(*exp, &block); end
56
+
57
+ sig { params(obj: T.anything, meth: T.any(String, Symbol), msg: T.anything, include_all: T::Boolean).returns(TrueClass) }
58
+ def assert_respond_to(obj, meth, msg = nil, include_all: false); end
59
+
60
+ sig { params(exp: T.anything, act: T.anything, msg: T.anything).returns(TrueClass) }
61
+ def assert_same(exp, act, msg = nil); end
62
+
63
+ sig { params(send_ary: T::Array[T.anything], m: T.anything).returns(T::Boolean) }
64
+ def assert_send(send_ary, m = nil); end
65
+
66
+ sig { params(block: T.proc.void).returns(T::Boolean) }
67
+ def assert_silent(&block); end
68
+
69
+ sig { params(sym: Symbol, msg: T.anything, block: T.proc.void).returns(T.anything) }
70
+ def assert_throws(sym, msg = nil, &block); end
71
+
72
+ sig { params(test: T.anything, msg: T.anything).returns(TrueClass) }
73
+ def refute(test, msg = nil); end
74
+
75
+ sig { params(obj: T.anything, msg: T.anything).returns(TrueClass) }
76
+ def refute_empty(obj, msg = nil); end
77
+
78
+ sig { params(exp: T.anything, act: T.anything, msg: T.anything).returns(TrueClass) }
79
+ def refute_equal(exp, act, msg = nil); end
80
+
81
+ sig { params(exp: T.anything, act: T.anything, delta: Numeric, msg: T.anything).returns(TrueClass) }
82
+ def refute_in_delta(exp, act, delta = T.unsafe(nil), msg = nil); end
83
+
84
+ sig { params(a: T.anything, b: T.anything, epsilon: Numeric, msg: T.anything).returns(TrueClass) }
85
+ def refute_in_epsilon(a, b, epsilon = T.unsafe(nil), msg = nil); end
86
+
87
+ sig { params(collection: T.anything, obj: T.anything, msg: T.anything).returns(TrueClass) }
88
+ def refute_includes(collection, obj, msg = nil); end
89
+
90
+ sig { params(cls: T.anything, obj: T.anything, msg: T.anything).returns(TrueClass) }
91
+ def refute_instance_of(cls, obj, msg = nil); end
92
+
93
+ sig { params(cls: T.anything, obj: T.anything, msg: T.anything).returns(TrueClass) }
94
+ def refute_kind_of(cls, obj, msg = nil); end
95
+
96
+ sig { params(matcher: T.any(String, Regexp), obj: T.anything, msg: T.anything).returns(TrueClass) }
97
+ def refute_match(matcher, obj, msg = nil); end
98
+
99
+ sig { params(obj: T.anything, msg: T.anything).returns(TrueClass) }
100
+ def refute_nil(obj, msg = nil); end
101
+
102
+ sig { params(block: T.proc.void).returns(TrueClass) }
103
+ def refute_pattern(&block); end
104
+
105
+ sig { params(o1: T.anything, op: T.any(Symbol, String), o2: T.anything, msg: T.anything).returns(TrueClass) }
106
+ def refute_operator(o1, op, o2 = T.unsafe(nil), msg = nil); end
107
+
108
+ sig { params(path: T.any(String, Pathname), msg: T.anything).returns(TrueClass) }
109
+ def refute_path_exists(path, msg = nil); end
110
+
111
+ sig { params(o1: T.anything, op: T.any(String, Symbol), msg: T.anything).returns(TrueClass) }
112
+ def refute_predicate(o1, op, msg = nil); end
113
+
114
+ sig { params(obj: T.anything, meth: T.any(String, Symbol), msg: T.anything, include_all: T::Boolean).returns(TrueClass) }
115
+ def refute_respond_to(obj, meth, msg = nil, include_all: false); end
116
+
117
+ sig { params(exp: T.anything, act: T.anything, msg: T.anything).returns(TrueClass) }
118
+ def refute_same(exp, act, msg = nil); end
119
+ end