steep 0.24.0 → 0.30.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +48 -0
- data/bin/smoke_runner.rb +3 -4
- data/lib/steep.rb +6 -4
- data/lib/steep/annotation_parser.rb +2 -4
- data/lib/steep/ast/builtin.rb +11 -21
- data/lib/steep/ast/types.rb +5 -3
- data/lib/steep/ast/types/any.rb +1 -3
- data/lib/steep/ast/types/boolean.rb +1 -3
- data/lib/steep/ast/types/bot.rb +1 -3
- data/lib/steep/ast/types/class.rb +2 -2
- data/lib/steep/ast/types/factory.rb +251 -89
- data/lib/steep/ast/types/helper.rb +6 -0
- data/lib/steep/ast/types/instance.rb +2 -2
- data/lib/steep/ast/types/intersection.rb +20 -13
- data/lib/steep/ast/types/literal.rb +1 -3
- data/lib/steep/ast/types/logic.rb +63 -0
- data/lib/steep/ast/types/name.rb +15 -67
- data/lib/steep/ast/types/nil.rb +1 -3
- data/lib/steep/ast/types/proc.rb +5 -2
- data/lib/steep/ast/types/record.rb +9 -4
- data/lib/steep/ast/types/self.rb +1 -1
- data/lib/steep/ast/types/top.rb +1 -3
- data/lib/steep/ast/types/tuple.rb +5 -3
- data/lib/steep/ast/types/union.rb +16 -9
- data/lib/steep/ast/types/var.rb +2 -2
- data/lib/steep/ast/types/void.rb +1 -3
- data/lib/steep/drivers/check.rb +4 -0
- data/lib/steep/errors.rb +14 -0
- data/lib/steep/interface/interface.rb +5 -62
- data/lib/steep/interface/method_type.rb +394 -93
- data/lib/steep/interface/substitution.rb +48 -6
- data/lib/steep/module_helper.rb +25 -0
- data/lib/steep/project.rb +25 -0
- data/lib/steep/project/completion_provider.rb +48 -51
- data/lib/steep/project/file_loader.rb +7 -2
- data/lib/steep/project/hover_content.rb +4 -6
- data/lib/steep/project/signature_file.rb +33 -0
- data/lib/steep/project/{file.rb → source_file.rb} +24 -54
- data/lib/steep/project/target.rb +36 -14
- data/lib/steep/server/base_worker.rb +5 -3
- data/lib/steep/server/code_worker.rb +31 -45
- data/lib/steep/server/master.rb +23 -31
- data/lib/steep/server/utils.rb +46 -13
- data/lib/steep/server/worker_process.rb +4 -2
- data/lib/steep/signature/validator.rb +3 -3
- data/lib/steep/source.rb +4 -3
- data/lib/steep/subtyping/check.rb +46 -59
- data/lib/steep/subtyping/constraints.rb +8 -0
- data/lib/steep/type_construction.rb +771 -513
- data/lib/steep/type_inference/block_params.rb +5 -0
- data/lib/steep/type_inference/constant_env.rb +3 -6
- data/lib/steep/type_inference/context.rb +8 -0
- data/lib/steep/type_inference/context_array.rb +4 -3
- data/lib/steep/type_inference/logic.rb +31 -0
- data/lib/steep/type_inference/logic_type_interpreter.rb +219 -0
- data/lib/steep/type_inference/type_env.rb +2 -2
- data/lib/steep/typing.rb +7 -0
- data/lib/steep/version.rb +1 -1
- data/smoke/alias/a.rb +1 -1
- data/smoke/case/a.rb +1 -1
- data/smoke/hash/d.rb +1 -1
- data/smoke/if/a.rb +1 -1
- data/smoke/module/a.rb +1 -1
- data/smoke/rescue/a.rb +4 -13
- data/smoke/toplevel/Steepfile +5 -0
- data/smoke/toplevel/a.rb +4 -0
- data/smoke/toplevel/a.rbs +3 -0
- data/smoke/type_case/a.rb +0 -7
- data/steep.gemspec +2 -2
- metadata +15 -11
- data/lib/steep/ast/method_type.rb +0 -126
- data/lib/steep/ast/namespace.rb +0 -80
- data/lib/steep/names.rb +0 -86
@@ -26,7 +26,32 @@ module Steep
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def self.empty
|
29
|
-
new(dictionary: {},
|
29
|
+
new(dictionary: {},
|
30
|
+
instance_type: INSTANCE_TYPE,
|
31
|
+
module_type: CLASS_TYPE,
|
32
|
+
self_type: SELF_TYPE)
|
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
|
+
INSTANCE_TYPE = AST::Types::Instance.new
|
43
|
+
CLASS_TYPE = AST::Types::Class.new
|
44
|
+
SELF_TYPE = AST::Types::Self.new
|
45
|
+
|
46
|
+
def domain
|
47
|
+
set = Set.new
|
48
|
+
|
49
|
+
set.merge(dictionary.keys)
|
50
|
+
set << INSTANCE_TYPE unless instance_type.is_a?(AST::Types::Instance)
|
51
|
+
set << CLASS_TYPE unless instance_type.is_a?(AST::Types::Class)
|
52
|
+
set << SELF_TYPE unless instance_type.is_a?(AST::Types::Self)
|
53
|
+
|
54
|
+
set
|
30
55
|
end
|
31
56
|
|
32
57
|
def to_s
|
@@ -65,22 +90,39 @@ module Steep
|
|
65
90
|
|
66
91
|
def except(vars)
|
67
92
|
self.class.new(
|
68
|
-
dictionary: dictionary
|
93
|
+
dictionary: dictionary,
|
69
94
|
instance_type: instance_type,
|
70
95
|
module_type: module_type,
|
71
96
|
self_type: self_type
|
72
|
-
)
|
97
|
+
).except!(vars)
|
73
98
|
end
|
74
99
|
|
75
|
-
def
|
100
|
+
def except!(vars)
|
101
|
+
vars.each do |var|
|
102
|
+
dictionary.delete(var)
|
103
|
+
end
|
104
|
+
|
105
|
+
self
|
106
|
+
end
|
107
|
+
|
108
|
+
def merge!(s, overwrite: false)
|
76
109
|
dictionary.transform_values! {|ty| ty.subst(s) }
|
77
110
|
dictionary.merge!(s.dictionary) do |key, a, b|
|
78
111
|
if a == b
|
79
112
|
a
|
80
113
|
else
|
81
|
-
|
114
|
+
if overwrite
|
115
|
+
b
|
116
|
+
else
|
117
|
+
raise "Duplicated key on merge!: #{key}, #{a}, #{b} (#{self})"
|
118
|
+
end
|
82
119
|
end
|
83
120
|
end
|
121
|
+
|
122
|
+
@instance_type = instance_type.subst(s)
|
123
|
+
@module_type = module_type.subst(s)
|
124
|
+
@self_type = self_type.subst(s)
|
125
|
+
|
84
126
|
self
|
85
127
|
end
|
86
128
|
|
@@ -92,7 +134,7 @@ module Steep
|
|
92
134
|
end
|
93
135
|
|
94
136
|
def add!(v, ty)
|
95
|
-
merge!(Substitution.new(dictionary: { v => ty }, instance_type:
|
137
|
+
merge!(Substitution.new(dictionary: { v => ty }, instance_type: instance_type, module_type: module_type, self_type: self_type))
|
96
138
|
end
|
97
139
|
end
|
98
140
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Steep
|
2
|
+
module ModuleHelper
|
3
|
+
def module_name_from_node(node)
|
4
|
+
case node.type
|
5
|
+
when :const, :casgn
|
6
|
+
namespace = namespace_from_node(node.children[0]) or return
|
7
|
+
name = node.children[1]
|
8
|
+
RBS::TypeName.new(name: name, namespace: namespace)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def namespace_from_node(node)
|
13
|
+
case node&.type
|
14
|
+
when nil
|
15
|
+
RBS::Namespace.empty
|
16
|
+
when :cbase
|
17
|
+
RBS::Namespace.root
|
18
|
+
when :const
|
19
|
+
namespace_from_node(node.children[0])&.yield_self do |parent|
|
20
|
+
parent.append(node.children[1])
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/steep/project.rb
CHANGED
@@ -24,6 +24,31 @@ module Steep
|
|
24
24
|
(base_dir + path).cleanpath
|
25
25
|
end
|
26
26
|
|
27
|
+
def target_for_source_path(path)
|
28
|
+
targets.find do |target|
|
29
|
+
target.possible_source_file?(path)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def targets_for_path(path)
|
34
|
+
if target = target_for_source_path(path)
|
35
|
+
[target, []]
|
36
|
+
else
|
37
|
+
[
|
38
|
+
nil,
|
39
|
+
targets.select do |target|
|
40
|
+
target.possible_signature_file?(path)
|
41
|
+
end
|
42
|
+
]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def all_source_files
|
47
|
+
targets.each.with_object(Set[]) do |target, paths|
|
48
|
+
paths.merge(target.source_files.keys)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
27
52
|
def type_of_node(path:, line:, column:)
|
28
53
|
source_file = targets.map {|target| target.source_files[path] }.compact[0]
|
29
54
|
|
@@ -10,13 +10,9 @@ 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, :
|
14
|
-
def method_type
|
15
|
-
def_type.type
|
16
|
-
end
|
17
|
-
|
13
|
+
MethodNameItem = Struct.new(:identifier, :range, :method_def, :method_type, :inherited_method, keyword_init: true) do
|
18
14
|
def comment
|
19
|
-
|
15
|
+
method_def&.comment
|
20
16
|
end
|
21
17
|
end
|
22
18
|
|
@@ -90,7 +86,9 @@ module Steep
|
|
90
86
|
end
|
91
87
|
|
92
88
|
def at_end?(pos, of:)
|
93
|
-
|
89
|
+
if of
|
90
|
+
of.last_line == pos.line && of.last_column == pos.column
|
91
|
+
end
|
94
92
|
end
|
95
93
|
|
96
94
|
def range_for(position, prefix: "")
|
@@ -194,21 +192,25 @@ module Steep
|
|
194
192
|
return [] unless node
|
195
193
|
|
196
194
|
if at_end?(shift_pos, of: node.loc)
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
195
|
+
begin
|
196
|
+
context = typing.context_at(line: position.line, column: position.column)
|
197
|
+
receiver_type = case (type = typing.type_of(node: node))
|
198
|
+
when AST::Types::Self
|
199
|
+
context.self_type
|
200
|
+
else
|
201
|
+
type
|
202
|
+
end
|
203
|
+
|
204
|
+
items = []
|
205
|
+
method_items_for_receiver_type(receiver_type,
|
206
|
+
include_private: false,
|
207
|
+
prefix: "",
|
208
|
+
position: position,
|
209
|
+
items: items)
|
210
|
+
items
|
211
|
+
rescue Typing::UnknownNodeError
|
212
|
+
[]
|
213
|
+
end
|
212
214
|
else
|
213
215
|
[]
|
214
216
|
end
|
@@ -230,37 +232,27 @@ module Steep
|
|
230
232
|
|
231
233
|
def method_items_for_receiver_type(type, include_private:, prefix:, position:, items:)
|
232
234
|
range = range_for(position, prefix: prefix)
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
if include_private || method.public?
|
250
|
-
if name.to_s.start_with?(prefix)
|
251
|
-
if word_name?(name.to_s)
|
252
|
-
method.defs.each do |def_type|
|
253
|
-
items << MethodNameItem.new(identifier: name,
|
254
|
-
range: range,
|
255
|
-
definition: method,
|
256
|
-
def_type: def_type,
|
257
|
-
inherited_method: inherited_method?(method, definition))
|
258
|
-
end
|
259
|
-
end
|
235
|
+
interface = subtyping.factory.interface(type, self_type: type, private: include_private)
|
236
|
+
|
237
|
+
interface.methods.each do |name, method_entry|
|
238
|
+
next if disallowed_method?(name)
|
239
|
+
|
240
|
+
if name.to_s.start_with?(prefix)
|
241
|
+
if word_name?(name.to_s)
|
242
|
+
method_entry.method_types.each do |method_type|
|
243
|
+
items << MethodNameItem.new(
|
244
|
+
identifier: name,
|
245
|
+
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)
|
249
|
+
)
|
260
250
|
end
|
261
251
|
end
|
262
252
|
end
|
263
253
|
end
|
254
|
+
rescue
|
255
|
+
# nop
|
264
256
|
end
|
265
257
|
|
266
258
|
def word_name?(name)
|
@@ -304,8 +296,13 @@ module Steep
|
|
304
296
|
index
|
305
297
|
end
|
306
298
|
|
307
|
-
def inherited_method?(
|
308
|
-
|
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
|
309
306
|
end
|
310
307
|
|
311
308
|
def disallowed_method?(name)
|
@@ -28,15 +28,20 @@ module Steep
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def load_sources(command_line_patterns)
|
31
|
+
loaded_paths = Set[]
|
32
|
+
|
31
33
|
project.targets.each do |target|
|
32
34
|
Steep.logger.tagged "target=#{target.name}" do
|
33
35
|
target_patterns = command_line_patterns.empty? ? target.source_patterns : command_line_patterns
|
34
36
|
|
35
|
-
each_path_in_patterns
|
37
|
+
each_path_in_patterns(target_patterns, ".rb") do |path|
|
36
38
|
if target.possible_source_file?(path)
|
37
|
-
|
39
|
+
if loaded_paths.include?(path)
|
40
|
+
Steep.logger.warn { "Skipping #{target} while loading #{path}... (Already loaded to another target.)" }
|
41
|
+
else
|
38
42
|
Steep.logger.info { "Adding source file: #{path}" }
|
39
43
|
target.add_source path, project.absolute_path(path).read
|
44
|
+
loaded_paths << path
|
40
45
|
end
|
41
46
|
end
|
42
47
|
end
|
@@ -21,9 +21,7 @@ module Steep
|
|
21
21
|
@project = project
|
22
22
|
end
|
23
23
|
|
24
|
-
def method_definition_for(factory,
|
25
|
-
type_name = factory.type_name_1(module_name)
|
26
|
-
|
24
|
+
def method_definition_for(factory, type_name, singleton_method: nil, instance_method: nil)
|
27
25
|
case
|
28
26
|
when instance_method
|
29
27
|
factory.definition_builder.build_instance(type_name).methods[instance_method]
|
@@ -86,16 +84,16 @@ module Steep
|
|
86
84
|
when AST::Types::Name::Instance
|
87
85
|
method_definition = method_definition_for(factory, receiver_type.name, instance_method: method_name)
|
88
86
|
if method_definition&.defined_in
|
89
|
-
owner_name =
|
87
|
+
owner_name = method_definition.defined_in
|
90
88
|
[
|
91
89
|
InstanceMethodName.new(owner_name, method_name),
|
92
90
|
method_definition
|
93
91
|
]
|
94
92
|
end
|
95
|
-
when AST::Types::Name::
|
93
|
+
when AST::Types::Name::Singleton
|
96
94
|
method_definition = method_definition_for(factory, receiver_type.name, singleton_method: method_name)
|
97
95
|
if method_definition&.defined_in
|
98
|
-
owner_name =
|
96
|
+
owner_name = method_definition.defined_in
|
99
97
|
[
|
100
98
|
SingletonMethodName.new(owner_name, method_name),
|
101
99
|
method_definition
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Steep
|
2
|
+
class Project
|
3
|
+
class SignatureFile
|
4
|
+
attr_reader :path
|
5
|
+
attr_reader :content
|
6
|
+
attr_reader :content_updated_at
|
7
|
+
|
8
|
+
attr_reader :status
|
9
|
+
|
10
|
+
ParseErrorStatus = Struct.new(:error, :timestamp, keyword_init: true)
|
11
|
+
DeclarationsStatus = Struct.new(:declarations, :timestamp, keyword_init: true)
|
12
|
+
|
13
|
+
def initialize(path:)
|
14
|
+
@path = path
|
15
|
+
self.content = ""
|
16
|
+
end
|
17
|
+
|
18
|
+
def content=(content)
|
19
|
+
@content_updated_at = Time.now
|
20
|
+
@content = content
|
21
|
+
@status = nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def load!
|
25
|
+
buffer = RBS::Buffer.new(name: path, content: content)
|
26
|
+
decls = RBS::Parser.parse_signature(buffer)
|
27
|
+
@status = DeclarationsStatus.new(declarations: decls, timestamp: Time.now)
|
28
|
+
rescue RBS::Parser::SyntaxError, RBS::Parser::SemanticsError => exn
|
29
|
+
@status = ParseErrorStatus.new(error: exn, timestamp: Time.now)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -8,10 +8,10 @@ module Steep
|
|
8
8
|
|
9
9
|
attr_accessor :status
|
10
10
|
|
11
|
-
ParseErrorStatus = Struct.new(:error, keyword_init: true)
|
12
|
-
AnnotationSyntaxErrorStatus = Struct.new(:error, :location, keyword_init: true)
|
11
|
+
ParseErrorStatus = Struct.new(:error, :timestamp, keyword_init: true)
|
12
|
+
AnnotationSyntaxErrorStatus = Struct.new(:error, :location, :timestamp, keyword_init: true)
|
13
13
|
TypeCheckStatus = Struct.new(:typing, :source, :timestamp, keyword_init: true)
|
14
|
-
TypeCheckErrorStatus = Struct.new(:error, keyword_init: true)
|
14
|
+
TypeCheckErrorStatus = Struct.new(:error, :timestamp, keyword_init: true)
|
15
15
|
|
16
16
|
def initialize(path:)
|
17
17
|
@path = path
|
@@ -20,11 +20,9 @@ module Steep
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def content=(content)
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
@status = nil
|
27
|
-
end
|
23
|
+
@content_updated_at = Time.now
|
24
|
+
@content = content
|
25
|
+
@status = nil
|
28
26
|
end
|
29
27
|
|
30
28
|
def errors
|
@@ -41,8 +39,8 @@ module Steep
|
|
41
39
|
end
|
42
40
|
|
43
41
|
def self.type_check(source, subtyping:)
|
44
|
-
annotations = source.annotations(block: source.node, factory: subtyping.factory, current_module:
|
45
|
-
const_env = TypeInference::ConstantEnv.new(factory: subtyping.factory, context: [
|
42
|
+
annotations = source.annotations(block: source.node, factory: subtyping.factory, current_module: RBS::Namespace.root)
|
43
|
+
const_env = TypeInference::ConstantEnv.new(factory: subtyping.factory, context: [RBS::Namespace.root])
|
46
44
|
type_env = TypeInference::TypeEnv.build(annotations: annotations,
|
47
45
|
subtyping: subtyping,
|
48
46
|
const_env: const_env,
|
@@ -55,12 +53,14 @@ module Steep
|
|
55
53
|
context = TypeInference::Context.new(
|
56
54
|
block_context: nil,
|
57
55
|
module_context: TypeInference::Context::ModuleContext.new(
|
58
|
-
instance_type:
|
59
|
-
module_type:
|
56
|
+
instance_type: AST::Builtin::Object.instance_type,
|
57
|
+
module_type: AST::Builtin::Object.module_type,
|
60
58
|
implement_name: nil,
|
61
|
-
current_namespace:
|
59
|
+
current_namespace: RBS::Namespace.root,
|
62
60
|
const_env: const_env,
|
63
|
-
class_name:
|
61
|
+
class_name: AST::Builtin::Object.module_name,
|
62
|
+
instance_definition: subtyping.factory.definition_builder.build_instance(AST::Builtin::Object.module_name),
|
63
|
+
module_definition: subtyping.factory.definition_builder.build_singleton(AST::Builtin::Object.module_name)
|
64
64
|
),
|
65
65
|
method_context: nil,
|
66
66
|
break_context: nil,
|
@@ -86,31 +86,31 @@ module Steep
|
|
86
86
|
|
87
87
|
def type_check(subtyping, env_updated_at)
|
88
88
|
# skip type check
|
89
|
-
return false if status
|
89
|
+
return false if status && env_updated_at <= status.timestamp
|
90
|
+
|
91
|
+
now = Time.now
|
90
92
|
|
91
93
|
parse(subtyping.factory) do |source|
|
92
94
|
typing = self.class.type_check(source, subtyping: subtyping)
|
93
|
-
@status = TypeCheckStatus.new(
|
94
|
-
typing: typing,
|
95
|
-
source: source,
|
96
|
-
timestamp: Time.now
|
97
|
-
)
|
95
|
+
@status = TypeCheckStatus.new(typing: typing, source: source, timestamp: now)
|
98
96
|
rescue RBS::NoTypeFoundError,
|
99
97
|
RBS::NoMixinFoundError,
|
100
98
|
RBS::NoSuperclassFoundError,
|
101
99
|
RBS::DuplicatedMethodDefinitionError,
|
102
100
|
RBS::InvalidTypeApplicationError => exn
|
103
101
|
# Skip logging known signature errors (they are handled with load_signatures(validate: true))
|
104
|
-
@status = TypeCheckErrorStatus.new(error: exn)
|
102
|
+
@status = TypeCheckErrorStatus.new(error: exn, timestamp: now)
|
105
103
|
rescue => exn
|
106
104
|
Steep.log_error(exn)
|
107
|
-
@status = TypeCheckErrorStatus.new(error: exn)
|
105
|
+
@status = TypeCheckErrorStatus.new(error: exn, timestamp: now)
|
108
106
|
end
|
109
107
|
|
110
108
|
true
|
111
109
|
end
|
112
110
|
|
113
111
|
def parse(factory)
|
112
|
+
now = Time.now
|
113
|
+
|
114
114
|
if status.is_a?(TypeCheckStatus)
|
115
115
|
yield status.source
|
116
116
|
else
|
@@ -118,40 +118,10 @@ module Steep
|
|
118
118
|
end
|
119
119
|
rescue AnnotationParser::SyntaxError => exn
|
120
120
|
Steep.logger.warn { "Annotation syntax error on #{path}: #{exn.inspect}" }
|
121
|
-
@status = AnnotationSyntaxErrorStatus.new(error: exn, location: exn.location)
|
121
|
+
@status = AnnotationSyntaxErrorStatus.new(error: exn, location: exn.location, timestamp: now)
|
122
122
|
rescue ::Parser::SyntaxError, EncodingError => exn
|
123
123
|
Steep.logger.warn { "Source parsing error on #{path}: #{exn.inspect}" }
|
124
|
-
@status = ParseErrorStatus.new(error: exn)
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
class SignatureFile
|
129
|
-
attr_reader :path
|
130
|
-
attr_reader :content
|
131
|
-
attr_reader :content_updated_at
|
132
|
-
|
133
|
-
attr_reader :status
|
134
|
-
|
135
|
-
ParseErrorStatus = Struct.new(:error, keyword_init: true)
|
136
|
-
DeclarationsStatus = Struct.new(:declarations, keyword_init: true)
|
137
|
-
|
138
|
-
def initialize(path:)
|
139
|
-
@path = path
|
140
|
-
self.content = ""
|
141
|
-
end
|
142
|
-
|
143
|
-
def content=(content)
|
144
|
-
@content_updated_at = Time.now
|
145
|
-
@content = content
|
146
|
-
@status = nil
|
147
|
-
end
|
148
|
-
|
149
|
-
def load!
|
150
|
-
buffer = RBS::Buffer.new(name: path, content: content)
|
151
|
-
decls = RBS::Parser.parse_signature(buffer)
|
152
|
-
@status = DeclarationsStatus.new(declarations: decls)
|
153
|
-
rescue RBS::Parser::SyntaxError, RBS::Parser::SemanticsError => exn
|
154
|
-
@status = ParseErrorStatus.new(error: exn)
|
124
|
+
@status = ParseErrorStatus.new(error: exn, timestamp: now)
|
155
125
|
end
|
156
126
|
end
|
157
127
|
end
|