steep 0.40.0 → 0.44.0

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