steep 0.30.0 → 0.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -101,20 +101,6 @@ module Steep
101
101
  end
102
102
  end
103
103
 
104
- class IncompatibleBlockParameters < Base
105
- attr_reader :node
106
- attr_reader :method_type
107
-
108
- def initialize(node:, method_type:)
109
- super(node: node)
110
- @method_type = method_type
111
- end
112
-
113
- def to_s
114
- "#{location_to_str}: IncompatibleBlockParameters: method_type=#{method_type}"
115
- end
116
- end
117
-
118
104
  class BlockParameterTypeMismatch < Base
119
105
  attr_reader :expected
120
106
  attr_reader :actual
@@ -186,7 +172,7 @@ module Steep
186
172
  end
187
173
 
188
174
  def to_s
189
- "#{location_to_str}: RequiredBlockMissing: method_type=#{method_type.location&.source}"
175
+ "#{location_to_str}: RequiredBlockMissing: method_type=#{method_type.to_s}"
190
176
  end
191
177
  end
192
178
 
@@ -557,5 +543,23 @@ module Steep
557
543
  "#{location_to_str}: UnsupportedSyntax: #{msg}"
558
544
  end
559
545
  end
546
+
547
+ class UnexpectedError < Base
548
+ attr_reader :message
549
+ attr_reader :error
550
+
551
+ def initialize(node:, error:)
552
+ super(node: node)
553
+ @error = error
554
+ @message = error.message
555
+ end
556
+
557
+ def to_s
558
+ <<-MESSAGE
559
+ #{location_to_str}: UnexpectedError: #{error.class}
560
+ >> #{message}
561
+ MESSAGE
562
+ end
563
+ end
560
564
  end
561
565
  end
@@ -774,16 +774,14 @@ module Steep
774
774
  attr_reader :params
775
775
  attr_reader :block
776
776
  attr_reader :return_type
777
- attr_reader :location
778
- attr_reader :method_def
777
+ attr_reader :method_decls
779
778
 
780
- def initialize(type_params:, params:, block:, return_type:, location:, method_def:)
779
+ def initialize(type_params:, params:, block:, return_type:, method_decls:)
781
780
  @type_params = type_params
782
781
  @params = params
783
782
  @block = block
784
783
  @return_type = return_type
785
- @location = location
786
- @method_def = method_def
784
+ @method_decls = method_decls
787
785
  end
788
786
 
789
787
  def ==(other)
@@ -791,9 +789,7 @@ module Steep
791
789
  other.type_params == type_params &&
792
790
  other.params == params &&
793
791
  other.block == block &&
794
- other.return_type == return_type &&
795
- (!other.method_def || !method_def || other.method_def == method_def) &&
796
- (!other.location || !location || other.location == location)
792
+ other.return_type == return_type
797
793
  end
798
794
 
799
795
  alias eql? ==
@@ -824,8 +820,7 @@ module Steep
824
820
  params: params.subst(s_),
825
821
  block: block&.subst(s_),
826
822
  return_type: return_type.subst(s_),
827
- method_def: method_def,
828
- location: location
823
+ method_decls: method_decls
829
824
  )
830
825
  end
831
826
 
@@ -847,17 +842,15 @@ module Steep
847
842
  params: params.subst(s),
848
843
  block: block&.subst(s),
849
844
  return_type: return_type.subst(s),
850
- location: location,
851
- method_def: method_def)
845
+ method_decls: method_decls)
852
846
  end
853
847
 
854
- def with(type_params: self.type_params, params: self.params, block: self.block, return_type: self.return_type, location: self.location, method_def: self.method_def)
848
+ def with(type_params: self.type_params, params: self.params, block: self.block, return_type: self.return_type, method_decls: self.method_decls)
855
849
  self.class.new(type_params: type_params,
856
850
  params: params,
857
851
  block: block,
858
852
  return_type: return_type,
859
- method_def: method_def,
860
- location: location)
853
+ method_decls: method_decls)
861
854
  end
862
855
 
863
856
  def to_s
@@ -873,8 +866,7 @@ module Steep
873
866
  params: params.map_type(&block),
874
867
  block: self.block&.yield_self {|blk| blk.map_type(&block) },
875
868
  return_type: yield(return_type),
876
- location: location,
877
- method_def: method_def)
869
+ method_decls: method_decls)
878
870
  end
879
871
 
880
872
  # Returns a new method type which can be used for the method implementation type of both `self` and `other`.
@@ -902,8 +894,7 @@ module Steep
902
894
  return_type: AST::Types::Union.build(
903
895
  types: [return_type.subst(s1),other.return_type.subst(s2)]
904
896
  ),
905
- method_def: method_def,
906
- location: nil
897
+ method_decls: method_decls + other.method_decls
907
898
  )
908
899
  end
909
900
 
@@ -958,8 +949,7 @@ module Steep
958
949
  block: block,
959
950
  return_type: return_type,
960
951
  type_params: type_params,
961
- method_def: nil,
962
- location: nil
952
+ method_decls: method_decls + other.method_decls
963
953
  )
964
954
  end
965
955
 
@@ -1006,8 +996,7 @@ module Steep
1006
996
  block: block,
1007
997
  return_type: return_type,
1008
998
  type_params: type_params,
1009
- method_def: nil,
1010
- location: nil
999
+ method_decls: method_decls + other.method_decls
1011
1000
  )
1012
1001
  end
1013
1002
  end
@@ -0,0 +1,28 @@
1
+ module Steep
2
+ InstanceMethodName = Struct.new(:type_name, :method_name, keyword_init: true) do
3
+ def to_s
4
+ "#{type_name}##{method_name}"
5
+ end
6
+ end
7
+
8
+ SingletonMethodName = Struct.new(:type_name, :method_name, keyword_init: true) do
9
+ def to_s
10
+ "#{type_name}.#{method_name}"
11
+ end
12
+ end
13
+
14
+ module ::Kernel
15
+ def MethodName(string)
16
+ case string
17
+ when /#/
18
+ type_name, method_name = string.split(/#/, 2)
19
+ InstanceMethodName.new(type_name: TypeName(type_name), method_name: method_name.to_sym)
20
+ when /\./
21
+ type_name, method_name = string.split(/\./, 2)
22
+ SingletonMethodName.new(type_name: TypeName(type_name), method_name: method_name.to_sym)
23
+ else
24
+ raise "Unexpected method name: #{string}"
25
+ end
26
+ end
27
+ end
28
+ end
@@ -10,9 +10,27 @@ module Steep
10
10
 
11
11
  InstanceVariableItem = Struct.new(:identifier, :range, :type, keyword_init: true)
12
12
  LocalVariableItem = Struct.new(:identifier, :range, :type, keyword_init: true)
13
- MethodNameItem = Struct.new(:identifier, :range, :method_def, :method_type, :inherited_method, keyword_init: true) do
13
+ MethodNameItem = Struct.new(:identifier, :range, :receiver_type, :method_type, :method_decls, keyword_init: true) do
14
14
  def comment
15
- method_def&.comment
15
+ case method_decls.size
16
+ when 0
17
+ nil
18
+ when 1
19
+ method_decls.to_a.first.method_def&.comment
20
+ else
21
+ nil
22
+ end
23
+ end
24
+
25
+ def inherited?
26
+ case receiver_type
27
+ when AST::Types::Name::Instance, AST::Types::Name::Singleton, AST::Types::Name::Interface
28
+ method_decls.any? do |decl|
29
+ decl.method_name.type_name != receiver_type.name
30
+ end
31
+ else
32
+ false
33
+ end
16
34
  end
17
35
  end
18
36
 
@@ -29,11 +47,13 @@ module Steep
29
47
  @subtyping = subtyping
30
48
  end
31
49
 
32
- def type_check!(text)
50
+ def type_check!(text, line:, column:)
33
51
  @modified_text = text
34
52
 
35
53
  Steep.measure "parsing" do
36
- @source = SourceFile.parse(text, path: path, factory: subtyping.factory)
54
+ @source = SourceFile
55
+ .parse(text, path: path, factory: subtyping.factory)
56
+ .without_unrelated_defs(line: line, column: column)
37
57
  end
38
58
 
39
59
  Steep.measure "typechecking" do
@@ -53,7 +73,7 @@ module Steep
53
73
  begin
54
74
  Steep.logger.tagged "completion_provider#run(line: #{line}, column: #{column})" do
55
75
  Steep.measure "type_check!" do
56
- type_check!(source_text)
76
+ type_check!(source_text, line: line, column: column)
57
77
  end
58
78
  end
59
79
 
@@ -66,11 +86,11 @@ module Steep
66
86
  case possible_trigger
67
87
  when "."
68
88
  source_text[index-1] = " "
69
- type_check!(source_text)
89
+ type_check!(source_text, line: line, column: column)
70
90
  items_for_dot(position: position)
71
91
  when "@"
72
92
  source_text[index-1] = " "
73
- type_check!(source_text)
93
+ type_check!(source_text, line: line, column: column)
74
94
  items_for_atmark(position: position)
75
95
  else
76
96
  []
@@ -219,14 +239,14 @@ module Steep
219
239
  def items_for_atmark(position:)
220
240
  # @ ←
221
241
  shift_pos = position-1
222
- node, *parents = source.find_nodes(line: shift_pos.line, column: shift_pos.column)
242
+ node, *_ = source.find_nodes(line: shift_pos.line, column: shift_pos.column)
223
243
  node ||= source.node
224
244
 
225
245
  return [] unless node
226
246
 
227
247
  context = typing.context_at(line: position.line, column: position.column)
228
248
  items = []
229
- instance_variable_items_for_context(context, prefix: "", position: position, items: items)
249
+ instance_variable_items_for_context(context, prefix: "@", position: position, items: items)
230
250
  items
231
251
  end
232
252
 
@@ -243,15 +263,15 @@ module Steep
243
263
  items << MethodNameItem.new(
244
264
  identifier: name,
245
265
  range: range,
246
- method_def: method_type.method_def,
247
- method_type: method_type.method_def&.type || subtyping.factory.method_type_1(method_type, self_type: type),
248
- inherited_method: inherited_method?(method_type.method_def, type)
266
+ receiver_type: type,
267
+ method_type: subtyping.factory.method_type_1(method_type, self_type: type),
268
+ method_decls: method_type.method_decls
249
269
  )
250
270
  end
251
271
  end
252
272
  end
253
273
  end
254
- rescue
274
+ rescue RuntimeError => exn
255
275
  # nop
256
276
  end
257
277
 
@@ -296,15 +316,6 @@ module Steep
296
316
  index
297
317
  end
298
318
 
299
- def inherited_method?(method_def, type)
300
- case type
301
- when AST::Types::Name::Instance, AST::Types::Name::Singleton, AST::Types::Name::Interface
302
- method_def.implemented_in != type.name
303
- else
304
- false
305
- end
306
- end
307
-
308
319
  def disallowed_method?(name)
309
320
  # initialize isn't invoked by developers when creating
310
321
  # instances of new classes, so don't show it as
@@ -36,102 +36,113 @@ module Steep
36
36
  end
37
37
  end
38
38
 
39
+ def typecheck(target, path:, line:, column:)
40
+ target.type_check(target_sources: [], validate_signatures: false)
41
+
42
+ case (status = target.status)
43
+ when Project::Target::TypeCheckStatus
44
+ subtyping = status.subtyping
45
+ source = SourceFile
46
+ .parse(target.source_files[path].content, path: path, factory: subtyping.factory)
47
+ .without_unrelated_defs(line: line, column: column)
48
+ SourceFile.type_check(source, subtyping: subtyping)
49
+ end
50
+ rescue
51
+ nil
52
+ end
53
+
39
54
  def content_for(path:, line:, column:)
40
- target = project.targets.find {|target| target.source_file?(path) }
55
+ target = project.target_for_source_path(path)
41
56
 
42
57
  if target
43
- source_file = target.source_files[path]
44
- target.type_check(target_sources: [source_file], validate_signatures: false)
58
+ typing = typecheck(target, path: path, line: line, column: column) or return
59
+
60
+ node, *parents = typing.source.find_nodes(line: line, column: column)
61
+
62
+ if node
63
+ case node.type
64
+ when :lvar
65
+ var_name = node.children[0]
66
+ context = typing.context_at(line: line, column: column)
67
+ var_type = context.lvar_env[var_name.name] || AST::Types::Any.new(location: nil)
45
68
 
46
- case (status = source_file.status)
47
- when SourceFile::TypeCheckStatus
48
- node, *parents = status.source.find_nodes(line: line, column: column)
69
+ VariableContent.new(node: node, name: var_name.name, type: var_type, location: node.location.name)
70
+ when :lvasgn
71
+ var_name, rhs = node.children
72
+ context = typing.context_at(line: line, column: column)
73
+ type = context.lvar_env[var_name.name] || typing.type_of(node: rhs)
49
74
 
50
- if node
51
- case node.type
52
- when :lvar
53
- var_name = node.children[0]
54
- context = status.typing.context_at(line: line, column: column)
55
- var_type = context.lvar_env[var_name.name] || AST::Types::Any.new(location: nil)
75
+ VariableContent.new(node: node, name: var_name.name, type: type, location: node.location.name)
76
+ when :send
77
+ receiver, method_name, *_ = node.children
56
78
 
57
- VariableContent.new(node: node, name: var_name.name, type: var_type, location: node.location.name)
58
- when :lvasgn
59
- var_name, rhs = node.children
60
- context = status.typing.context_at(line: line, column: column)
61
- type = context.lvar_env[var_name.name] || status.typing.type_of(node: rhs)
62
79
 
63
- VariableContent.new(node: node, name: var_name.name, type: type, location: node.location.name)
64
- when :send
65
- receiver, method_name, *_ = node.children
80
+ result_node = if parents[0]&.type == :block
81
+ parents[0]
82
+ else
83
+ node
84
+ end
66
85
 
86
+ context = typing.context_at(line: line, column: column)
67
87
 
68
- result_node = if parents[0]&.type == :block
69
- parents[0]
88
+ receiver_type = if receiver
89
+ typing.type_of(node: receiver)
70
90
  else
71
- node
91
+ context.self_type
72
92
  end
73
93
 
74
- context = status.typing.context_at(line: line, column: column)
75
-
76
- receiver_type = if receiver
77
- status.typing.type_of(node: receiver)
78
- else
79
- context.self_type
80
- end
81
-
82
- factory = context.type_env.subtyping.factory
83
- method_name, definition = case receiver_type
84
- when AST::Types::Name::Instance
85
- method_definition = method_definition_for(factory, receiver_type.name, instance_method: method_name)
86
- if method_definition&.defined_in
87
- owner_name = method_definition.defined_in
88
- [
89
- InstanceMethodName.new(owner_name, method_name),
90
- method_definition
91
- ]
92
- end
93
- when AST::Types::Name::Singleton
94
- method_definition = method_definition_for(factory, receiver_type.name, singleton_method: method_name)
95
- if method_definition&.defined_in
96
- owner_name = method_definition.defined_in
97
- [
98
- SingletonMethodName.new(owner_name, method_name),
99
- method_definition
100
- ]
101
- end
102
- else
103
- nil
94
+ factory = context.type_env.subtyping.factory
95
+ method_name, definition = case receiver_type
96
+ when AST::Types::Name::Instance
97
+ method_definition = method_definition_for(factory, receiver_type.name, instance_method: method_name)
98
+ if method_definition&.defined_in
99
+ owner_name = method_definition.defined_in
100
+ [
101
+ InstanceMethodName.new(owner_name, method_name),
102
+ method_definition
103
+ ]
104
104
  end
105
-
106
- MethodCallContent.new(
107
- node: node,
108
- method_name: method_name,
109
- type: status.typing.type_of(node: result_node),
110
- definition: definition,
111
- location: result_node.location.expression
112
- )
113
- when :def, :defs
114
- context = status.typing.context_at(line: line, column: column)
115
- method_context = context.method_context
116
-
117
- if method_context && method_context.method
118
- DefinitionContent.new(
119
- node: node,
120
- method_name: method_context.name,
121
- method_type: method_context.method_type,
122
- definition: method_context.method,
123
- location: node.loc.expression
124
- )
125
- end
126
- else
127
- type = status.typing.type_of(node: node)
128
-
129
- TypeContent.new(
105
+ when AST::Types::Name::Singleton
106
+ method_definition = method_definition_for(factory, receiver_type.name, singleton_method: method_name)
107
+ if method_definition&.defined_in
108
+ owner_name = method_definition.defined_in
109
+ [
110
+ SingletonMethodName.new(owner_name, method_name),
111
+ method_definition
112
+ ]
113
+ end
114
+ else
115
+ nil
116
+ end
117
+
118
+ MethodCallContent.new(
119
+ node: node,
120
+ method_name: method_name,
121
+ type: typing.type_of(node: result_node),
122
+ definition: definition,
123
+ location: result_node.location.expression
124
+ )
125
+ when :def, :defs
126
+ context = typing.context_at(line: line, column: column)
127
+ method_context = context.method_context
128
+
129
+ if method_context && method_context.method
130
+ DefinitionContent.new(
130
131
  node: node,
131
- type: type,
132
- location: node.location.expression
132
+ method_name: method_context.name,
133
+ method_type: method_context.method_type,
134
+ definition: method_context.method,
135
+ location: node.loc.expression
133
136
  )
134
137
  end
138
+ else
139
+ type = typing.type_of(node: node)
140
+
141
+ TypeContent.new(
142
+ node: node,
143
+ type: type,
144
+ location: node.location.expression
145
+ )
135
146
  end
136
147
  end
137
148
  end