steep 0.30.0 → 0.34.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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