type_toolkit 0.0.2 → 0.0.3

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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +33 -0
  3. data/README.md +106 -15
  4. data/Rakefile +26 -2
  5. data/config/default.yml +4 -0
  6. data/lib/rubocop/cop/type_toolkit/dont_expect_unexpected_nil.rb +115 -0
  7. data/lib/rubocop-type_toolkit.rb +7 -0
  8. data/lib/type_toolkit/ext/nil_assertions.rb +36 -0
  9. data/lib/type_toolkit/version.rb +2 -1
  10. data/lib/type_toolkit.rb +2 -2
  11. data/sorbet/config +7 -0
  12. data/sorbet/rbi/annotations/.gitattributes +1 -0
  13. data/sorbet/rbi/annotations/minitest.rbi +120 -0
  14. data/sorbet/rbi/annotations/rainbow.rbi +269 -0
  15. data/sorbet/rbi/gems/.gitattributes +1 -0
  16. data/sorbet/rbi/gems/ast@2.4.3.rbi +586 -0
  17. data/sorbet/rbi/gems/benchmark@0.5.0.rbi +637 -0
  18. data/sorbet/rbi/gems/date@3.5.1.rbi +403 -0
  19. data/sorbet/rbi/gems/erb@6.0.1.rbi +816 -0
  20. data/sorbet/rbi/gems/erubi@1.13.1.rbi +157 -0
  21. data/sorbet/rbi/gems/io-console@0.8.2.rbi +9 -0
  22. data/sorbet/rbi/gems/json@2.18.1.rbi +2340 -0
  23. data/sorbet/rbi/gems/language_server-protocol@3.17.0.5.rbi +9 -0
  24. data/sorbet/rbi/gems/lint_roller@1.1.0.rbi +119 -0
  25. data/sorbet/rbi/gems/logger@1.7.0.rbi +963 -0
  26. data/sorbet/rbi/gems/minitest@5.27.0.rbi +1549 -0
  27. data/sorbet/rbi/gems/netrc@0.11.0.rbi +177 -0
  28. data/sorbet/rbi/gems/parallel@1.27.0.rbi +291 -0
  29. data/sorbet/rbi/gems/parser@3.3.10.2.rbi +5537 -0
  30. data/sorbet/rbi/gems/pp@0.6.3.rbi +376 -0
  31. data/sorbet/rbi/gems/prettyprint@0.2.0.rbi +477 -0
  32. data/sorbet/rbi/gems/prism@1.9.0.rbi +43414 -0
  33. data/sorbet/rbi/gems/psych@5.3.1.rbi +2542 -0
  34. data/sorbet/rbi/gems/racc@1.8.1.rbi +168 -0
  35. data/sorbet/rbi/gems/rainbow@3.1.1.rbi +403 -0
  36. data/sorbet/rbi/gems/rake@13.3.1.rbi +3036 -0
  37. data/sorbet/rbi/gems/rbi@0.3.9.rbi +5238 -0
  38. data/sorbet/rbi/gems/rbs@4.0.0.dev.5.rbi +8393 -0
  39. data/sorbet/rbi/gems/rdoc@7.2.0.rbi +13378 -0
  40. data/sorbet/rbi/gems/regexp_parser@2.11.3.rbi +3883 -0
  41. data/sorbet/rbi/gems/reline@0.6.3.rbi +2995 -0
  42. data/sorbet/rbi/gems/require-hooks@0.2.2.rbi +110 -0
  43. data/sorbet/rbi/gems/rexml@3.4.4.rbi +5258 -0
  44. data/sorbet/rbi/gems/rubocop-ast@1.49.0.rbi +7456 -0
  45. data/sorbet/rbi/gems/rubocop-minitest@0.38.2.rbi +2649 -0
  46. data/sorbet/rbi/gems/rubocop-rake@0.7.1.rbi +328 -0
  47. data/sorbet/rbi/gems/rubocop-shopify@2.18.0.rbi +9 -0
  48. data/sorbet/rbi/gems/rubocop@1.84.2.rbi +64803 -0
  49. data/sorbet/rbi/gems/ruby-progressbar@1.13.0.rbi +1318 -0
  50. data/sorbet/rbi/gems/spoom@1.7.11.rbi +5878 -0
  51. data/sorbet/rbi/gems/stringio@3.2.0.rbi +9 -0
  52. data/sorbet/rbi/gems/tapioca@0.17.10.rbi +3513 -0
  53. data/sorbet/rbi/gems/thor@1.5.0.rbi +4476 -0
  54. data/sorbet/rbi/gems/tsort@0.2.0.rbi +393 -0
  55. data/sorbet/rbi/gems/unicode-display_width@3.2.0.rbi +132 -0
  56. data/sorbet/rbi/gems/unicode-emoji@4.2.0.rbi +254 -0
  57. data/sorbet/rbi/gems/yard-sorbet@0.9.0.rbi +430 -0
  58. data/sorbet/rbi/gems/yard@0.9.38.rbi +18425 -0
  59. data/sorbet/rbi/shims/lint_roller.rbi +6 -0
  60. data/sorbet/rbi/shims/minitest.rbi +43 -0
  61. data/sorbet/rbi/shims/rubocop_minitest.rbi +17 -0
  62. data/sorbet/rbi/todo.rbi +5 -0
  63. data/sorbet/tapioca/config.yml +13 -0
  64. data/sorbet/tapioca/require.rb +5 -0
  65. data/spec/.rubocop.yml +13 -0
  66. data/spec/nil_assertions_spec.rb +19 -0
  67. data/spec/rubocop/cop/type_toolkit/dont_expect_unexpected_nil_spec.rb +194 -0
  68. data/spec/spec_helper.rb +8 -0
  69. data/spec/type_toolkit_spec.rb +11 -0
  70. metadata +65 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2d33653934711736d4c8e0eb83bf41f9a28c1393fb21d7c9154b033541073df5
4
- data.tar.gz: ad5d09cbe4a290b4890e63b0cc03e177b78704eba0b2d90036813a6c074972e7
3
+ metadata.gz: d495c6e64eda206b11d7dc9eaaa07bc3eaedfd94e08404ed199e3e8fc55be488
4
+ data.tar.gz: c3265eb72e3675220942f392f4a67d9df862dfae292b24b3602cd572997448cd
5
5
  SHA512:
6
- metadata.gz: c47c4644cc21abebafb856e6e9407006ab4e77223f0674b497baccb09d16de6cc11f7c13d6ba54fc4d4b883d8e825567fcc58d4bf6065ef69fa06fa2dbf53f0e
7
- data.tar.gz: 1d8b8c1a14700403807e14845e617d10856c9ef8b982675785cbe674b7463038993baa6a51ddcecc5a897e1c1bde28600a268b11efaa673c6eeec68e81435dee
6
+ metadata.gz: 615492be957fad036838266b6521e5a98f540ca37128b7d116a1524c4e0fa9c412f70933e51edb3465415e1ff390105a040e4072f8b62770f9140cd50789f001
7
+ data.tar.gz: 17b8774a7b86b8a89081448c56ef834ef463941835b5a48ca9b300e288cf009d48e79acbb3438ca70981f3165ff67d0a49f36539ab6ac7ab706207b0fb29b957
@@ -0,0 +1,33 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+
9
+ jobs:
10
+ ci:
11
+ runs-on: ubuntu-latest
12
+ name: CI checks
13
+ steps:
14
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
15
+ - name: Set up Ruby
16
+ uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1.288.0
17
+ with:
18
+ bundler-cache: true
19
+ rubygems: 4.0.4
20
+ - name: Run type check
21
+ run: bundle exec rake typecheck
22
+ - name: Run type check with Prism parser
23
+ run: bundle exec rake typecheck_prism
24
+ continue-on-error: true
25
+ - name: Run tests
26
+ run: bundle exec rake test
27
+ continue-on-error: true
28
+ - name: Lint Ruby files
29
+ run: bundle exec rake rubocop
30
+ - name: Verify gem RBIs are up-to-date
31
+ run: bin/tapioca gem --verify
32
+ - name: Verify duplicates in shims
33
+ run: bin/tapioca check-shims
data/README.md CHANGED
@@ -1,35 +1,126 @@
1
1
  # TypeToolkit
2
2
 
3
- TODO: Delete this and the text below, and describe your gem
3
+ [💎 RubyGems](https://rubygems.org/gems/type_toolkit)
4
4
 
5
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/type_toolkit`. To experiment with that code, run `bin/console` for an interactive prompt.
5
+ A minimal runtime library for implementing abstract classes, interfaces, and more.
6
6
 
7
7
  ## Installation
8
8
 
9
- TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
9
+ Install Type Toolkit into your bundle, add it to your `Gemfile`:
10
10
 
11
- Install the gem and add to the application's Gemfile by executing:
11
+ ```rb
12
+ gem "type_toolkit"
13
+ ```
14
+
15
+ And then run `bundle install`.
16
+
17
+ ### RuboCop Cops
18
+
19
+ This gem ships with RuboCop cops that we recommend you enable for your application. You can do so by adding it to the `plugins` list of your `rubocop.yml`:
20
+
21
+ ```yml
22
+ plugins:
23
+ - rubocop-other-extension
24
+ - rubocop-type_toolkit
25
+ ```
26
+
27
+ ### Cherry-picking features
28
+
29
+ Simply writing `gem "type_toolkit"` in your `Gemfile` will grab all the tools from the toolkit, which we highly recommend. This adds methods to Ruby's core classes, to make them feel like a native part of the language.
12
30
 
13
- ```bash
14
- bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
31
+ Alternatively, you can cherry-pick only the tools you need. For example, if you only want to use the `not_nil!` assertion, you can add the following to your `Gemfile`:
32
+
33
+ ```rb
34
+ gem "type_toolkit", require: ["type_toolkit/ext/nil_assertions"]
15
35
  ```
16
36
 
17
- If bundler is not being used to manage dependencies, install the gem by executing:
37
+ or you can skip the require in the `Gemfile`, and later manually require it in a specific file:
18
38
 
19
- ```bash
20
- gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
39
+ ```ruby
40
+ gem "type_toolkit", require: false
21
41
  ```
22
42
 
23
- ## Usage
43
+ ```ruby
44
+ # your_script.rb
45
+ require "type_toolkit/ext/nil_assertions"
46
+ ```
24
47
 
25
- TODO: Write usage instructions here
48
+
49
+ ## Tools
50
+
51
+ ### `not_nil!` assertion
52
+
53
+ When debugging a `nil`-related error, it can be difficult to trace back where the `nil` actually originated from. It could have come in from a parameter, whose argument was read from an instance variable, on an object loaded from a cache, populated by some totally different request.
54
+
55
+ If a value can't be nil, it's best for that to be clearly asserted as close to where that nilable value was first generated. That way, a rogue `nil` isn't allowed to propagate arbitrarily far away in downstream code.
56
+
57
+ Type Toolkit provides a `not_nil!` assertion, which will raise an `UnexpectedNilError` if the receiver is `nil`.
58
+
59
+ ```rb
60
+ # `__dir__` can be nil in an "eval", but never in a Ruby file.
61
+ gemfile = Pathname.new(__dir__.not_nil!) / "Gemfile"
62
+ ```
63
+
64
+ `not_nil!` method calls can be chained, to fail early if any value in the chain is `nil`:
65
+
66
+ ```rb
67
+ last_delivery = user.not_nil!
68
+ .orders.last.not_nil!
69
+ .deliveries.last.not_nil!
70
+ ```
71
+
72
+ ## Guiding Principles
73
+
74
+ ### Blazingly fast™
75
+
76
+ All tools should aim to have 0 overhead at runtime, as compared to hand-written Ruby.
77
+
78
+ ### Pay only for what you use
79
+
80
+ There should be no performance cost for a tool that you're not using.
81
+
82
+ Wherever there's an unavoidable cost, it should only ever apply to code that actually uses the tool. **No global costs.**
83
+
84
+ Tools should be optimized for the common case, even if that slows them in rare cases. For example, calling an abstract method is as fast as calling any other method, but only if it's implemented. Calling an unimplemented method call hits the `#method_missing` path, which is significantly slower. This is an acceptable trade-off, because no production code should be calling `#method_missing`, anyway.
85
+
86
+ In all cases, performance costs are quantified and well-documented.
87
+
88
+ ### Feels like Ruby
89
+
90
+ Tools should feel like part of a programming language itself, and less like its standard library. Type Toolkit takes on the implementation complexity so your code doesn't have to.
91
+
92
+ To keep that bar high, the toolkit is lean and deliberately focused on
93
+ language-level primitives. Where practical, new
94
+ features should be built in separate libraries that _use_ the Type Toolkit.
26
95
 
27
96
  ## Development
28
97
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
98
+ This repo has Rake tasks configured for common development tasks:
99
+ 1. `bundle exec rake` to do the next 3 steps all together
100
+ 1. `bundle exec rake rubocop` for linting
101
+ 1. `bundle exec rake typecheck` to typecheck with Sorbet
102
+ 1. `bundle exec rake test` to run all the tests
103
+ 1. `bundle exec rake -T` to list all the tasks
104
+
105
+ ### Releasing
106
+
107
+ This gem is automatically released to [RubyGems.org](https://rubygems.org/gems/type_toolkit) via [Trusted Publishing](https://guides.rubygems.org/trusted-publishing/). To publish a new version of the gem, all you have to do is:
108
+
109
+ 1. Update the version number in [`version.rb`](https://github.com/Shopify/type_toolkit/blob/main/lib/type_toolkit/version.rb)
110
+ * This can either be part of an existing PR, or a new standalone PR.
111
+
112
+ 2. Once that PR is merged, create a tag at the new head of the `main` branch:
113
+
114
+ ```sh
115
+ git pull origin main && git checkout main && git tag v1.2.3
116
+ ```
117
+
118
+ 3. Push the new tag.
30
119
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
120
+ ```sh
121
+ git push origin v1.2.3
122
+ ```
32
123
 
33
- ## Contributing
124
+ This will automatically trigger our [release workflow](https://github.com/Shopify/type_toolkit/actions/workflows/release.yml). It must be approved by a member of the Ruby and Rails Infrastructure team at Shopify before it will run.
34
125
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/type_toolkit.
126
+ Once approved, the workflow will automatically publish the new gem version to RubyGems.org, and create a new [GitHub release](https://github.com/Shopify/type_toolkit/releases).
data/Rakefile CHANGED
@@ -1,12 +1,36 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "bundler/gem_tasks"
4
+
5
+ desc "Type-check the code base with Sorbet"
6
+ task :typecheck do
7
+ sh "bundle exec srb tc" do |ok, _res|
8
+ abort unless ok
9
+ end
10
+ end
11
+
12
+ # Aliases for common names for this task.
13
+ desc "alias for typecheck"; task tc: :typecheck
14
+ desc "alias for typecheck"; task srb: :typecheck
15
+ desc "alias for typecheck"; task sorbet: :typecheck
16
+
17
+ desc "Type-check the code base with Sorbet using Prism"
18
+ task :typecheck_prism do
19
+ sh "bundle exec srb tc --parser=prism" do |ok, _res|
20
+ abort unless ok
21
+ end
22
+ end
23
+
4
24
  require "minitest/test_task"
5
25
 
6
- Minitest::TestTask.create
26
+ Minitest::TestTask.create do |t|
27
+ t.libs.delete("test")
28
+ t.libs << "spec"
29
+ t.test_globs = ["spec/**/*_spec.rb"]
30
+ end
7
31
 
8
32
  require "rubocop/rake_task"
9
33
 
10
34
  RuboCop::RakeTask.new
11
35
 
12
- task default: %i[test rubocop]
36
+ task default: [:typecheck, :test, :rubocop]
@@ -0,0 +1,4 @@
1
+ TypeToolkit/DontExpectUnexpectedNil:
2
+ Description: "Detects misuse of UnexpectedNilError (rescuing, raising, or asserting it)."
3
+ Enabled: true
4
+ VersionAdded: "0.1.0"
@@ -0,0 +1,115 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ require "type_toolkit/ext/nil_assertions"
5
+
6
+ module RuboCop
7
+ module Cop
8
+ module TypeToolkit
9
+ # This cop detects attempts to raise, rescue, or otherwise use the `UnexpectedNilError` class.
10
+ class DontExpectUnexpectedNil < Base
11
+ RESTRICT_ON_SEND = [:assert_raises, :raise].freeze
12
+
13
+ UNEXPECTED_NIL_ERROR_NAME = ::TypeToolkit::UnexpectedNilError.name.not_nil!
14
+ .split("::").last.not_nil!
15
+ .to_sym #: Symbol
16
+ private_constant :UNEXPECTED_NIL_ERROR_NAME
17
+
18
+ #: (RuboCop::AST::SendNode) -> void
19
+ def on_send(node)
20
+ case node.method_name
21
+ when :raise then check_raise(node)
22
+ when :assert_raises then check_assert_raises(node)
23
+ end
24
+ end
25
+
26
+ #: (RuboCop::AST::ResbodyNode) -> void
27
+ def on_resbody(node)
28
+ if (rescued_cls = node.exceptions.find { |ex_class| ex_class.const_type? && unexpected_nil_error?(ex_class) })
29
+ message = "It is always a mistake for `not_nil!` to be called on nil, " \
30
+ "so you should never try to rescue `UnexpectedNilError` specifically. " \
31
+ "Change your code to gracefully handle `nil` instead."
32
+ add_offense(rescued_cls, message:)
33
+ ignore_const_node(rescued_cls)
34
+ end
35
+ end
36
+
37
+ # This is a catch-all for cases where the `UnexpectedNilError` class is used outside of a raise, rescue, etc.
38
+ #: (RuboCop::AST::ConstNode) -> void
39
+ def on_const(node)
40
+ # Don't report this node right away, in case its parent AST is reported by one of the other cases.
41
+ # Instead, record it for now, and maybe report it at the end of the investigation.
42
+ if unexpected_nil_error?(node)
43
+ @const_read_nodes ||= Set.new.compare_by_identity
44
+ @const_read_nodes << node
45
+ end
46
+ end
47
+
48
+ # @override
49
+ #: -> void
50
+ def on_investigation_end
51
+ @const_read_nodes&.each do |node|
52
+ next if @ignored_const_nodes&.include?(node)
53
+
54
+ message = "`UnexpectedNilError` should only ever be used by `#not_nil!`."
55
+ add_offense(node, message:)
56
+ end
57
+
58
+ super
59
+ end
60
+
61
+ private
62
+
63
+ #: (RuboCop::AST::ConstNode) -> bool
64
+ def unexpected_nil_error?(node)
65
+ return false unless node.short_name == UNEXPECTED_NIL_ERROR_NAME
66
+
67
+ ns = node.namespace
68
+ return true if ns.nil? || ns.cbase_type?
69
+
70
+ ns.const_type? && ns.short_name == :TypeToolkit && (ns.namespace.nil? || ns.namespace.cbase_type?)
71
+ end
72
+
73
+ # Check for `raise UnexpectedNilError`
74
+ #: (RuboCop::AST::SendNode) -> void
75
+ def check_raise(node)
76
+ constant = case (first_arg = node.arguments.first)
77
+ when RuboCop::AST::ConstNode
78
+ node.arguments.first
79
+ when RuboCop::AST::SendNode
80
+ return unless first_arg.method_name == :new && first_arg.receiver.const_type?
81
+
82
+ first_arg.receiver
83
+ else return
84
+ end
85
+
86
+ if unexpected_nil_error?(constant)
87
+ message = "`UnexpectedNilError` should only ever be raised by `NilClass#not_nil!`."
88
+ add_offense(node, message:)
89
+ ignore_const_node(constant)
90
+ end
91
+ end
92
+
93
+ # Check for `assert_raises UnexpectedNilError`
94
+ #: (RuboCop::AST::SendNode) -> void
95
+ def check_assert_raises(node)
96
+ if (constants = node.arguments.filter { |arg| arg.const_type? && unexpected_nil_error?(arg) }).any?
97
+ message = "It is always a mistake for `not_nil!` to be called on nil, " \
98
+ "so tests should not expect any code to raise `UnexpectedNilError`. " \
99
+ "Change your code to gracefully handle `nil` instead."
100
+ add_offense(node, message:)
101
+ ignore_const_node(*constants)
102
+ end
103
+ end
104
+
105
+ # Call this when this constant node is part of a node tree that already has an offense.
106
+ # This way we don't report a second offense for the same constant.
107
+ #: (*RuboCop::AST::ConstNode) -> void
108
+ def ignore_const_node(*nodes)
109
+ @ignored_const_nodes ||= Set.new.compare_by_identity
110
+ @ignored_const_nodes.merge(nodes)
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rubocop"
4
+
5
+ RuboCop::ConfigLoader.inject_defaults!(File.join(__dir__, "..", "config", "default.yml"))
6
+
7
+ require_relative "rubocop/cop/type_toolkit/dont_expect_unexpected_nil"
@@ -0,0 +1,36 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ # Asserts that the receiver is not nil.
5
+ #
6
+ # You should use `not_nil!` in places where you're absolutely sure a `nil` value can't occur.
7
+ # This should be done as closely to where the value is created as possible, so that the `nil`
8
+ # value doesn't have a chance to be passed around the system. This way, failures occur close to
9
+ # the source of the problem, and are easier to fix.
10
+ module Kernel
11
+ #: -> self
12
+ def not_nil!
13
+ self
14
+ end
15
+ end
16
+
17
+ class NilClass
18
+ # @override
19
+ #: -> bot
20
+ def not_nil!
21
+ raise TypeToolkit::UnexpectedNilError
22
+ end
23
+ end
24
+
25
+ module TypeToolkit
26
+ # An error raised when calling `#not_nil!` on a `nil` value.
27
+ #
28
+ # `UnexpectedNilError` should never occur in well-formed code, so it should never be rescued.
29
+ # This is why it inherits from `Exception` instead of `StandardError`,
30
+ # so that bare rescues clauses (like `rescue => e`) don't rescue it.
31
+ class UnexpectedNilError < Exception # rubocop:disable Lint/InheritException
32
+ def initialize(message = "Called `not_nil!` on nil.")
33
+ super
34
+ end
35
+ end
36
+ end
@@ -1,5 +1,6 @@
1
+ # typed: strong
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module TypeToolkit
4
- VERSION = "0.0.2"
5
+ VERSION = "0.0.3"
5
6
  end
data/lib/type_toolkit.rb CHANGED
@@ -1,8 +1,8 @@
1
+ # typed: strong
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require_relative "type_toolkit/version"
5
+ require_relative "type_toolkit/ext/nil_assertions"
4
6
 
5
7
  module TypeToolkit
6
- class Error < StandardError; end
7
- # Your code goes here...
8
8
  end
data/sorbet/config ADDED
@@ -0,0 +1,7 @@
1
+ --dir
2
+ .
3
+ --ignore=tmp/
4
+ --ignore=vendor/
5
+ --enable-experimental-rbs-comments
6
+ --suppress-payload-superclass-redefinition-for=RDoc::Markup::Heading
7
+ --disable-watchman
@@ -0,0 +1 @@
1
+ **/*.rbi linguist-vendored=true
@@ -0,0 +1,120 @@
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
+ # @version < 6.0.0
64
+ sig { params(send_ary: T::Array[T.anything], m: T.anything).returns(T::Boolean) }
65
+ def assert_send(send_ary, m = nil); end
66
+
67
+ sig { params(block: T.proc.void).returns(T::Boolean) }
68
+ def assert_silent(&block); end
69
+
70
+ sig { params(sym: Symbol, msg: T.anything, block: T.proc.void).returns(T.anything) }
71
+ def assert_throws(sym, msg = nil, &block); end
72
+
73
+ sig { params(test: T.anything, msg: T.anything).returns(TrueClass) }
74
+ def refute(test, msg = nil); end
75
+
76
+ sig { params(obj: T.anything, msg: T.anything).returns(TrueClass) }
77
+ def refute_empty(obj, msg = nil); end
78
+
79
+ sig { params(exp: T.anything, act: T.anything, msg: T.anything).returns(TrueClass) }
80
+ def refute_equal(exp, act, msg = nil); end
81
+
82
+ sig { params(exp: T.anything, act: T.anything, delta: Numeric, msg: T.anything).returns(TrueClass) }
83
+ def refute_in_delta(exp, act, delta = T.unsafe(nil), msg = nil); end
84
+
85
+ sig { params(a: T.anything, b: T.anything, epsilon: Numeric, msg: T.anything).returns(TrueClass) }
86
+ def refute_in_epsilon(a, b, epsilon = T.unsafe(nil), msg = nil); end
87
+
88
+ sig { params(collection: T.anything, obj: T.anything, msg: T.anything).returns(TrueClass) }
89
+ def refute_includes(collection, obj, msg = nil); end
90
+
91
+ sig { params(cls: T.anything, obj: T.anything, msg: T.anything).returns(TrueClass) }
92
+ def refute_instance_of(cls, obj, msg = nil); end
93
+
94
+ sig { params(cls: T.anything, obj: T.anything, msg: T.anything).returns(TrueClass) }
95
+ def refute_kind_of(cls, obj, msg = nil); end
96
+
97
+ sig { params(matcher: T.any(String, Regexp), obj: T.anything, msg: T.anything).returns(TrueClass) }
98
+ def refute_match(matcher, obj, msg = nil); end
99
+
100
+ sig { params(obj: T.anything, msg: T.anything).returns(TrueClass) }
101
+ def refute_nil(obj, msg = nil); end
102
+
103
+ sig { params(block: T.proc.void).returns(TrueClass) }
104
+ def refute_pattern(&block); end
105
+
106
+ sig { params(o1: T.anything, op: T.any(Symbol, String), o2: T.anything, msg: T.anything).returns(TrueClass) }
107
+ def refute_operator(o1, op, o2 = T.unsafe(nil), msg = nil); end
108
+
109
+ sig { params(path: T.any(String, Pathname), msg: T.anything).returns(TrueClass) }
110
+ def refute_path_exists(path, msg = nil); end
111
+
112
+ sig { params(o1: T.anything, op: T.any(String, Symbol), msg: T.anything).returns(TrueClass) }
113
+ def refute_predicate(o1, op, msg = nil); end
114
+
115
+ sig { params(obj: T.anything, meth: T.any(String, Symbol), msg: T.anything, include_all: T::Boolean).returns(TrueClass) }
116
+ def refute_respond_to(obj, meth, msg = nil, include_all: false); end
117
+
118
+ sig { params(exp: T.anything, act: T.anything, msg: T.anything).returns(TrueClass) }
119
+ def refute_same(exp, act, msg = nil); end
120
+ end