steep-activesupport-4 1.9.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (164) 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/Steepfile +68 -0
  9. data/bin/console +14 -0
  10. data/bin/generate-diagnostics-docs.rb +112 -0
  11. data/bin/mem_graph.rb +67 -0
  12. data/bin/mem_prof.rb +102 -0
  13. data/bin/output_rebaseline.rb +34 -0
  14. data/bin/output_test.rb +60 -0
  15. data/bin/rbs +20 -0
  16. data/bin/rbs-inline +19 -0
  17. data/bin/setup +9 -0
  18. data/bin/stackprof_test.rb +19 -0
  19. data/bin/steep +19 -0
  20. data/bin/steep-check.rb +251 -0
  21. data/bin/steep-prof +16 -0
  22. data/doc/narrowing.md +195 -0
  23. data/doc/shape.md +194 -0
  24. data/exe/steep +18 -0
  25. data/guides/README.md +5 -0
  26. data/guides/src/gem-rbs-collection/gem-rbs-collection.md +126 -0
  27. data/guides/src/getting-started/getting-started.md +163 -0
  28. data/guides/src/nil-optional/nil-optional.md +195 -0
  29. data/lib/steep/annotation_parser.rb +199 -0
  30. data/lib/steep/ast/annotation/collection.rb +172 -0
  31. data/lib/steep/ast/annotation.rb +137 -0
  32. data/lib/steep/ast/builtin.rb +104 -0
  33. data/lib/steep/ast/ignore.rb +148 -0
  34. data/lib/steep/ast/node/type_application.rb +88 -0
  35. data/lib/steep/ast/node/type_assertion.rb +81 -0
  36. data/lib/steep/ast/types/any.rb +35 -0
  37. data/lib/steep/ast/types/boolean.rb +45 -0
  38. data/lib/steep/ast/types/bot.rb +35 -0
  39. data/lib/steep/ast/types/class.rb +43 -0
  40. data/lib/steep/ast/types/factory.rb +557 -0
  41. data/lib/steep/ast/types/helper.rb +40 -0
  42. data/lib/steep/ast/types/instance.rb +42 -0
  43. data/lib/steep/ast/types/intersection.rb +93 -0
  44. data/lib/steep/ast/types/literal.rb +59 -0
  45. data/lib/steep/ast/types/logic.rb +84 -0
  46. data/lib/steep/ast/types/name.rb +128 -0
  47. data/lib/steep/ast/types/nil.rb +41 -0
  48. data/lib/steep/ast/types/proc.rb +117 -0
  49. data/lib/steep/ast/types/record.rb +79 -0
  50. data/lib/steep/ast/types/self.rb +43 -0
  51. data/lib/steep/ast/types/shared_instance.rb +11 -0
  52. data/lib/steep/ast/types/top.rb +35 -0
  53. data/lib/steep/ast/types/tuple.rb +60 -0
  54. data/lib/steep/ast/types/union.rb +97 -0
  55. data/lib/steep/ast/types/var.rb +65 -0
  56. data/lib/steep/ast/types/void.rb +35 -0
  57. data/lib/steep/cli.rb +401 -0
  58. data/lib/steep/diagnostic/deprecated/else_on_exhaustive_case.rb +20 -0
  59. data/lib/steep/diagnostic/deprecated/unknown_constant_assigned.rb +28 -0
  60. data/lib/steep/diagnostic/helper.rb +18 -0
  61. data/lib/steep/diagnostic/lsp_formatter.rb +78 -0
  62. data/lib/steep/diagnostic/result_printer2.rb +48 -0
  63. data/lib/steep/diagnostic/ruby.rb +1221 -0
  64. data/lib/steep/diagnostic/signature.rb +570 -0
  65. data/lib/steep/drivers/annotations.rb +52 -0
  66. data/lib/steep/drivers/check.rb +339 -0
  67. data/lib/steep/drivers/checkfile.rb +210 -0
  68. data/lib/steep/drivers/diagnostic_printer.rb +105 -0
  69. data/lib/steep/drivers/init.rb +66 -0
  70. data/lib/steep/drivers/langserver.rb +56 -0
  71. data/lib/steep/drivers/print_project.rb +113 -0
  72. data/lib/steep/drivers/stats.rb +203 -0
  73. data/lib/steep/drivers/utils/driver_helper.rb +143 -0
  74. data/lib/steep/drivers/utils/jobs_option.rb +26 -0
  75. data/lib/steep/drivers/vendor.rb +27 -0
  76. data/lib/steep/drivers/watch.rb +194 -0
  77. data/lib/steep/drivers/worker.rb +58 -0
  78. data/lib/steep/equatable.rb +23 -0
  79. data/lib/steep/expectations.rb +228 -0
  80. data/lib/steep/index/rbs_index.rb +350 -0
  81. data/lib/steep/index/signature_symbol_provider.rb +185 -0
  82. data/lib/steep/index/source_index.rb +167 -0
  83. data/lib/steep/interface/block.rb +103 -0
  84. data/lib/steep/interface/builder.rb +843 -0
  85. data/lib/steep/interface/function.rb +1090 -0
  86. data/lib/steep/interface/method_type.rb +330 -0
  87. data/lib/steep/interface/shape.rb +239 -0
  88. data/lib/steep/interface/substitution.rb +159 -0
  89. data/lib/steep/interface/type_param.rb +115 -0
  90. data/lib/steep/located_value.rb +20 -0
  91. data/lib/steep/method_name.rb +42 -0
  92. data/lib/steep/module_helper.rb +24 -0
  93. data/lib/steep/node_helper.rb +273 -0
  94. data/lib/steep/path_helper.rb +30 -0
  95. data/lib/steep/project/dsl.rb +268 -0
  96. data/lib/steep/project/group.rb +31 -0
  97. data/lib/steep/project/options.rb +63 -0
  98. data/lib/steep/project/pattern.rb +59 -0
  99. data/lib/steep/project/target.rb +92 -0
  100. data/lib/steep/project.rb +78 -0
  101. data/lib/steep/rake_task.rb +132 -0
  102. data/lib/steep/range_extension.rb +29 -0
  103. data/lib/steep/server/base_worker.rb +97 -0
  104. data/lib/steep/server/change_buffer.rb +73 -0
  105. data/lib/steep/server/custom_methods.rb +77 -0
  106. data/lib/steep/server/delay_queue.rb +45 -0
  107. data/lib/steep/server/interaction_worker.rb +492 -0
  108. data/lib/steep/server/lsp_formatter.rb +455 -0
  109. data/lib/steep/server/master.rb +912 -0
  110. data/lib/steep/server/target_group_files.rb +205 -0
  111. data/lib/steep/server/type_check_controller.rb +366 -0
  112. data/lib/steep/server/type_check_worker.rb +303 -0
  113. data/lib/steep/server/work_done_progress.rb +64 -0
  114. data/lib/steep/server/worker_process.rb +176 -0
  115. data/lib/steep/services/completion_provider.rb +802 -0
  116. data/lib/steep/services/content_change.rb +61 -0
  117. data/lib/steep/services/file_loader.rb +74 -0
  118. data/lib/steep/services/goto_service.rb +441 -0
  119. data/lib/steep/services/hover_provider/rbs.rb +88 -0
  120. data/lib/steep/services/hover_provider/ruby.rb +221 -0
  121. data/lib/steep/services/hover_provider/singleton_methods.rb +20 -0
  122. data/lib/steep/services/path_assignment.rb +46 -0
  123. data/lib/steep/services/signature_help_provider.rb +202 -0
  124. data/lib/steep/services/signature_service.rb +428 -0
  125. data/lib/steep/services/stats_calculator.rb +68 -0
  126. data/lib/steep/services/type_check_service.rb +394 -0
  127. data/lib/steep/services/type_name_completion.rb +236 -0
  128. data/lib/steep/signature/validator.rb +651 -0
  129. data/lib/steep/source/ignore_ranges.rb +69 -0
  130. data/lib/steep/source.rb +691 -0
  131. data/lib/steep/subtyping/cache.rb +30 -0
  132. data/lib/steep/subtyping/check.rb +1113 -0
  133. data/lib/steep/subtyping/constraints.rb +341 -0
  134. data/lib/steep/subtyping/relation.rb +101 -0
  135. data/lib/steep/subtyping/result.rb +324 -0
  136. data/lib/steep/subtyping/variable_variance.rb +89 -0
  137. data/lib/steep/test.rb +9 -0
  138. data/lib/steep/thread_waiter.rb +43 -0
  139. data/lib/steep/type_construction.rb +5183 -0
  140. data/lib/steep/type_inference/block_params.rb +416 -0
  141. data/lib/steep/type_inference/case_when.rb +303 -0
  142. data/lib/steep/type_inference/constant_env.rb +56 -0
  143. data/lib/steep/type_inference/context.rb +195 -0
  144. data/lib/steep/type_inference/logic_type_interpreter.rb +613 -0
  145. data/lib/steep/type_inference/method_call.rb +193 -0
  146. data/lib/steep/type_inference/method_params.rb +531 -0
  147. data/lib/steep/type_inference/multiple_assignment.rb +194 -0
  148. data/lib/steep/type_inference/send_args.rb +712 -0
  149. data/lib/steep/type_inference/type_env.rb +341 -0
  150. data/lib/steep/type_inference/type_env_builder.rb +138 -0
  151. data/lib/steep/typing.rb +321 -0
  152. data/lib/steep/version.rb +3 -0
  153. data/lib/steep.rb +369 -0
  154. data/manual/annotations.md +181 -0
  155. data/manual/ignore.md +20 -0
  156. data/manual/ruby-diagnostics.md +1879 -0
  157. data/sample/Steepfile +22 -0
  158. data/sample/lib/conference.rb +49 -0
  159. data/sample/lib/length.rb +35 -0
  160. data/sample/sig/conference.rbs +42 -0
  161. data/sample/sig/generics.rbs +15 -0
  162. data/sample/sig/length.rbs +34 -0
  163. data/steep-activesupport-4.gemspec +55 -0
  164. metadata +437 -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