steep-relaxed 1.9.3.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 (165) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.gitmodules +0 -0
  4. data/CHANGELOG.md +1032 -0
  5. data/LICENSE +21 -0
  6. data/README.md +260 -0
  7. data/Rakefile +227 -0
  8. data/STDGEM_DEPENDENCIES.txt +59 -0
  9. data/Steepfile +68 -0
  10. data/bin/console +14 -0
  11. data/bin/generate-diagnostics-docs.rb +112 -0
  12. data/bin/mem_graph.rb +67 -0
  13. data/bin/mem_prof.rb +102 -0
  14. data/bin/output_rebaseline.rb +34 -0
  15. data/bin/output_test.rb +60 -0
  16. data/bin/rbs +20 -0
  17. data/bin/rbs-inline +19 -0
  18. data/bin/setup +9 -0
  19. data/bin/stackprof_test.rb +19 -0
  20. data/bin/steep +19 -0
  21. data/bin/steep-check.rb +251 -0
  22. data/bin/steep-prof +16 -0
  23. data/doc/narrowing.md +195 -0
  24. data/doc/shape.md +194 -0
  25. data/exe/steep +18 -0
  26. data/guides/README.md +5 -0
  27. data/guides/src/gem-rbs-collection/gem-rbs-collection.md +126 -0
  28. data/guides/src/getting-started/getting-started.md +163 -0
  29. data/guides/src/nil-optional/nil-optional.md +195 -0
  30. data/lib/steep/annotation_parser.rb +199 -0
  31. data/lib/steep/ast/annotation/collection.rb +172 -0
  32. data/lib/steep/ast/annotation.rb +137 -0
  33. data/lib/steep/ast/builtin.rb +104 -0
  34. data/lib/steep/ast/ignore.rb +148 -0
  35. data/lib/steep/ast/node/type_application.rb +88 -0
  36. data/lib/steep/ast/node/type_assertion.rb +81 -0
  37. data/lib/steep/ast/types/any.rb +35 -0
  38. data/lib/steep/ast/types/boolean.rb +45 -0
  39. data/lib/steep/ast/types/bot.rb +35 -0
  40. data/lib/steep/ast/types/class.rb +43 -0
  41. data/lib/steep/ast/types/factory.rb +557 -0
  42. data/lib/steep/ast/types/helper.rb +40 -0
  43. data/lib/steep/ast/types/instance.rb +42 -0
  44. data/lib/steep/ast/types/intersection.rb +93 -0
  45. data/lib/steep/ast/types/literal.rb +59 -0
  46. data/lib/steep/ast/types/logic.rb +84 -0
  47. data/lib/steep/ast/types/name.rb +128 -0
  48. data/lib/steep/ast/types/nil.rb +41 -0
  49. data/lib/steep/ast/types/proc.rb +117 -0
  50. data/lib/steep/ast/types/record.rb +79 -0
  51. data/lib/steep/ast/types/self.rb +43 -0
  52. data/lib/steep/ast/types/shared_instance.rb +11 -0
  53. data/lib/steep/ast/types/top.rb +35 -0
  54. data/lib/steep/ast/types/tuple.rb +60 -0
  55. data/lib/steep/ast/types/union.rb +97 -0
  56. data/lib/steep/ast/types/var.rb +65 -0
  57. data/lib/steep/ast/types/void.rb +35 -0
  58. data/lib/steep/cli.rb +401 -0
  59. data/lib/steep/diagnostic/deprecated/else_on_exhaustive_case.rb +20 -0
  60. data/lib/steep/diagnostic/deprecated/unknown_constant_assigned.rb +28 -0
  61. data/lib/steep/diagnostic/helper.rb +18 -0
  62. data/lib/steep/diagnostic/lsp_formatter.rb +78 -0
  63. data/lib/steep/diagnostic/result_printer2.rb +48 -0
  64. data/lib/steep/diagnostic/ruby.rb +1221 -0
  65. data/lib/steep/diagnostic/signature.rb +570 -0
  66. data/lib/steep/drivers/annotations.rb +52 -0
  67. data/lib/steep/drivers/check.rb +339 -0
  68. data/lib/steep/drivers/checkfile.rb +210 -0
  69. data/lib/steep/drivers/diagnostic_printer.rb +105 -0
  70. data/lib/steep/drivers/init.rb +66 -0
  71. data/lib/steep/drivers/langserver.rb +56 -0
  72. data/lib/steep/drivers/print_project.rb +113 -0
  73. data/lib/steep/drivers/stats.rb +203 -0
  74. data/lib/steep/drivers/utils/driver_helper.rb +143 -0
  75. data/lib/steep/drivers/utils/jobs_option.rb +26 -0
  76. data/lib/steep/drivers/vendor.rb +27 -0
  77. data/lib/steep/drivers/watch.rb +194 -0
  78. data/lib/steep/drivers/worker.rb +58 -0
  79. data/lib/steep/equatable.rb +23 -0
  80. data/lib/steep/expectations.rb +228 -0
  81. data/lib/steep/index/rbs_index.rb +350 -0
  82. data/lib/steep/index/signature_symbol_provider.rb +185 -0
  83. data/lib/steep/index/source_index.rb +167 -0
  84. data/lib/steep/interface/block.rb +103 -0
  85. data/lib/steep/interface/builder.rb +843 -0
  86. data/lib/steep/interface/function.rb +1090 -0
  87. data/lib/steep/interface/method_type.rb +330 -0
  88. data/lib/steep/interface/shape.rb +239 -0
  89. data/lib/steep/interface/substitution.rb +159 -0
  90. data/lib/steep/interface/type_param.rb +115 -0
  91. data/lib/steep/located_value.rb +20 -0
  92. data/lib/steep/method_name.rb +42 -0
  93. data/lib/steep/module_helper.rb +24 -0
  94. data/lib/steep/node_helper.rb +273 -0
  95. data/lib/steep/path_helper.rb +30 -0
  96. data/lib/steep/project/dsl.rb +268 -0
  97. data/lib/steep/project/group.rb +31 -0
  98. data/lib/steep/project/options.rb +63 -0
  99. data/lib/steep/project/pattern.rb +59 -0
  100. data/lib/steep/project/target.rb +92 -0
  101. data/lib/steep/project.rb +78 -0
  102. data/lib/steep/rake_task.rb +132 -0
  103. data/lib/steep/range_extension.rb +29 -0
  104. data/lib/steep/server/base_worker.rb +97 -0
  105. data/lib/steep/server/change_buffer.rb +73 -0
  106. data/lib/steep/server/custom_methods.rb +77 -0
  107. data/lib/steep/server/delay_queue.rb +45 -0
  108. data/lib/steep/server/interaction_worker.rb +492 -0
  109. data/lib/steep/server/lsp_formatter.rb +455 -0
  110. data/lib/steep/server/master.rb +922 -0
  111. data/lib/steep/server/target_group_files.rb +205 -0
  112. data/lib/steep/server/type_check_controller.rb +366 -0
  113. data/lib/steep/server/type_check_worker.rb +303 -0
  114. data/lib/steep/server/work_done_progress.rb +64 -0
  115. data/lib/steep/server/worker_process.rb +176 -0
  116. data/lib/steep/services/completion_provider.rb +802 -0
  117. data/lib/steep/services/content_change.rb +61 -0
  118. data/lib/steep/services/file_loader.rb +74 -0
  119. data/lib/steep/services/goto_service.rb +441 -0
  120. data/lib/steep/services/hover_provider/rbs.rb +88 -0
  121. data/lib/steep/services/hover_provider/ruby.rb +221 -0
  122. data/lib/steep/services/hover_provider/singleton_methods.rb +20 -0
  123. data/lib/steep/services/path_assignment.rb +46 -0
  124. data/lib/steep/services/signature_help_provider.rb +202 -0
  125. data/lib/steep/services/signature_service.rb +428 -0
  126. data/lib/steep/services/stats_calculator.rb +68 -0
  127. data/lib/steep/services/type_check_service.rb +394 -0
  128. data/lib/steep/services/type_name_completion.rb +236 -0
  129. data/lib/steep/signature/validator.rb +651 -0
  130. data/lib/steep/source/ignore_ranges.rb +69 -0
  131. data/lib/steep/source.rb +691 -0
  132. data/lib/steep/subtyping/cache.rb +30 -0
  133. data/lib/steep/subtyping/check.rb +1113 -0
  134. data/lib/steep/subtyping/constraints.rb +341 -0
  135. data/lib/steep/subtyping/relation.rb +101 -0
  136. data/lib/steep/subtyping/result.rb +324 -0
  137. data/lib/steep/subtyping/variable_variance.rb +89 -0
  138. data/lib/steep/test.rb +9 -0
  139. data/lib/steep/thread_waiter.rb +43 -0
  140. data/lib/steep/type_construction.rb +5183 -0
  141. data/lib/steep/type_inference/block_params.rb +416 -0
  142. data/lib/steep/type_inference/case_when.rb +303 -0
  143. data/lib/steep/type_inference/constant_env.rb +56 -0
  144. data/lib/steep/type_inference/context.rb +195 -0
  145. data/lib/steep/type_inference/logic_type_interpreter.rb +613 -0
  146. data/lib/steep/type_inference/method_call.rb +193 -0
  147. data/lib/steep/type_inference/method_params.rb +531 -0
  148. data/lib/steep/type_inference/multiple_assignment.rb +194 -0
  149. data/lib/steep/type_inference/send_args.rb +712 -0
  150. data/lib/steep/type_inference/type_env.rb +341 -0
  151. data/lib/steep/type_inference/type_env_builder.rb +138 -0
  152. data/lib/steep/typing.rb +321 -0
  153. data/lib/steep/version.rb +3 -0
  154. data/lib/steep.rb +369 -0
  155. data/manual/annotations.md +181 -0
  156. data/manual/ignore.md +20 -0
  157. data/manual/ruby-diagnostics.md +1879 -0
  158. data/sample/Steepfile +22 -0
  159. data/sample/lib/conference.rb +49 -0
  160. data/sample/lib/length.rb +35 -0
  161. data/sample/sig/conference.rbs +42 -0
  162. data/sample/sig/generics.rbs +15 -0
  163. data/sample/sig/length.rbs +34 -0
  164. data/steep-relaxed.gemspec +56 -0
  165. metadata +340 -0
@@ -0,0 +1,159 @@
1
+ module Steep
2
+ module Interface
3
+ class Substitution
4
+ class InvalidSubstitutionError < StandardError
5
+ attr_reader :vars_size
6
+ attr_reader :types_size
7
+
8
+ def initialize(vars_size:, types_size:)
9
+ @vars_size = vars_size
10
+ @types_size = types_size
11
+
12
+ super "Invalid substitution: vars.size=#{vars_size}, types.size=#{types_size}"
13
+ end
14
+ end
15
+
16
+ attr_reader :dictionary
17
+ attr_reader :instance_type
18
+ attr_reader :module_type
19
+ attr_reader :self_type
20
+
21
+ def initialize(dictionary:, instance_type:, module_type:, self_type:)
22
+ @dictionary = dictionary
23
+ @instance_type = instance_type
24
+ @module_type = module_type
25
+ @self_type = self_type
26
+ end
27
+
28
+ def self.empty
29
+ new(dictionary: {},
30
+ instance_type: AST::Types::Instance.instance,
31
+ module_type: AST::Types::Class.instance,
32
+ self_type: AST::Types::Self.instance)
33
+ end
34
+
35
+ def empty?
36
+ dictionary.empty? &&
37
+ instance_type.is_a?(AST::Types::Instance) &&
38
+ module_type.is_a?(AST::Types::Class) &&
39
+ self_type.is_a?(AST::Types::Self)
40
+ end
41
+
42
+ def domain
43
+ set = Set.new
44
+
45
+ set.merge(dictionary.keys)
46
+ set << AST::Types::Self.instance if self_type
47
+ set << AST::Types::Class.instance if module_type
48
+ set << AST::Types::Instance.instance if instance_type
49
+
50
+ set
51
+ end
52
+
53
+ def to_s
54
+ a = [] #: Array[String]
55
+
56
+ dictionary.each do |x, ty|
57
+ a << "#{x} -> #{ty}"
58
+ end
59
+
60
+ a << "[instance_type] -> #{instance_type}"
61
+ a << "[module_type] -> #{module_type}"
62
+ a << "[self_type] -> #{self_type}"
63
+
64
+ "{ #{a.join(", ")} }"
65
+ end
66
+
67
+ def [](key)
68
+ dictionary[key] or raise "Unknown variable: #{key}"
69
+ end
70
+
71
+ def key?(var)
72
+ dictionary.key?(var)
73
+ end
74
+
75
+ def apply?(type)
76
+ case type
77
+ when AST::Types::Var
78
+ key?(type.name)
79
+ when AST::Types::Self
80
+ !self_type.is_a?(AST::Types::Self)
81
+ when AST::Types::Instance
82
+ !instance_type.is_a?(AST::Types::Instance)
83
+ when AST::Types::Class
84
+ !module_type.is_a?(AST::Types::Class)
85
+ when AST::Types::Name::Applying
86
+ type.args.any? {|ty| apply?(ty) }
87
+ else
88
+ type.each_child.any? {|t| apply?(t) }
89
+ end
90
+ end
91
+
92
+ def self.build(vars, types = nil, instance_type: nil, module_type: nil, self_type: nil)
93
+ types ||= vars.map {|var| AST::Types::Var.fresh(var) }
94
+
95
+ raise InvalidSubstitutionError.new(vars_size: vars.size, types_size: types.size) unless vars.size == types.size
96
+
97
+ dic = vars.zip(types).each.with_object({}) do |(var, type), d| #$ Hash[Symbol, AST::Types::t]
98
+ type or raise
99
+ d[var] = type
100
+ end
101
+
102
+ new(dictionary: dic, instance_type: instance_type, module_type: module_type, self_type: self_type)
103
+ end
104
+
105
+ def except(vars)
106
+ self.class.new(
107
+ dictionary: dictionary.dup,
108
+ instance_type: instance_type,
109
+ module_type: module_type,
110
+ self_type: self_type
111
+ ).except!(vars)
112
+ end
113
+
114
+ def except!(vars)
115
+ vars.each do |var|
116
+ dictionary.delete(var)
117
+ end
118
+
119
+ self
120
+ end
121
+
122
+ def merge!(s, overwrite: false)
123
+ dictionary.transform_values! {|ty| ty.subst(s) }
124
+ dictionary.merge!(s.dictionary) do |key, a, b|
125
+ if a == b
126
+ a
127
+ else
128
+ if overwrite
129
+ b
130
+ else
131
+ raise "Duplicated key on merge!: #{key}, #{a}, #{b} (#{self})"
132
+ end
133
+ end
134
+ end
135
+
136
+ @instance_type = instance_type.subst(s) if instance_type
137
+ @module_type = module_type.subst(s) if module_type
138
+ @self_type = self_type.subst(s) if self_type
139
+
140
+ self
141
+ end
142
+
143
+ def update(self_type: self_type(), instance_type: instance_type(), module_type: module_type())
144
+ Substitution.new(dictionary: dictionary.dup, instance_type: instance_type, self_type: self_type, module_type: module_type)
145
+ end
146
+
147
+ def merge(s)
148
+ Substitution.new(dictionary: dictionary.dup,
149
+ instance_type: instance_type,
150
+ module_type: module_type,
151
+ self_type: self_type).merge!(s)
152
+ end
153
+
154
+ def add!(v, ty)
155
+ merge!(Substitution.new(dictionary: { v => ty }, instance_type: instance_type, module_type: module_type, self_type: self_type))
156
+ end
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,115 @@
1
+ module Steep
2
+ module Interface
3
+ class TypeParam
4
+ attr_reader :name
5
+ attr_reader :upper_bound
6
+ attr_reader :variance
7
+ attr_reader :unchecked
8
+ attr_reader :location
9
+ attr_reader :default_type
10
+
11
+ def initialize(name:, upper_bound:, variance:, unchecked:, location: nil, default_type:)
12
+ @name = name
13
+ @upper_bound = upper_bound
14
+ @variance = variance
15
+ @unchecked = unchecked
16
+ @location = location
17
+ @default_type = default_type
18
+ end
19
+
20
+ def ==(other)
21
+ other.is_a?(TypeParam) &&
22
+ other.name == name &&
23
+ other.upper_bound == upper_bound &&
24
+ other.variance == variance &&
25
+ other.unchecked == unchecked &&
26
+ other.default_type == default_type
27
+ end
28
+
29
+ alias eql? ==
30
+
31
+ def hash
32
+ name.hash ^ upper_bound.hash ^ variance.hash ^ unchecked.hash ^ default_type.hash
33
+ end
34
+
35
+ def self.rename(params, conflicting_names = params.map(&:name), new_names = conflicting_names.map {|n| AST::Types::Var.fresh_name(n) })
36
+ unless conflicting_names.empty?
37
+ hash = conflicting_names.zip(new_names).to_h
38
+ new_types = new_names.map {|n| AST::Types::Var.new(name: n) }
39
+
40
+ subst = Substitution.build(conflicting_names, new_types)
41
+
42
+ [
43
+ params.map do |param|
44
+ if hash.key?(param.name) || param.upper_bound
45
+ TypeParam.new(
46
+ name: hash[param.name] || param.name,
47
+ upper_bound: param.upper_bound&.subst(subst),
48
+ variance: param.variance,
49
+ unchecked: param.unchecked,
50
+ location: param.location,
51
+ default_type: param.default_type&.subst(subst)
52
+ )
53
+ else
54
+ param
55
+ end
56
+ end,
57
+ subst
58
+ ]
59
+ else
60
+ [params, Substitution.empty]
61
+ end
62
+ end
63
+
64
+ def to_s
65
+ buf = +""
66
+
67
+ if unchecked
68
+ buf << "unchecked "
69
+ end
70
+
71
+ case variance
72
+ when :covariant
73
+ buf << "out "
74
+ when :contravariant
75
+ buf << "in "
76
+ end
77
+
78
+ buf << name.to_s
79
+
80
+ if upper_bound
81
+ buf << " < #{upper_bound}"
82
+ end
83
+
84
+ buf
85
+ end
86
+
87
+ def update(name: self.name, upper_bound: self.upper_bound, variance: self.variance, unchecked: self.unchecked, location: self.location, default_type: self.default_type)
88
+ TypeParam.new(
89
+ name: name,
90
+ upper_bound: upper_bound,
91
+ variance: variance,
92
+ unchecked: unchecked,
93
+ location: location,
94
+ default_type: default_type
95
+ )
96
+ end
97
+
98
+ def subst(s)
99
+ if u = upper_bound
100
+ ub = u.subst(s)
101
+ end
102
+
103
+ if d = default_type
104
+ dt = d.subst(s)
105
+ end
106
+
107
+ if ub || dt
108
+ update(upper_bound: ub, default_type: dt)
109
+ else
110
+ self
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,20 @@
1
+ module Steep
2
+ class LocatedValue
3
+ attr_reader :value, :location
4
+
5
+ def initialize(value:, location:)
6
+ @value = value
7
+ @location = location
8
+ end
9
+
10
+ def ==(other)
11
+ other.is_a?(LocatedValue) && other.value == value
12
+ end
13
+
14
+ alias eql? ==
15
+
16
+ def hash
17
+ value.hash # steep:ignore NoMethod
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,42 @@
1
+ module Steep
2
+ InstanceMethodName = _ = Struct.new(:type_name, :method_name, keyword_init: true) do
3
+ # @implements InstanceMethodName
4
+ def to_s
5
+ "#{type_name}##{method_name}"
6
+ end
7
+
8
+ def relative
9
+ InstanceMethodName.new(type_name: type_name.relative!, method_name: method_name)
10
+ end
11
+ end
12
+
13
+ SingletonMethodName = _ = Struct.new(:type_name, :method_name, keyword_init: true) do
14
+ # @implements SingletonMethodName
15
+ def to_s
16
+ "#{type_name}.#{method_name}"
17
+ end
18
+
19
+ def relative
20
+ SingletonMethodName.new(type_name: type_name.relative!, method_name: method_name)
21
+ end
22
+ end
23
+
24
+ class ::Object
25
+ def MethodName(string)
26
+ case string
27
+ when /#/
28
+ type_name, method_name = string.split(/#/, 2)
29
+ type_name or raise
30
+ method_name or raise
31
+ InstanceMethodName.new(type_name: RBS::TypeName.parse(type_name), method_name: method_name.to_sym)
32
+ when /\./
33
+ type_name, method_name = string.split(/\./, 2)
34
+ type_name or raise
35
+ method_name or raise
36
+ SingletonMethodName.new(type_name: RBS::TypeName.parse(type_name), method_name: method_name.to_sym)
37
+ else
38
+ raise "Unexpected method name: #{string}"
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,24 @@
1
+ module Steep
2
+ module ModuleHelper
3
+ def module_name_from_node(parent_node, constant_name)
4
+ if namespace = namespace_from_node(parent_node)
5
+ RBS::TypeName.new(name: constant_name, namespace: namespace)
6
+ end
7
+ end
8
+
9
+ def namespace_from_node(node)
10
+ if node
11
+ case node.type
12
+ when :cbase
13
+ RBS::Namespace.root
14
+ when :const
15
+ if parent = namespace_from_node(node.children[0])
16
+ parent.append(node.children[1])
17
+ end
18
+ end
19
+ else
20
+ RBS::Namespace.empty
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,273 @@
1
+ module Steep
2
+ module NodeHelper
3
+ def each_child_node(node, &block)
4
+ if block
5
+ node.children.each do |child|
6
+ if child.is_a?(Parser::AST::Node)
7
+ yield child
8
+ end
9
+ end
10
+ else
11
+ enum_for :each_child_node, node
12
+ end
13
+ end
14
+
15
+ def each_descendant_node(node, &block)
16
+ if block
17
+ each_child_node(node) do |child|
18
+ yield child
19
+ each_descendant_node(child, &block)
20
+ end
21
+ else
22
+ enum_for :each_descendant_node, node
23
+ end
24
+ end
25
+
26
+ def value_node?(node)
27
+ case node.type
28
+ when :self
29
+ true
30
+ when :true, :false, :str, :sym, :int, :float, :nil
31
+ true
32
+ when :lvar
33
+ true
34
+ when :const
35
+ each_child_node(node).all? {|child| child.type == :cbase || value_node?(child) }
36
+ when :array
37
+ each_child_node(node).all? {|child| value_node?(child) }
38
+ when :hash
39
+ each_child_node(node).all? do |pair|
40
+ each_child_node(pair).all? {|child| value_node?(child) }
41
+ end
42
+ when :dstr
43
+ each_child_node(node).all? {|child| value_node?(child)}
44
+ when :begin
45
+ each_child_node(node).all? {|child| value_node?(child) }
46
+ else
47
+ false
48
+ end
49
+ end
50
+
51
+ def deconstruct_if_node(node)
52
+ if node.type == :if
53
+ [
54
+ node.children[0],
55
+ node.children[1],
56
+ node.children[2],
57
+ _ = node.location
58
+ ]
59
+ end
60
+ end
61
+
62
+ def deconstruct_if_node!(node)
63
+ deconstruct_if_node(node) or raise
64
+ end
65
+
66
+ def test_if_node(node)
67
+ if (a, b, c, d = deconstruct_if_node(node))
68
+ yield(a, b, c, d)
69
+ else
70
+ false
71
+ end
72
+ end
73
+
74
+ def deconstruct_whileish_node(node)
75
+ case node.type
76
+ when :while, :until, :while_post, :until_post
77
+ [
78
+ node.children[0],
79
+ node.children[1],
80
+ _ = node.location
81
+ ]
82
+ end
83
+ end
84
+
85
+ def deconstruct_whileish_node!(node)
86
+ deconstruct_whileish_node(node) or raise
87
+ end
88
+
89
+ def test_whileish_node(node)
90
+ if (a, b, c = deconstruct_whileish_node(node))
91
+ yield(a, b, c)
92
+ else
93
+ false
94
+ end
95
+ end
96
+
97
+ def deconstruct_case_node(node)
98
+ case node.type
99
+ when :case
100
+ cond, *whens, else_ = node.children
101
+ [
102
+ cond,
103
+ whens,
104
+ else_,
105
+ _ = node.loc
106
+ ]
107
+ end
108
+ end
109
+
110
+ def deconstruct_case_node!(node)
111
+ deconstruct_case_node(node) or raise
112
+ end
113
+
114
+ def test_case_node(node)
115
+ if (a, b, c, d = deconstruct_case_node(node))
116
+ yield a, b, c, d
117
+ else
118
+ false
119
+ end
120
+ end
121
+
122
+ def deconstruct_when_node(node)
123
+ case node.type
124
+ when :when
125
+ *conds, body = node.children
126
+ [
127
+ conds,
128
+ body,
129
+ _ = node.loc
130
+ ]
131
+ end
132
+ end
133
+
134
+ def deconstruct_when_node!(node)
135
+ deconstruct_when_node(node) or raise
136
+ end
137
+
138
+ def test_when_node(node)
139
+ if (a, b, c = deconstruct_when_node(node))
140
+ yield a, b, c
141
+ else
142
+ false
143
+ end
144
+ end
145
+
146
+ def deconstruct_rescue_node(node)
147
+ case node.type
148
+ when :rescue
149
+ body, *resbodies, else_ = node.children
150
+
151
+ [
152
+ body,
153
+ resbodies,
154
+ else_,
155
+ _ = node.loc
156
+ ]
157
+ end
158
+ end
159
+
160
+ def deconstruct_rescue_node!(node)
161
+ deconstruct_rescue_node(node) or raise
162
+ end
163
+
164
+ def test_rescue_node(node)
165
+ if (a, b, c, d = deconstruct_rescue_node(node))
166
+ yield a, b, c, d
167
+ else
168
+ false
169
+ end
170
+ end
171
+
172
+ def deconstruct_resbody_node(node)
173
+ case node.type
174
+ when :resbody
175
+ [
176
+ node.children[0],
177
+ node.children[1],
178
+ node.children[2],
179
+ _ = node.loc
180
+ ]
181
+ end
182
+ end
183
+
184
+ def deconstruct_resbody_node!(node)
185
+ deconstruct_resbody_node(node) or raise
186
+ end
187
+
188
+ def test_resbody_node(node)
189
+ if (a, b, c, d = deconstruct_resbody_node(node))
190
+ yield a, b, c, d
191
+ else
192
+ false
193
+ end
194
+ end
195
+
196
+ def deconstruct_send_node(node)
197
+ case node.type
198
+ when :send, :csend
199
+ receiver, selector, *args = node.children
200
+ [
201
+ receiver,
202
+ selector,
203
+ args,
204
+ _ = node.loc
205
+ ]
206
+ end
207
+ end
208
+
209
+ def deconstruct_send_node!(node)
210
+ deconstruct_send_node(node) or raise(node.inspect)
211
+ end
212
+
213
+ def test_send_node(node)
214
+ if (a, b, c, d = deconstruct_send_node(node))
215
+ yield a, b, c, d
216
+ else
217
+ false
218
+ end
219
+ end
220
+
221
+ def private_send?(node)
222
+ case node.type
223
+ when :block, :numblock
224
+ private_send?(node.children[0])
225
+ when :send, :csend
226
+ receiver, = deconstruct_send_node!(node)
227
+
228
+ if receiver && receiver.type != :self
229
+ return false
230
+ end
231
+
232
+ true
233
+ else
234
+ raise "Unexpected node is given: #{node.inspect}"
235
+ end
236
+ end
237
+
238
+ def deconstruct_sendish_and_block_nodes(*nodes)
239
+ send_node, block_node = nodes.take(2)
240
+
241
+ if send_node
242
+ case send_node.type
243
+ when :send, :csend, :super
244
+ if block_node
245
+ case block_node.type
246
+ when :block, :numblock
247
+ if send_node.equal?(block_node.children[0])
248
+ return [send_node, block_node]
249
+ end
250
+ end
251
+ end
252
+
253
+ [send_node, nil]
254
+ when :zsuper
255
+ # zsuper doesn't receive block
256
+ [send_node, nil]
257
+ end
258
+ end
259
+ end
260
+
261
+ def clone_node(node)
262
+ children = node.children.map do |child|
263
+ if child.is_a?(Parser::AST::Node)
264
+ clone_node(child)
265
+ else
266
+ child.dup
267
+ end
268
+ end
269
+
270
+ node.updated(nil, children)
271
+ end
272
+ end
273
+ end
@@ -0,0 +1,30 @@
1
+ module Steep
2
+ module PathHelper
3
+ module_function
4
+
5
+ URIParser = URI::RFC2396_Parser.new()
6
+
7
+ def to_pathname(uri, dosish: Gem.win_platform?)
8
+ uri = URI.parse(uri)
9
+ if uri.scheme == "file"
10
+ path = uri.path or raise
11
+ path.sub!(%r{^/([a-zA-Z])(:|%3A)//?}i, '\1:/') if dosish
12
+ path = URIParser.unescape(path)
13
+ Pathname(path)
14
+ end
15
+ end
16
+
17
+ def to_pathname!(uri, dosish: Gem.win_platform?)
18
+ to_pathname(uri, dosish: dosish) or raise "Cannot translate a URI to pathname: #{uri}"
19
+ end
20
+
21
+ def to_uri(path, dosish: Gem.win_platform?)
22
+ str_path = path.to_s
23
+ if dosish
24
+ str_path.insert(0, "/") if str_path[0] != "/"
25
+ end
26
+ str_path = URIParser.escape(str_path)
27
+ URI::File.build(path: str_path)
28
+ end
29
+ end
30
+ end