steep 1.7.0.dev.4 → 1.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (153) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +49 -0
  3. data/README.md +18 -0
  4. data/doc/shape.md +18 -0
  5. data/guides/src/gem-rbs-collection/gem-rbs-collection.md +7 -24
  6. data/lib/steep/interface/builder.rb +11 -4
  7. data/lib/steep/rake_task.rb +132 -0
  8. data/lib/steep/signature/validator.rb +184 -132
  9. data/lib/steep/subtyping/check.rb +25 -21
  10. data/lib/steep/type_construction.rb +1 -0
  11. data/lib/steep/version.rb +1 -1
  12. data/steep.gemspec +4 -1
  13. metadata +3 -142
  14. data/.github/dependabot.yml +0 -28
  15. data/.github/workflows/ruby-windows.yml +0 -35
  16. data/.github/workflows/ruby.yml +0 -32
  17. data/.vscode/steep-shared.code-snippets +0 -41
  18. data/Gemfile +0 -14
  19. data/Gemfile.lock +0 -104
  20. data/Gemfile.steep +0 -0
  21. data/gemfile_steep/Gemfile +0 -3
  22. data/gemfile_steep/Gemfile.lock +0 -77
  23. data/rbs_collection.steep.lock.yaml +0 -108
  24. data/rbs_collection.steep.yaml +0 -23
  25. data/sig/shims/bundler.rbs +0 -3
  26. data/sig/shims/concurrent-ruby.rbs +0 -39
  27. data/sig/shims/exception.rbs +0 -4
  28. data/sig/shims/language-server_protocol.rbs +0 -450
  29. data/sig/shims/parser/comment.rbs +0 -33
  30. data/sig/shims/parser/nodes.rbs +0 -252
  31. data/sig/shims/parser/source/map.rbs +0 -146
  32. data/sig/shims/parser/source/range.rbs +0 -237
  33. data/sig/shims/parser.rbs +0 -69
  34. data/sig/shims/string.rbs +0 -4
  35. data/sig/shims/tagged_logging.rbs +0 -6
  36. data/sig/shims/yaml.rbs +0 -4
  37. data/sig/steep/annotation_parser.rbs +0 -60
  38. data/sig/steep/ast/annotation/collection.rbs +0 -78
  39. data/sig/steep/ast/annotation.rbs +0 -121
  40. data/sig/steep/ast/builtin.rbs +0 -69
  41. data/sig/steep/ast/ignore.rbs +0 -66
  42. data/sig/steep/ast/node/type_application.rbs +0 -31
  43. data/sig/steep/ast/node/type_assertion.rbs +0 -32
  44. data/sig/steep/ast/types/any.rbs +0 -29
  45. data/sig/steep/ast/types/boolean.rbs +0 -31
  46. data/sig/steep/ast/types/bot.rbs +0 -29
  47. data/sig/steep/ast/types/class.rbs +0 -33
  48. data/sig/steep/ast/types/factory.rbs +0 -110
  49. data/sig/steep/ast/types/helper.rbs +0 -24
  50. data/sig/steep/ast/types/instance.rbs +0 -33
  51. data/sig/steep/ast/types/intersection.rbs +0 -40
  52. data/sig/steep/ast/types/literal.rbs +0 -35
  53. data/sig/steep/ast/types/logic.rbs +0 -83
  54. data/sig/steep/ast/types/name.rbs +0 -84
  55. data/sig/steep/ast/types/nil.rbs +0 -31
  56. data/sig/steep/ast/types/proc.rbs +0 -53
  57. data/sig/steep/ast/types/record.rbs +0 -39
  58. data/sig/steep/ast/types/self.rbs +0 -33
  59. data/sig/steep/ast/types/top.rbs +0 -29
  60. data/sig/steep/ast/types/tuple.rbs +0 -37
  61. data/sig/steep/ast/types/union.rbs +0 -40
  62. data/sig/steep/ast/types/var.rbs +0 -42
  63. data/sig/steep/ast/types/void.rbs +0 -29
  64. data/sig/steep/ast/types.rbs +0 -16
  65. data/sig/steep/cli.rbs +0 -55
  66. data/sig/steep/diagnostic/deprecated/else_on_exhaustive_case.rbs +0 -13
  67. data/sig/steep/diagnostic/deprecated/unknown_constant_assigned.rbs +0 -15
  68. data/sig/steep/diagnostic/helper.rbs +0 -15
  69. data/sig/steep/diagnostic/lsp_formatter.rbs +0 -36
  70. data/sig/steep/diagnostic/ruby.rbs +0 -703
  71. data/sig/steep/diagnostic/signature.rbs +0 -252
  72. data/sig/steep/drivers/annotations.rbs +0 -17
  73. data/sig/steep/drivers/check.rbs +0 -33
  74. data/sig/steep/drivers/checkfile.rbs +0 -27
  75. data/sig/steep/drivers/diagnostic_printer.rbs +0 -25
  76. data/sig/steep/drivers/init.rbs +0 -19
  77. data/sig/steep/drivers/langserver.rbs +0 -36
  78. data/sig/steep/drivers/print_project.rbs +0 -15
  79. data/sig/steep/drivers/stats.rbs +0 -47
  80. data/sig/steep/drivers/utils/driver_helper.rbs +0 -25
  81. data/sig/steep/drivers/utils/jobs_option.rbs +0 -19
  82. data/sig/steep/drivers/validate.rbs +0 -15
  83. data/sig/steep/drivers/vendor.rbs +0 -19
  84. data/sig/steep/drivers/watch.rbs +0 -27
  85. data/sig/steep/drivers/worker.rbs +0 -29
  86. data/sig/steep/equatable.rbs +0 -11
  87. data/sig/steep/expectations.rbs +0 -72
  88. data/sig/steep/index/rbs_index.rbs +0 -141
  89. data/sig/steep/index/signature_symbol_provider.rbs +0 -41
  90. data/sig/steep/index/source_index.rbs +0 -63
  91. data/sig/steep/interface/block.rbs +0 -41
  92. data/sig/steep/interface/builder.rbs +0 -111
  93. data/sig/steep/interface/function.rbs +0 -271
  94. data/sig/steep/interface/method_type.rbs +0 -105
  95. data/sig/steep/interface/shape.rbs +0 -80
  96. data/sig/steep/interface/substitution.rbs +0 -51
  97. data/sig/steep/interface/type_param.rbs +0 -43
  98. data/sig/steep/method_name.rbs +0 -30
  99. data/sig/steep/module_helper.rbs +0 -16
  100. data/sig/steep/node_helper.rbs +0 -91
  101. data/sig/steep/path_helper.rbs +0 -15
  102. data/sig/steep/project/dsl.rbs +0 -108
  103. data/sig/steep/project/options.rbs +0 -47
  104. data/sig/steep/project/pattern.rbs +0 -47
  105. data/sig/steep/project/target.rbs +0 -25
  106. data/sig/steep/project.rbs +0 -26
  107. data/sig/steep/range_extension.rbs +0 -7
  108. data/sig/steep/server/base_worker.rbs +0 -49
  109. data/sig/steep/server/change_buffer.rbs +0 -38
  110. data/sig/steep/server/delay_queue.rbs +0 -37
  111. data/sig/steep/server/interaction_worker.rbs +0 -90
  112. data/sig/steep/server/lsp_formatter.rbs +0 -63
  113. data/sig/steep/server/master.rbs +0 -299
  114. data/sig/steep/server/type_check_worker.rbs +0 -141
  115. data/sig/steep/server/worker_process.rbs +0 -97
  116. data/sig/steep/services/completion_provider.rbs +0 -264
  117. data/sig/steep/services/content_change.rbs +0 -37
  118. data/sig/steep/services/file_loader.rbs +0 -21
  119. data/sig/steep/services/goto_service.rbs +0 -106
  120. data/sig/steep/services/hover_provider/rbs.rbs +0 -47
  121. data/sig/steep/services/hover_provider/ruby.rbs +0 -127
  122. data/sig/steep/services/hover_provider/singleton_methods.rbs +0 -11
  123. data/sig/steep/services/path_assignment.rbs +0 -21
  124. data/sig/steep/services/signature_help_provider.rbs +0 -51
  125. data/sig/steep/services/signature_service.rbs +0 -156
  126. data/sig/steep/services/stats_calculator.rbs +0 -41
  127. data/sig/steep/services/type_check_service.rbs +0 -112
  128. data/sig/steep/services/type_name_completion.rbs +0 -135
  129. data/sig/steep/signature/validator.rbs +0 -85
  130. data/sig/steep/source/ignore_ranges.rbs +0 -38
  131. data/sig/steep/source.rbs +0 -105
  132. data/sig/steep/subtyping/cache.rbs +0 -17
  133. data/sig/steep/subtyping/check.rbs +0 -131
  134. data/sig/steep/subtyping/constraints.rbs +0 -111
  135. data/sig/steep/subtyping/relation.rbs +0 -63
  136. data/sig/steep/subtyping/result.rbs +0 -179
  137. data/sig/steep/subtyping/variable_variance.rbs +0 -25
  138. data/sig/steep/thread_waiter.rbs +0 -13
  139. data/sig/steep/type_construction.rbs +0 -542
  140. data/sig/steep/type_inference/block_params.rbs +0 -170
  141. data/sig/steep/type_inference/case_when.rbs +0 -130
  142. data/sig/steep/type_inference/constant_env.rbs +0 -29
  143. data/sig/steep/type_inference/context.rbs +0 -216
  144. data/sig/steep/type_inference/context_array.rbs +0 -38
  145. data/sig/steep/type_inference/logic_type_interpreter.rbs +0 -108
  146. data/sig/steep/type_inference/method_call.rbs +0 -124
  147. data/sig/steep/type_inference/method_params.rbs +0 -127
  148. data/sig/steep/type_inference/multiple_assignment.rbs +0 -76
  149. data/sig/steep/type_inference/send_args.rbs +0 -243
  150. data/sig/steep/type_inference/type_env.rbs +0 -160
  151. data/sig/steep/type_inference/type_env_builder.rbs +0 -81
  152. data/sig/steep/typing.rbs +0 -75
  153. data/sig/steep.rbs +0 -45
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 17795ed14e183d6e8858e6ea8f57f71dbd3cdced0e4d9cf7e43c646188e486cd
4
- data.tar.gz: 7005e9d96f44f23a47f1844597b86fd3d774f000b1de5cf100d235e68c56a0b5
3
+ metadata.gz: 6031a713ec97be707b33a667121cba53ba966e30c0949c1070c62ccf4c698596
4
+ data.tar.gz: 01cd81e06eb1228a4b01070e0f6a12098fe10ee2cfe7620434a629f70e504005
5
5
  SHA512:
6
- metadata.gz: e178baa7a185edaafb359032266bfa7f29d082c9da30ca418e5ef4030b5723423f3f36ba4165a640d996e252bb91883dcfe55b1f750f51c3153452b368e5a9ee
7
- data.tar.gz: 8919d4c047097e7e7fd63ecba71ae96f412a56588c7b6ff1d381838d2d935d2ba7dc382ca83fe5b679f35ebbe298460e80e87047c88b6ebcc5e3e6ef258e2535
6
+ metadata.gz: abfac9447afb1c68ba1702738f1ffd67c9b2cddc860a84a4552b963eafd3e9936987c2085d25b565b8834bc70be49bf5271daa28ac02926db12a5d056cc0780b
7
+ data.tar.gz: '0871a287d3bc466c58a9106def0ed944e682c862f5ab30d849cfd9dfdcbd9aefb49b376791c6a61211f0cfefef000d05f62e7b0ce3a5045faf9f2f9a39eadc0d'
data/CHANGELOG.md CHANGED
@@ -1,5 +1,54 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 1.7.1 (2024-06-12)
4
+
5
+ ### Type checker core
6
+
7
+ * Fix subtyping issues ([#1165](https://github.com/soutaro/steep/pull/1165))
8
+
9
+ ## 1.7.0 (2024-06-07)
10
+
11
+ ### Type checker core
12
+
13
+ * Implement untyped function params ([#1101](https://github.com/soutaro/steep/pull/1101))
14
+ * Fix method call type narrowing with`||` operator ([#1085](https://github.com/soutaro/steep/pull/1085))
15
+ * Refactor `Interface::Builder` ([#1081](https://github.com/soutaro/steep/pull/1081))
16
+ * Fix UnexpectedError with unnamed arguments ([#1041](https://github.com/soutaro/steep/pull/1041))
17
+ * Abort if subtyping fails to (possible) infinite loop ([#1055](https://github.com/soutaro/steep/pull/1055))
18
+ * Ignore diagnostics by `steep:ignore` comment ([#1034](https://github.com/soutaro/steep/pull/1034))
19
+ * Make defined? accept any type ([#1031](https://github.com/soutaro/steep/pull/1031))
20
+ * Refactor case-when syntax ([#999](https://github.com/soutaro/steep/pull/999))
21
+ * Update `Steep::Subtyping::Check#check` types ([#972](https://github.com/soutaro/steep/pull/972))
22
+
23
+ ### Commandline tool
24
+
25
+ * Improve wildcard handling in pattern matching for directory paths ([#1121](https://github.com/soutaro/steep/pull/1121))
26
+ * Fix issue with wildcard expansion in FileLoader ([#1113](https://github.com/soutaro/steep/pull/1113))
27
+ * Avoid unnecessary calling `RBS::Location#to_s` on debug log ([#1092](https://github.com/soutaro/steep/pull/1092))
28
+ * Better recovery from collection problems ([#987](https://github.com/soutaro/steep/pull/987))
29
+ * Handle absolute path ([#975](https://github.com/soutaro/steep/pull/975))
30
+ * Default to check the entire current directory when there is no `Steepfile` ([#968](https://github.com/soutaro/steep/pull/968))
31
+
32
+ ### Language server
33
+
34
+ * Fix variable untyped hover issue in rescue clause ([#1147](https://github.com/soutaro/steep/pull/1147))
35
+ * Handle `$/file/reset` request in interaction worker ([#1122](https://github.com/soutaro/steep/pull/1122))
36
+ * Skip pending UI jobs ([#1035](https://github.com/soutaro/steep/pull/1035))
37
+ * Fix no method error ([#1040](https://github.com/soutaro/steep/pull/1040))
38
+ * Implement completion for comments ([#1039](https://github.com/soutaro/steep/pull/1039))
39
+ * Fix signature help ([#1038](https://github.com/soutaro/steep/pull/1038))
40
+
41
+ ### Miscellaneous
42
+
43
+ * Revise rake tasks ([#1156](https://github.com/soutaro/steep/pull/1156))
44
+ * Update `steep.gemspec` ([#1155](https://github.com/soutaro/steep/pull/1155))
45
+ * Add `Steep::RakeTask` ([#995](https://github.com/soutaro/steep/pull/995))
46
+ * Stop to distribute sig dir ([#1144](https://github.com/soutaro/steep/pull/1144))
47
+ * Update gem-rbs-collection.md ([#1127](https://github.com/soutaro/steep/pull/1127))
48
+ * Add shape docs ([#1089](https://github.com/soutaro/steep/pull/1089))
49
+ * Ignore smoke tests when packaging gem ([#962](https://github.com/soutaro/steep/pull/962))
50
+ * Fix setup for Ruby 3.3 ([#1000](https://github.com/soutaro/steep/pull/1000))
51
+
3
52
  ## master
4
53
 
5
54
  ## 1.6.0 (2023-11-09)
data/README.md CHANGED
@@ -219,6 +219,24 @@ Steep implements some of the Language Server Protocol features.
219
219
 
220
220
  Other LSP supporting tools may work with Steep where it starts the server as `steep langserver`.
221
221
 
222
+ ## Rake Tasks
223
+
224
+ Steep comes with a set of configurable Rake tasks.
225
+
226
+ ```ruby
227
+ # Rakefile
228
+
229
+ require "steep/rake_task"
230
+ Steep::RakeTask.new do |t|
231
+ t.check.severity_level = :error
232
+ t.watch.verbose
233
+ end
234
+
235
+ task default: [:steep]
236
+ ```
237
+
238
+ Use `bundle exec rake -T` to see all available tasks.
239
+
222
240
  ## Development
223
241
 
224
242
  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.
data/doc/shape.md CHANGED
@@ -24,7 +24,9 @@ Shape (_Foo) {
24
24
  Note that the `self` type in the example is resolved to `_Foo` during shape calculation.
25
25
 
26
26
  The shape calculation of an object is straightforward. Calculate a `RBS::Definition` of a class singleton/instance, or an interface, and translate the data structure to a `Shape` object. But there are a few things to consider.
27
+
27
28
  ## Tuple, record, and proc types
29
+
28
30
  The shape of tuple, record, or proc types are based on their base types -- Array, Hash, or Proc classes --, but with specialized method types.
29
31
 
30
32
  ```
@@ -37,16 +39,22 @@ Shape ([Integer, String]) {
37
39
  ```
38
40
 
39
41
  The specialization is implemented as a part of shape calculation.
42
+
40
43
  ## Special methods
44
+
41
45
  Steep recognizes some special methods for type narrowing, including `#is_a?`, `#===`, `#nil?`, ... These methods are defined with normal RBS syntax, but the method types in shapes are transformed to types using logic types.
42
46
 
43
47
  The shape calculation inserts the specialized methods with these special methods.
48
+
44
49
  ## `self` types
50
+
45
51
  There are two cases of `self` types to consider during shape calculation.
46
52
 
47
53
  1. `self` types included in the shape of a type
48
54
  2. `self` types included in given types
55
+
49
56
  ### 1. `self` types included in the shape of a type
57
+
50
58
  `self` types may be included in a class or interface definition.
51
59
 
52
60
  ```rbs
@@ -62,7 +70,9 @@ Shape (_Foo) {
62
70
  itself: () -> _Foo
63
71
  }
64
72
  ```
73
+
65
74
  ### 2. `self` types included in given types
75
+
66
76
  Unlike `self` types included in definitions, `self` types in given types should be preserved.
67
77
 
68
78
  ```rbs
@@ -100,7 +110,9 @@ end
100
110
  ```
101
111
 
102
112
  We want the type of `foo.get` to be `self`, not `Foo`, to avoid a type error being detected.
113
+
103
114
  ## Shape of `self` types
115
+
104
116
  We also want `self` type if `self` is the type of the shape.
105
117
 
106
118
  ```rb
@@ -154,7 +166,9 @@ Shape (Foo | Bar) {
154
166
  So, the resulting type of `self.foo` where the type of `self` is `Foo | Bar`, would be `Integer | Foo | Bar`. But, actually, it won't be `Foo` because the `self` comes from `Bar`.
155
167
 
156
168
  This is an incorrect result, but Steep is doing this right now.
169
+
157
170
  ## `class` and `instance` types
171
+
158
172
  The shape calculation provides limited support for `class` and `instance` types.
159
173
 
160
174
  1. `class`/`instance` types from the definition are resolved
@@ -162,13 +176,17 @@ The shape calculation provides limited support for `class` and `instance` types.
162
176
  3. Shape of `class`/`instance` types are resolved to configuration's `class_type` and `instance_type`, and the translated types are used to calculate the shape
163
177
 
164
178
  It's different from `self` types except case #2. The relationship between `self`/`class`/`instance` is not trivial in Ruby. All of them might be resolved to any type, which means calculating one from another of them is simply impossible.
179
+
165
180
  ## Public methods, private methods
181
+
166
182
  `Shape` objects have a flag of if the shape is for *public* method calls or *private* method calls. Private method call is a form of `foo()` or `self.foo()` -- when the receiver is omitted or `self`. Public method calls are anything else.
167
183
 
168
184
  The shape calculation starts with *private methods*, and the `Shape#public_shape` method returns another shape that only has *public* methods.
169
185
 
170
186
  > Note that the private shape calculation is required even on public method calls. This means a possible chance of future optimizations.
187
+
171
188
  ## Lazy method type calculation
189
+
172
190
  We rarely need all of the methods available for an object. If we want to type check a method call, we only need the method type of that method. All other methods can be just ignored.
173
191
 
174
192
  *Lazy method type calculation* is introduced for that case. Instead of calculating the types of all of the methods, it registers a block that computes the method type.
@@ -12,30 +12,13 @@ Run rbs-collection-init to start setup.
12
12
  $ rbs collection init
13
13
  ```
14
14
 
15
- You have to edit the generated `rbs_collection.yaml` file. Add a few lines under gems section.
16
-
17
- ```yaml
18
- # Download sources
19
- sources:
20
- - name: ruby/gem_rbs_collection
21
- remote: https://github.com/ruby/gem_rbs_collection.git
22
- revision: main
23
- repo_dir: gems
24
-
25
- # A directory to install the downloaded RBSs
26
- path: .gem_rbs_collection
27
-
28
- gems:
29
- # Skip loading rbs gem's RBS.
30
- # It's unnecessary if you don't use rbs as a library.
31
- - name: rbs
32
- ignore: true
33
- - name: steep
34
- ignore: true
35
- - name: rbs_rails # Add these lines if you use rbs_rails
36
- ignore: true
37
- - name: rbs_protobuf # Add these lines if you use rbs_protobuf
38
- ignore: true
15
+ You have to edit your `Gemfile`. Specify `require: false` for gems for which you do not want type definitions.
16
+
17
+ ```ruby
18
+ gem 'rbs', require: false
19
+ gem 'steep, require: false
20
+ gem 'rbs_rails', require: false
21
+ gem 'rbs_protobuf', require: false
39
22
  ```
40
23
 
41
24
  Once you save the file, run the install command.
@@ -9,8 +9,6 @@ module Steep
9
9
  @class_type = class_type
10
10
  @instance_type = instance_type
11
11
  @variable_bounds = variable_bounds
12
-
13
- validate
14
12
  end
15
13
 
16
14
  def self.empty
@@ -23,11 +21,16 @@ module Steep
23
21
  end
24
22
  end
25
23
 
26
- def validate
24
+ def validate_self_type
27
25
  validate_fvs(:self_type, self_type)
26
+ end
27
+
28
+ def validate_instance_type
28
29
  validate_fvs(:instance_type, instance_type)
30
+ end
31
+
32
+ def validate_class_type
29
33
  validate_fvs(:class_type, class_type)
30
- self
31
34
  end
32
35
 
33
36
  def validate_fvs(name, type)
@@ -37,6 +40,7 @@ module Steep
37
40
  raise "#{name} cannot include 'self' type: #{type}"
38
41
  end
39
42
  if fvs.include?(AST::Types::Instance.instance)
43
+ Steep.logger.fatal { "#{name} cannot include 'instance' type: #{type}" }
40
44
  raise "#{name} cannot include 'instance' type: #{type}"
41
45
  end
42
46
  if fvs.include?(AST::Types::Class.instance)
@@ -87,12 +91,15 @@ module Steep
87
91
  def raw_shape(type, config)
88
92
  case type
89
93
  when AST::Types::Self
94
+ config.validate_self_type
90
95
  self_type = config.self_type or raise
91
96
  self_shape(self_type, config)
92
97
  when AST::Types::Instance
98
+ config.validate_instance_type
93
99
  instance_type = config.instance_type or raise
94
100
  raw_shape(instance_type, config)
95
101
  when AST::Types::Class
102
+ config.validate_class_type
96
103
  klass_type = config.class_type or raise
97
104
  raw_shape(klass_type, config)
98
105
  when AST::Types::Name::Singleton
@@ -0,0 +1,132 @@
1
+ require "rake"
2
+ require "rake/tasklib"
3
+ require "steep/cli"
4
+
5
+ module Steep
6
+ # Provides Rake tasks for running Steep commands.
7
+ #
8
+ # require "steep/rake_task"
9
+ # Steep::RakeTask.new do |t|
10
+ # t.check.severity_level = :error
11
+ # t.watch.verbose
12
+ # t.stats << "--format=table"
13
+ # end
14
+ class RakeTask < Rake::TaskLib # steep:ignore UnknownConstant
15
+ attr_accessor :name
16
+
17
+ def self.available_commands
18
+ %i(init check stats binstub project watch)
19
+ end
20
+
21
+ def initialize(name = :steep, cli_runner = default_cli_runner)
22
+ super()
23
+
24
+ @name = name
25
+
26
+ configuration = TaskConfiguration.new
27
+
28
+ yield configuration if block_given?
29
+
30
+ define_tasks(configuration, cli_runner)
31
+ end
32
+
33
+ private
34
+
35
+ # :nodoc:
36
+ class TaskConfiguration
37
+ def initialize
38
+ @commands = {}
39
+ end
40
+
41
+ def method_missing(command)
42
+ if respond_to?(command)
43
+ @commands[command] ||= CommandConfiguration.new
44
+ else
45
+ super
46
+ end
47
+ end
48
+
49
+ def respond_to_missing?(name, include_private = false)
50
+ RakeTask.available_commands.include?(name) || super
51
+ end
52
+
53
+ def options(command)
54
+ @commands[command]&.to_a || []
55
+ end
56
+ end
57
+
58
+ # :nodoc:
59
+ class CommandConfiguration
60
+ def initialize
61
+ @options = []
62
+ end
63
+
64
+ def method_missing(name, value = nil)
65
+ option = "--#{name.to_s.gsub(/_/, '-').gsub(/=/, '')}"
66
+ option << "=#{value}" if value
67
+
68
+ self << option
69
+ end
70
+
71
+ def respond_to_missing?(_name)
72
+ true
73
+ end
74
+
75
+ def <<(value)
76
+ @options << value
77
+ self
78
+ end
79
+
80
+ def to_a
81
+ @options
82
+ end
83
+ end
84
+
85
+ def default_cli_runner
86
+ lambda do |arguments|
87
+ require "steep"
88
+
89
+ cli = Steep::CLI.new(
90
+ stdout: $stdout,
91
+ stdin: $stdin,
92
+ stderr: $stderr,
93
+ argv: arguments
94
+ )
95
+
96
+ cli.run
97
+ end
98
+ end
99
+
100
+ def define_tasks(configuration, cli_runner)
101
+ namespace name do
102
+ RakeTask.available_commands.each do |command|
103
+ desc "Run steep #{command}"
104
+ task command do |_, args|
105
+ configured_options = configuration.options(command)
106
+
107
+ argv = [
108
+ command.to_s,
109
+ *configured_options,
110
+ *args.extras
111
+ ]
112
+
113
+ result = cli_runner[argv]
114
+
115
+ raise "Steep failed" if result.nonzero?
116
+ end
117
+ end
118
+
119
+ desc "Run steep help"
120
+ task "help" do
121
+ arguments = ["--help"]
122
+
123
+ cli_runner[arguments]
124
+ end
125
+ end
126
+
127
+ # Default steep task to steep:check
128
+ desc "Run steep check" unless ::Rake.application.last_description # steep:ignore UnknownConstant
129
+ task name => ["#{name}:check"]
130
+ end
131
+ end
132
+ end