steep 0.40.0 → 0.44.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.
Files changed (169) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +38 -0
  3. data/Gemfile +1 -0
  4. data/bin/output_rebaseline.rb +15 -30
  5. data/bin/output_test.rb +23 -57
  6. data/lib/steep.rb +89 -15
  7. data/lib/steep/annotation_parser.rb +10 -2
  8. data/lib/steep/ast/types/class.rb +4 -0
  9. data/lib/steep/cli.rb +31 -6
  10. data/lib/steep/diagnostic/ruby.rb +13 -8
  11. data/lib/steep/diagnostic/signature.rb +152 -2
  12. data/lib/steep/drivers/annotations.rb +18 -36
  13. data/lib/steep/drivers/check.rb +140 -31
  14. data/lib/steep/drivers/diagnostic_printer.rb +20 -11
  15. data/lib/steep/drivers/langserver.rb +4 -8
  16. data/lib/steep/drivers/print_project.rb +10 -9
  17. data/lib/steep/drivers/stats.rb +135 -119
  18. data/lib/steep/drivers/utils/driver_helper.rb +35 -0
  19. data/lib/steep/drivers/utils/jobs_count.rb +9 -0
  20. data/lib/steep/drivers/validate.rb +29 -18
  21. data/lib/steep/drivers/watch.rb +55 -49
  22. data/lib/steep/drivers/worker.rb +11 -8
  23. data/lib/steep/expectations.rb +159 -0
  24. data/lib/steep/index/signature_symbol_provider.rb +23 -1
  25. data/lib/steep/index/source_index.rb +55 -5
  26. data/lib/steep/interface/block.rb +4 -0
  27. data/lib/steep/project.rb +0 -30
  28. data/lib/steep/project/dsl.rb +5 -3
  29. data/lib/steep/project/pattern.rb +56 -0
  30. data/lib/steep/project/target.rb +11 -227
  31. data/lib/steep/server/base_worker.rb +1 -3
  32. data/lib/steep/server/change_buffer.rb +63 -0
  33. data/lib/steep/server/interaction_worker.rb +72 -57
  34. data/lib/steep/server/master.rb +652 -234
  35. data/lib/steep/server/type_check_worker.rb +304 -0
  36. data/lib/steep/server/worker_process.rb +16 -11
  37. data/lib/steep/{project → services}/completion_provider.rb +5 -5
  38. data/lib/steep/services/content_change.rb +61 -0
  39. data/lib/steep/services/file_loader.rb +48 -0
  40. data/lib/steep/services/goto_service.rb +321 -0
  41. data/lib/steep/{project → services}/hover_content.rb +19 -20
  42. data/lib/steep/services/path_assignment.rb +27 -0
  43. data/lib/steep/services/signature_service.rb +403 -0
  44. data/lib/steep/services/stats_calculator.rb +69 -0
  45. data/lib/steep/services/type_check_service.rb +413 -0
  46. data/lib/steep/signature/validator.rb +187 -85
  47. data/lib/steep/source.rb +21 -18
  48. data/lib/steep/subtyping/check.rb +246 -45
  49. data/lib/steep/subtyping/constraints.rb +4 -4
  50. data/lib/steep/type_construction.rb +428 -193
  51. data/lib/steep/type_inference/block_params.rb +1 -1
  52. data/lib/steep/type_inference/context.rb +22 -0
  53. data/lib/steep/type_inference/local_variable_type_env.rb +26 -12
  54. data/lib/steep/type_inference/logic.rb +1 -1
  55. data/lib/steep/type_inference/logic_type_interpreter.rb +4 -4
  56. data/lib/steep/type_inference/type_env.rb +43 -17
  57. data/lib/steep/version.rb +1 -1
  58. data/smoke/alias/test_expectations.yml +96 -0
  59. data/smoke/and/test_expectations.yml +31 -0
  60. data/smoke/array/test_expectations.yml +103 -0
  61. data/smoke/block/test_expectations.yml +125 -0
  62. data/smoke/case/test_expectations.yml +47 -0
  63. data/smoke/class/test_expectations.yml +120 -0
  64. data/smoke/const/test_expectations.yml +129 -0
  65. data/smoke/diagnostics-rbs-duplicated/test_expectations.yml +13 -0
  66. data/smoke/diagnostics-rbs/Steepfile +7 -4
  67. data/smoke/diagnostics-rbs/test_expectations.yml +231 -0
  68. data/smoke/diagnostics-rbs/unknown-type-name-2.rbs +5 -0
  69. data/smoke/{broken → diagnostics-ruby-unsat}/Steepfile +0 -0
  70. data/smoke/diagnostics-ruby-unsat/a.rbs +3 -0
  71. data/smoke/diagnostics-ruby-unsat/test_expectations.yml +27 -0
  72. data/smoke/{diagnostics → diagnostics-ruby-unsat}/unsatisfiable_constraint.rb +0 -1
  73. data/smoke/diagnostics/a.rbs +0 -4
  74. data/smoke/diagnostics/test_expectations.yml +451 -0
  75. data/smoke/dstr/test_expectations.yml +13 -0
  76. data/smoke/ensure/test_expectations.yml +62 -0
  77. data/smoke/enumerator/test_expectations.yml +135 -0
  78. data/smoke/extension/f.rb +2 -0
  79. data/smoke/extension/f.rbs +3 -0
  80. data/smoke/extension/test_expectations.yml +73 -0
  81. data/smoke/hash/test_expectations.yml +81 -0
  82. data/smoke/hello/test_expectations.yml +25 -0
  83. data/smoke/if/test_expectations.yml +34 -0
  84. data/smoke/implements/b.rb +13 -0
  85. data/smoke/implements/b.rbs +12 -0
  86. data/smoke/implements/test_expectations.yml +23 -0
  87. data/smoke/initialize/test_expectations.yml +1 -0
  88. data/smoke/integer/test_expectations.yml +101 -0
  89. data/smoke/interface/test_expectations.yml +23 -0
  90. data/smoke/kwbegin/test_expectations.yml +17 -0
  91. data/smoke/lambda/test_expectations.yml +39 -0
  92. data/smoke/literal/test_expectations.yml +106 -0
  93. data/smoke/map/test_expectations.yml +1 -0
  94. data/smoke/method/test_expectations.yml +90 -0
  95. data/smoke/module/test_expectations.yml +75 -0
  96. data/smoke/regexp/test_expectations.yml +615 -0
  97. data/smoke/regression/issue_328.rb +1 -0
  98. data/smoke/regression/issue_328.rbs +0 -0
  99. data/smoke/regression/issue_332.rb +11 -0
  100. data/smoke/regression/issue_332.rbs +19 -0
  101. data/smoke/regression/issue_372.rb +8 -0
  102. data/smoke/regression/issue_372.rbs +4 -0
  103. data/smoke/regression/masgn.rb +4 -0
  104. data/smoke/regression/test_expectations.yml +60 -0
  105. data/smoke/regression/thread.rb +7 -0
  106. data/smoke/rescue/test_expectations.yml +79 -0
  107. data/smoke/self/test_expectations.yml +23 -0
  108. data/smoke/skip/test_expectations.yml +23 -0
  109. data/smoke/stdout/test_expectations.yml +1 -0
  110. data/smoke/super/test_expectations.yml +69 -0
  111. data/smoke/toplevel/test_expectations.yml +15 -0
  112. data/smoke/tsort/Steepfile +2 -0
  113. data/smoke/tsort/test_expectations.yml +63 -0
  114. data/smoke/type_case/test_expectations.yml +48 -0
  115. data/smoke/unexpected/Steepfile +5 -0
  116. data/smoke/unexpected/test_expectations.yml +25 -0
  117. data/smoke/unexpected/unexpected.rb +1 -0
  118. data/smoke/unexpected/unexpected.rbs +3 -0
  119. data/smoke/yield/test_expectations.yml +68 -0
  120. data/steep.gemspec +4 -3
  121. metadata +127 -80
  122. data/lib/steep/project/file_loader.rb +0 -68
  123. data/lib/steep/project/signature_file.rb +0 -39
  124. data/lib/steep/project/source_file.rb +0 -129
  125. data/lib/steep/project/stats_calculator.rb +0 -80
  126. data/lib/steep/server/code_worker.rb +0 -150
  127. data/lib/steep/server/signature_worker.rb +0 -157
  128. data/lib/steep/server/utils.rb +0 -69
  129. data/smoke/alias/test.yaml +0 -73
  130. data/smoke/and/test.yaml +0 -24
  131. data/smoke/array/test.yaml +0 -80
  132. data/smoke/block/test.yaml +0 -96
  133. data/smoke/broken/broken.rb +0 -0
  134. data/smoke/broken/broken.rbs +0 -0
  135. data/smoke/broken/test.yaml +0 -6
  136. data/smoke/case/test.yaml +0 -36
  137. data/smoke/class/test.yaml +0 -89
  138. data/smoke/const/test.yaml +0 -96
  139. data/smoke/diagnostics-rbs-duplicated/test.yaml +0 -10
  140. data/smoke/diagnostics-rbs/test.yaml +0 -142
  141. data/smoke/diagnostics/test.yaml +0 -333
  142. data/smoke/dstr/test.yaml +0 -10
  143. data/smoke/ensure/test.yaml +0 -47
  144. data/smoke/enumerator/test.yaml +0 -100
  145. data/smoke/extension/test.yaml +0 -50
  146. data/smoke/hash/test.yaml +0 -62
  147. data/smoke/hello/test.yaml +0 -18
  148. data/smoke/if/test.yaml +0 -27
  149. data/smoke/implements/test.yaml +0 -16
  150. data/smoke/initialize/test.yaml +0 -4
  151. data/smoke/integer/test.yaml +0 -66
  152. data/smoke/interface/test.yaml +0 -16
  153. data/smoke/kwbegin/test.yaml +0 -14
  154. data/smoke/lambda/test.yaml +0 -28
  155. data/smoke/literal/test.yaml +0 -79
  156. data/smoke/map/test.yaml +0 -4
  157. data/smoke/method/test.yaml +0 -71
  158. data/smoke/module/test.yaml +0 -51
  159. data/smoke/regexp/test.yaml +0 -372
  160. data/smoke/regression/test.yaml +0 -38
  161. data/smoke/rescue/test.yaml +0 -60
  162. data/smoke/self/test.yaml +0 -16
  163. data/smoke/skip/test.yaml +0 -16
  164. data/smoke/stdout/test.yaml +0 -4
  165. data/smoke/super/test.yaml +0 -52
  166. data/smoke/toplevel/test.yaml +0 -12
  167. data/smoke/tsort/test.yaml +0 -32
  168. data/smoke/type_case/test.yaml +0 -33
  169. data/smoke/yield/test.yaml +0 -49
@@ -4,10 +4,14 @@ module Steep
4
4
  LSP = LanguageServer::Protocol
5
5
  SymbolInformation = Struct.new(:name, :kind, :container_name, :location, keyword_init: true)
6
6
 
7
+ attr_reader :project
7
8
  attr_reader :indexes
9
+ attr_reader :assignment
8
10
 
9
- def initialize()
11
+ def initialize(project:, assignment:)
10
12
  @indexes = []
13
+ @project = project
14
+ @assignment = assignment
11
15
  end
12
16
 
13
17
  def self.test_type_name(query, type_name)
@@ -33,6 +37,16 @@ module Steep
33
37
  end
34
38
  end
35
39
 
40
+ def assigned?(path)
41
+ if path.relative?
42
+ if project.targets.any? {|target| target.possible_signature_file?(path) }
43
+ path = project.absolute_path(path)
44
+ end
45
+ end
46
+
47
+ assignment =~ path
48
+ end
49
+
36
50
  def query_symbol(query)
37
51
  symbols = []
38
52
 
@@ -46,6 +60,8 @@ module Steep
46
60
  name = entry.type_name.name.to_s
47
61
 
48
62
  entry.declarations.each do |decl|
63
+ next unless assigned?(Pathname(decl.location.buffer.name))
64
+
49
65
  case decl
50
66
  when RBS::AST::Declarations::Class
51
67
  symbols << SymbolInformation.new(
@@ -89,6 +105,8 @@ module Steep
89
105
  container_name = entry.method_name.type_name.relative!.to_s
90
106
 
91
107
  entry.declarations.each do |decl|
108
+ next unless assigned?(Pathname(decl.location.buffer.name))
109
+
92
110
  case decl
93
111
  when RBS::AST::Members::MethodDefinition
94
112
  symbols << SymbolInformation.new(
@@ -126,6 +144,8 @@ module Steep
126
144
  next unless SignatureSymbolProvider.test_const_name(query, entry.const_name)
127
145
 
128
146
  entry.declarations.each do |decl|
147
+ next unless assigned?(Pathname(decl.location.buffer.name))
148
+
129
149
  symbols << SymbolInformation.new(
130
150
  name: entry.const_name.name.to_s,
131
151
  location: decl.location,
@@ -137,6 +157,8 @@ module Steep
137
157
  next unless SignatureSymbolProvider.test_global_name(query, entry.global_name)
138
158
 
139
159
  entry.declarations.each do |decl|
160
+ next unless assigned?(Pathname(decl.location.buffer.name))
161
+
140
162
  symbols << SymbolInformation.new(
141
163
  name: decl.name.to_s,
142
164
  location: decl.location,
@@ -43,8 +43,51 @@ module Steep
43
43
  end
44
44
  end
45
45
 
46
+ class MethodEntry
47
+ attr_reader :name
48
+
49
+ attr_reader :definitions
50
+ attr_reader :references
51
+
52
+ def initialize(name:)
53
+ @name = name
54
+
55
+ @definitions = Set[].compare_by_identity
56
+ @references = Set[].compare_by_identity
57
+ end
58
+
59
+ def add_definition(node)
60
+ case node.type
61
+ when :def, :defs
62
+ @definitions << node
63
+ else
64
+ raise "Unexpected method definition: #{node.type}"
65
+ end
66
+
67
+ self
68
+ end
69
+
70
+ def add_reference(node)
71
+ case node.type
72
+ when :send, :block
73
+ @references << node
74
+ else
75
+ raise "Unexpected method reference: #{node.type}"
76
+ end
77
+
78
+ self
79
+ end
80
+
81
+ def merge!(other)
82
+ definitions.merge(other.definitions)
83
+ references.merge(other.references)
84
+ self
85
+ end
86
+ end
87
+
46
88
  attr_reader :source
47
89
  attr_reader :constant_index
90
+ attr_reader :method_index
48
91
 
49
92
  attr_reader :parent
50
93
  attr_reader :count
@@ -58,6 +101,7 @@ module Steep
58
101
  @count = @parent_count || 0
59
102
 
60
103
  @constant_index = {}
104
+ @method_index = {}
61
105
  end
62
106
 
63
107
  def new_child
@@ -72,25 +116,31 @@ module Steep
72
116
  entry.merge!(child_entry)
73
117
  end
74
118
 
119
+ method_index.merge!(child.method_index) do |_, entry, child_entry|
120
+ entry.merge!(child_entry)
121
+ end
122
+
75
123
  @count = child.count + 1
76
124
  end
77
125
 
78
- def add_definition(constant:, definition:)
126
+ def add_definition(constant: nil, method: nil, definition:)
79
127
  @count += 1
80
- entry(constant: constant).add_definition(definition)
128
+ entry(constant: constant, method: method).add_definition(definition)
81
129
  self
82
130
  end
83
131
 
84
- def add_reference(constant:, ref:)
132
+ def add_reference(constant: nil, method: nil, ref:)
85
133
  @count += 1
86
- entry(constant: constant).add_reference(ref)
134
+ entry(constant: constant, method: method).add_reference(ref)
87
135
  self
88
136
  end
89
137
 
90
- def entry(constant:)
138
+ def entry(constant: nil, method: nil)
91
139
  case
92
140
  when constant
93
141
  constant_index[constant] ||= ConstantEntry.new(name: constant)
142
+ when method
143
+ method_index[method] ||= MethodEntry.new(name: method)
94
144
  else
95
145
  raise
96
146
  end
@@ -13,6 +13,10 @@ module Steep
13
13
  @optional
14
14
  end
15
15
 
16
+ def required?
17
+ !optional?
18
+ end
19
+
16
20
  def to_optional
17
21
  self.class.new(
18
22
  type: type,
data/lib/steep/project.rb CHANGED
@@ -42,35 +42,5 @@ module Steep
42
42
  ]
43
43
  end
44
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
-
52
- def type_of_node(path:, line:, column:)
53
- source_file = targets.map {|target| target.source_files[path] }.compact[0]
54
-
55
- if source_file
56
-
57
- case (status = source_file.status)
58
- when SourceFile::TypeCheckStatus
59
- node = status.source.find_node(line: line, column: column)
60
-
61
- type = begin
62
- status.typing.type_of(node: node)
63
- rescue RuntimeError
64
- AST::Builtin.any_type
65
- end
66
-
67
- if block_given?
68
- yield type, node
69
- else
70
- type
71
- end
72
- end
73
- end
74
- end
75
45
  end
76
46
  end
@@ -120,11 +120,13 @@ module Steep
120
120
 
121
121
  target.instance_eval(&block) if block_given?
122
122
 
123
+ source_pattern = Pattern.new(patterns: target.sources, ignores: target.ignored_sources, ext: ".rb")
124
+ signature_pattern = Pattern.new(patterns: target.signatures, ext: ".rbs")
125
+
123
126
  Project::Target.new(
124
127
  name: target.name,
125
- source_patterns: target.sources,
126
- ignore_patterns: target.ignored_sources,
127
- signature_patterns: target.signatures,
128
+ source_pattern: source_pattern,
129
+ signature_pattern: signature_pattern,
128
130
  options: Options.new.tap do |options|
129
131
  options.libraries.push(*target.libraries)
130
132
  options.repository_paths.push(*target.repo_paths)
@@ -0,0 +1,56 @@
1
+ module Steep
2
+ class Project
3
+ class Pattern
4
+ attr_reader :patterns
5
+ attr_reader :ignores
6
+ attr_reader :prefixes
7
+ attr_reader :ignore_prefixes
8
+ attr_reader :ext
9
+
10
+ def initialize(patterns:, ignores: [], ext:)
11
+ @patterns = patterns
12
+ @ignores = ignores
13
+ @ext = ext
14
+
15
+ @prefixes = patterns.map do |pat|
16
+ if pat == "." || pat == "./"
17
+ ""
18
+ else
19
+ pat.delete_prefix("./").delete_suffix(File::Separator) << File::Separator
20
+ end
21
+ end
22
+ @ignore_prefixes = ignores.map do |pat|
23
+ if pat == "." || pat == "./"
24
+ ""
25
+ else
26
+ pat.delete_prefix("./").delete_suffix(File::Separator) << File::Separator
27
+ end
28
+ end
29
+ end
30
+
31
+ def =~(path)
32
+ unless path.is_a?(Pathname)
33
+ path = Pathname(path.to_s)
34
+ end
35
+
36
+ match?(path) && !ignore?(path)
37
+ end
38
+
39
+ def match?(path)
40
+ test_string(path, patterns, prefixes)
41
+ end
42
+
43
+ def ignore?(path)
44
+ test_string(path, ignores, ignore_prefixes)
45
+ end
46
+
47
+ def test_string(path, patterns, prefixes)
48
+ string = path.to_s
49
+ extension = path.extname
50
+
51
+ patterns.any? {|pat| File.fnmatch(pat, string) } ||
52
+ prefixes.any? {|prefix| string.start_with?(prefix) && extension == ext }
53
+ end
54
+ end
55
+ end
56
+ end
@@ -4,118 +4,35 @@ module Steep
4
4
  attr_reader :name
5
5
  attr_reader :options
6
6
 
7
- attr_reader :source_patterns
8
- attr_reader :ignore_patterns
9
- attr_reader :signature_patterns
7
+ attr_reader :source_pattern
8
+ attr_reader :signature_pattern
10
9
 
11
- attr_reader :source_files
12
- attr_reader :signature_files
13
-
14
- attr_reader :status
15
-
16
- SignatureErrorStatus = Struct.new(:timestamp, :errors, keyword_init: true)
17
- TypeCheckStatus = Struct.new(:environment, :subtyping, :type_check_sources, :timestamp, keyword_init: true)
18
-
19
- def initialize(name:, options:, source_patterns:, ignore_patterns:, signature_patterns:)
10
+ def initialize(name:, options:, source_pattern:, signature_pattern:)
20
11
  @name = name
21
12
  @options = options
22
- @source_patterns = source_patterns
23
- @ignore_patterns = ignore_patterns
24
- @signature_patterns = signature_patterns
13
+ @source_pattern = source_pattern
14
+ @signature_pattern = signature_pattern
25
15
 
26
16
  @source_files = {}
27
17
  @signature_files = {}
28
18
  end
29
19
 
30
- def add_source(path, content = "")
31
- file = SourceFile.new(path: path)
32
-
33
- if block_given?
34
- file.content = yield
35
- else
36
- file.content = content
37
- end
38
-
39
- source_files[path] = file
40
- end
41
-
42
- def remove_source(path)
43
- source_files.delete(path)
44
- end
45
-
46
- def update_source(path, content = nil)
47
- file = source_files[path]
48
- if block_given?
49
- file.content = yield(file.content)
50
- else
51
- file.content = content || file.content
52
- end
53
- end
54
-
55
- def add_signature(path, content = "")
56
- file = SignatureFile.new(path: path)
57
- if block_given?
58
- file.content = yield
59
- else
60
- file.content = content
61
- end
62
- signature_files[path] = file
63
- end
64
-
65
- def remove_signature(path)
66
- signature_files.delete(path)
67
- end
68
-
69
- def update_signature(path, content = nil)
70
- file = signature_files[path]
71
- if block_given?
72
- file.content = yield(file.content)
73
- else
74
- file.content = content || file.content
75
- end
76
- end
77
-
78
- def source_file?(path)
79
- source_files.key?(path)
80
- end
81
-
82
- def signature_file?(path)
83
- signature_files.key?(path)
84
- end
85
-
86
20
  def possible_source_file?(path)
87
- self.class.test_pattern(source_patterns, path, ext: ".rb") &&
88
- !self.class.test_pattern(ignore_patterns, path, ext: ".rb")
21
+ source_pattern =~ path
89
22
  end
90
23
 
91
24
  def possible_signature_file?(path)
92
- self.class.test_pattern(signature_patterns, path, ext: ".rbs")
93
- end
94
-
95
- def self.test_pattern(patterns, path, ext:)
96
- patterns.any? do |pattern|
97
- p = pattern.end_with?(File::Separator) ? pattern : pattern + File::Separator
98
- p.delete_prefix!('./')
99
- (path.to_s.start_with?(p) && path.extname == ext) || File.fnmatch(pattern, path.to_s)
100
- end
25
+ signature_pattern =~ path
101
26
  end
102
27
 
103
- def type_check(target_sources: source_files.values, validate_signatures: true)
104
- Steep.logger.tagged "target#type_check(target_sources: [#{target_sources.map(&:path).join(", ")}], validate_signatures: #{validate_signatures})" do
105
- Steep.measure "load signature and type check" do
106
- load_signatures(validate: validate_signatures) do |env, check, timestamp|
107
- Steep.measure "type checking #{target_sources.size} files" do
108
- run_type_check(env, check, timestamp, target_sources: target_sources)
109
- end
110
- end
111
- end
112
- end
28
+ def new_env_loader(project:)
29
+ Target.construct_env_loader(options: options, project: project)
113
30
  end
114
31
 
115
- def self.construct_env_loader(options:)
32
+ def self.construct_env_loader(options:, project:)
116
33
  repo = RBS::Repository.new(no_stdlib: options.vendor_path)
117
34
  options.repository_paths.each do |path|
118
- repo.add(path)
35
+ repo.add(project.absolute_path(path))
119
36
  end
120
37
 
121
38
  loader = RBS::EnvironmentLoader.new(
@@ -130,139 +47,6 @@ module Steep
130
47
 
131
48
  loader
132
49
  end
133
-
134
- def environment
135
- @environment ||= RBS::Environment.from_loader(Target.construct_env_loader(options: options))
136
- end
137
-
138
- def parse_signatures(timestamp:)
139
- updated_signature_files = []
140
-
141
- signature_files.each_value do |file|
142
- if !timestamp || file.content_updated_at >= timestamp
143
- Steep.logger.debug { "Loading #{file.path}..."}
144
- updated_signature_files << file
145
- file.load!()
146
- end
147
- end
148
-
149
- error_sigs = signature_files.each_value.reject {|file| file.status.is_a?(SignatureFile::DeclarationsStatus) }
150
-
151
- if error_sigs.empty?
152
- yield updated_signature_files
153
- else
154
- errors = error_sigs.map do |file|
155
- case error = file.status.error
156
- when RBS::Parser::SemanticsError
157
- Diagnostic::Signature::SyntaxError.new(error, location: error.location)
158
- when RBS::Parser::SyntaxError
159
- Diagnostic::Signature::SyntaxError.new(error, location: error.error_value.location)
160
- end
161
- end
162
-
163
- @status = SignatureErrorStatus.new(
164
- errors: errors,
165
- timestamp: Time.now
166
- )
167
- end
168
- end
169
-
170
- def load_decls(now:)
171
- errors = []
172
- env = environment.dup
173
-
174
- signature_files.each_value do |file|
175
- raise unless file.status.is_a?(SignatureFile::DeclarationsStatus)
176
-
177
- file.status.declarations.each do |decl|
178
- env << decl
179
- rescue RBS::DuplicatedDeclarationError => exn
180
- errors << Diagnostic::Signature::DuplicatedDeclaration.new(
181
- type_name: exn.name,
182
- location: exn.decls[0].location
183
- )
184
- end
185
- end
186
-
187
- if errors.empty?
188
- yield env.resolve_type_names
189
- else
190
- @status = SignatureErrorStatus.new(
191
- errors: errors,
192
- timestamp: now
193
- )
194
- end
195
- end
196
-
197
- def load_signatures(validate:)
198
- timestamp = case status
199
- when TypeCheckStatus
200
- status.timestamp
201
- end
202
- now = Time.now
203
-
204
- parse_signatures(timestamp: timestamp) do |updated_signature_files|
205
- if status.is_a?(TypeCheckStatus) && updated_signature_files.empty?
206
- yield status.environment, status.subtyping, status.timestamp
207
- else
208
- load_decls(now: now) do |env|
209
- definition_builder = RBS::DefinitionBuilder.new(env: env)
210
- factory = AST::Types::Factory.new(builder: definition_builder)
211
- check = Subtyping::Check.new(factory: factory)
212
-
213
- if validate
214
- validator = Signature::Validator.new(checker: check)
215
- validator.validate()
216
-
217
- if validator.no_error?
218
- yield env, check, now
219
- else
220
- @status = SignatureErrorStatus.new(
221
- errors: validator.each_error.to_a,
222
- timestamp: now
223
- )
224
- end
225
- else
226
- yield env, check, Time.now
227
- end
228
- end
229
- end
230
- end
231
- end
232
-
233
- def run_type_check(env, check, timestamp, target_sources: source_files.values)
234
- type_check_sources = []
235
-
236
- target_sources.each do |file|
237
- Steep.logger.tagged("path=#{file.path}") do
238
- if file.type_check(check, timestamp)
239
- type_check_sources << file
240
- end
241
- end
242
- end
243
-
244
- @status = TypeCheckStatus.new(
245
- environment: env,
246
- subtyping: check,
247
- type_check_sources: type_check_sources,
248
- timestamp: timestamp
249
- )
250
- end
251
-
252
- def no_error?
253
- source_files.all? do |_, file|
254
- file.status.is_a?(Project::SourceFile::TypeCheckStatus)
255
- end
256
- end
257
-
258
- def errors
259
- case status
260
- when TypeCheckStatus
261
- source_files.each_value.flat_map(&:errors).select { |error | options.error_to_report?(error) }
262
- else
263
- []
264
- end
265
- end
266
50
  end
267
51
  end
268
52
  end