steep 1.9.0.dev.2 → 1.9.1

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +82 -0
  3. data/README.md +9 -4
  4. data/Rakefile +1 -0
  5. data/Steepfile +11 -0
  6. data/bin/generate-diagnostics-docs.rb +112 -0
  7. data/lib/steep/ast/builtin.rb +1 -0
  8. data/lib/steep/ast/ignore.rb +1 -1
  9. data/lib/steep/ast/types/factory.rb +2 -0
  10. data/lib/steep/cli.rb +9 -2
  11. data/lib/steep/diagnostic/lsp_formatter.rb +8 -1
  12. data/lib/steep/diagnostic/ruby.rb +65 -3
  13. data/lib/steep/diagnostic/signature.rb +4 -4
  14. data/lib/steep/drivers/annotations.rb +1 -1
  15. data/lib/steep/drivers/check.rb +3 -3
  16. data/lib/steep/drivers/diagnostic_printer.rb +1 -1
  17. data/lib/steep/drivers/init.rb +6 -3
  18. data/lib/steep/expectations.rb +1 -1
  19. data/lib/steep/interface/builder.rb +7 -5
  20. data/lib/steep/interface/function.rb +13 -0
  21. data/lib/steep/interface/method_type.rb +5 -0
  22. data/lib/steep/interface/shape.rb +1 -1
  23. data/lib/steep/project/dsl.rb +11 -1
  24. data/lib/steep/project/target.rb +3 -1
  25. data/lib/steep/server/change_buffer.rb +1 -1
  26. data/lib/steep/server/interaction_worker.rb +5 -5
  27. data/lib/steep/server/master.rb +2 -17
  28. data/lib/steep/server/type_check_controller.rb +3 -3
  29. data/lib/steep/server/type_check_worker.rb +1 -1
  30. data/lib/steep/services/completion_provider.rb +4 -4
  31. data/lib/steep/services/goto_service.rb +3 -3
  32. data/lib/steep/services/hover_provider/rbs.rb +1 -1
  33. data/lib/steep/services/hover_provider/ruby.rb +6 -6
  34. data/lib/steep/services/signature_help_provider.rb +8 -8
  35. data/lib/steep/services/signature_service.rb +12 -8
  36. data/lib/steep/services/type_check_service.rb +9 -9
  37. data/lib/steep/signature/validator.rb +3 -3
  38. data/lib/steep/source.rb +4 -4
  39. data/lib/steep/subtyping/check.rb +3 -3
  40. data/lib/steep/subtyping/constraints.rb +4 -4
  41. data/lib/steep/type_construction.rb +84 -45
  42. data/lib/steep/type_inference/block_params.rb +3 -3
  43. data/lib/steep/type_inference/context.rb +1 -1
  44. data/lib/steep/type_inference/method_params.rb +1 -1
  45. data/lib/steep/type_inference/type_env.rb +3 -3
  46. data/lib/steep/version.rb +1 -1
  47. data/manual/annotations.md +37 -0
  48. data/manual/ignore.md +20 -0
  49. data/manual/ruby-diagnostics.md +1812 -0
  50. data/steep.gemspec +1 -1
  51. metadata +8 -5
@@ -1057,6 +1057,19 @@ module Steep
1057
1057
  )
1058
1058
  end
1059
1059
 
1060
+ def accept_one_arg?
1061
+ return false unless params
1062
+ return false unless params.keyword_params.requireds.empty?
1063
+ head = params.positional_params or return false
1064
+
1065
+ case head.head
1066
+ when Params::PositionalParams::Required
1067
+ !head.tail.is_a?(Params::PositionalParams::Required)
1068
+ else
1069
+ true
1070
+ end
1071
+ end
1072
+
1060
1073
  def to_s
1061
1074
  if params
1062
1075
  "#{params} -> #{return_type}"
@@ -320,6 +320,11 @@ module Steep
320
320
  block: block
321
321
  )
322
322
  end
323
+
324
+ def accept_one_arg?
325
+ return false if block && block.required?
326
+ type.accept_one_arg?
327
+ end
323
328
  end
324
329
  end
325
330
  end
@@ -125,7 +125,7 @@ module Steep
125
125
  return nil unless key?(name)
126
126
 
127
127
  resolved_methods[name] ||= begin
128
- entry = methods[name]
128
+ entry = methods.fetch(name)
129
129
  Entry.new(
130
130
  method_name: name,
131
131
  overloads: entry.overloads.map do |overload|
@@ -119,6 +119,7 @@ module Steep
119
119
  attr_reader :project
120
120
  attr_reader :unreferenced
121
121
  attr_reader :groups
122
+ attr_reader :implicitly_returns_nil
122
123
 
123
124
  def initialize(name, project:)
124
125
  @name = name
@@ -127,6 +128,7 @@ module Steep
127
128
  @project = project
128
129
  @collection_config_path = collection_config_path
129
130
  @unreferenced = false
131
+ @implicitly_returns_nil = false
130
132
  @groups = []
131
133
  end
132
134
 
@@ -144,6 +146,7 @@ module Steep
144
146
  @project = other.project
145
147
  @collection_config_path = other.collection_config_path
146
148
  @unreferenced = other.unreferenced
149
+ @implicitly_returns_nil = other.implicitly_returns_nil
147
150
  @groups = other.groups.dup
148
151
  end
149
152
 
@@ -151,6 +154,10 @@ module Steep
151
154
  @unreferenced = value
152
155
  end
153
156
 
157
+ def implicitly_returns_nil!(value = true)
158
+ @implicitly_returns_nil = value
159
+ end
160
+
154
161
  def configure_code_diagnostics(hash = nil)
155
162
  if hash
156
163
  code_diagnostics_config.merge!(hash)
@@ -164,6 +171,7 @@ module Steep
164
171
  end
165
172
 
166
173
  def group(name, &block)
174
+ name = name.to_str.to_sym unless Symbol === name
167
175
  group = GroupDSL.new(name, self)
168
176
 
169
177
  Steep.logger.tagged "group=#{name}" do
@@ -230,6 +238,7 @@ module Steep
230
238
  end
231
239
 
232
240
  def target(name, &block)
241
+ name = name.to_str.to_sym unless Symbol === name
233
242
  dsl = TargetDSL.new(name, project: project)
234
243
 
235
244
  Steep.logger.tagged "target=#{name}" do
@@ -243,7 +252,8 @@ module Steep
243
252
  options: dsl.library_configured? ? dsl.to_library_options : nil,
244
253
  code_diagnostics_config: dsl.code_diagnostics_config,
245
254
  project: project,
246
- unreferenced: dsl.unreferenced
255
+ unreferenced: dsl.unreferenced,
256
+ implicitly_returns_nil: dsl.implicitly_returns_nil
247
257
  )
248
258
 
249
259
  dsl.groups.each do
@@ -10,8 +10,9 @@ module Steep
10
10
  attr_reader :project
11
11
  attr_reader :unreferenced
12
12
  attr_reader :groups
13
+ attr_reader :implicitly_returns_nil
13
14
 
14
- def initialize(name:, options:, source_pattern:, signature_pattern:, code_diagnostics_config:, project:, unreferenced:)
15
+ def initialize(name:, options:, source_pattern:, signature_pattern:, code_diagnostics_config:, project:, unreferenced:, implicitly_returns_nil:)
15
16
  @name = name
16
17
  @target_options = options
17
18
  @source_pattern = source_pattern
@@ -20,6 +21,7 @@ module Steep
20
21
  @project = project
21
22
  @unreferenced = unreferenced
22
23
  @groups = []
24
+ @implicitly_returns_nil = implicitly_returns_nil
23
25
  end
24
26
 
25
27
  def options
@@ -46,7 +46,7 @@ module Steep
46
46
 
47
47
  changes[path] ||= []
48
48
  request[:params][:contentChanges].each do |change|
49
- changes[path] << Services::ContentChange.new(
49
+ changes.fetch(path) << Services::ContentChange.new(
50
50
  range: change[:range]&.yield_self {|range|
51
51
  [
52
52
  range[:start].yield_self {|pos| Services::ContentChange::Position.new(line: pos[:line] + 1, column: pos[:character]) },
@@ -156,7 +156,7 @@ module Steep
156
156
  case
157
157
  when target = project.target_for_source_path(job.path)
158
158
  file = service.source_files[job.path] or return
159
- subtyping = service.signature_services[target.name].current_subtyping or return
159
+ subtyping = service.signature_services.fetch(target.name).current_subtyping or return
160
160
 
161
161
  provider = Services::CompletionProvider.new(source_text: file.content, path: job.path, subtyping: subtyping)
162
162
  items = begin
@@ -184,12 +184,12 @@ module Steep
184
184
  case sig_service.status
185
185
  when Services::SignatureService::SyntaxErrorStatus, Services::SignatureService::AncestorErrorStatus
186
186
  if buffer = sig_service.latest_env.buffers.find {|buf| Pathname(buf.name) == Pathname(relative_path) }
187
- dirs = sig_service.latest_env.signatures[buffer][0]
187
+ dirs = sig_service.latest_env.signatures.fetch(buffer)[0]
188
188
  else
189
189
  dirs = [] #: Array[RBS::AST::Directives::t]
190
190
  end
191
191
  else
192
- signature = sig_service.files[relative_path].signature
192
+ signature = sig_service.files.fetch(relative_path).signature
193
193
  signature.is_a?(Array) or raise
194
194
  buffer, dirs, decls = signature
195
195
 
@@ -210,7 +210,7 @@ module Steep
210
210
  end
211
211
  end
212
212
 
213
- buffer = RBS::Buffer.new(name: relative_path, content: sig_service.files[relative_path].content)
213
+ buffer = RBS::Buffer.new(name: relative_path, content: sig_service.files.fetch(relative_path).content)
214
214
  prefix = Services::TypeNameCompletion::Prefix.parse(buffer, line: job.line, column: job.column)
215
215
 
216
216
  completion = Services::TypeNameCompletion.new(env: sig_service.latest_env, context: context, dirs: dirs)
@@ -451,7 +451,7 @@ module Steep
451
451
  Steep.logger.tagged("##{__method__}") do
452
452
  if target = project.target_for_source_path(job.path)
453
453
  file = service.source_files[job.path] or return
454
- subtyping = service.signature_services[target.name].current_subtyping or return
454
+ subtyping = service.signature_services.fetch(target.name).current_subtyping or return
455
455
  source =
456
456
  Source.parse(file.content, path: file.path, factory: subtyping.factory)
457
457
  .without_unrelated_defs(line: job.line, column: job.column)
@@ -178,7 +178,6 @@ module Steep
178
178
  attr_reader :job_queue, :write_queue
179
179
 
180
180
  attr_reader :current_type_check_request
181
- attr_reader :current_diagnostics
182
181
  attr_reader :controller
183
182
  attr_reader :result_controller
184
183
 
@@ -197,7 +196,6 @@ module Steep
197
196
  @commandline_args = []
198
197
  @job_queue = queue
199
198
  @write_queue = SizedQueue.new(100)
200
- @current_diagnostics = {}
201
199
 
202
200
  @controller = TypeCheckController.new(project: project)
203
201
  @result_controller = ResultController.new()
@@ -802,15 +800,7 @@ module Steep
802
800
  Steep.logger.info "Starting new progress..."
803
801
 
804
802
  @current_type_check_request = request
805
- if last_request
806
- checking_paths = request.each_path.to_set
807
- current_diagnostics.keep_if do |path, _|
808
- checking_paths.include?(path)
809
- end
810
- else
811
- current_diagnostics.clear
812
- end
813
-
803
+
814
804
  if progress
815
805
  # If `request:` keyword arg is not given
816
806
  request.work_done_progress.begin("Type checking", request_id: fresh_request_id)
@@ -909,15 +899,10 @@ module Steep
909
899
 
910
900
  def push_diagnostics(path, diagnostics)
911
901
  if diagnostics
912
- ds = (current_diagnostics[path] ||= [])
913
-
914
- ds.concat(diagnostics)
915
- ds.uniq!
916
-
917
902
  write_queue.push SendMessageJob.to_client(
918
903
  message: {
919
904
  method: :"textDocument/publishDiagnostics",
920
- params: { uri: Steep::PathHelper.to_uri(path).to_s, diagnostics: ds }
905
+ params: { uri: Steep::PathHelper.to_uri(path).to_s, diagnostics: diagnostics }
921
906
  }
922
907
  )
923
908
  end
@@ -185,7 +185,7 @@ module Steep
185
185
  loader = Services::FileLoader.new(base_dir: project.base_dir)
186
186
 
187
187
  project.targets.each do |target|
188
- signature_service = Services::SignatureService.load_from(target.new_env_loader())
188
+ signature_service = Services::SignatureService.load_from(target.new_env_loader(), implicitly_returns_nil: target.implicitly_returns_nil)
189
189
  files.add_library_path(target, *signature_service.env_rbs_paths.to_a)
190
190
  end
191
191
 
@@ -266,7 +266,7 @@ module Steep
266
266
  request.code_paths << [target_group.name, path]
267
267
  end
268
268
  else
269
- group_set = groups.map do |group_name|
269
+ group_set = groups.filter_map do |group_name|
270
270
  target_name, group_name = group_name.split(".", 2)
271
271
  target_name or raise
272
272
 
@@ -280,7 +280,7 @@ module Steep
280
280
  else
281
281
  project.targets.find {|target| target.name == target_name }
282
282
  end
283
- end.compact.to_set
283
+ end.to_set
284
284
 
285
285
  files.signature_paths.each do |path, target_group|
286
286
  if group_set.include?(target_group)
@@ -223,7 +223,7 @@ module Steep
223
223
  Steep.measure "Generating workspace symbol list for query=`#{query}`" do
224
224
  provider = Index::SignatureSymbolProvider.new(project: project, assignment: assignment)
225
225
  project.targets.each do |target|
226
- index = service.signature_services[target.name].latest_rbs_index
226
+ index = service.signature_services.fetch(target.name).latest_rbs_index
227
227
  provider.indexes[target] = index
228
228
  end
229
229
 
@@ -105,9 +105,9 @@ module Steep
105
105
  def decl
106
106
  case
107
107
  when absolute_type_name.interface?
108
- env.interface_decls[absolute_type_name].decl
108
+ env.interface_decls.fetch(absolute_type_name).decl
109
109
  when absolute_type_name.alias?
110
- env.type_alias_decls[absolute_type_name].decl
110
+ env.type_alias_decls.fetch(absolute_type_name).decl
111
111
  when absolute_type_name.class?
112
112
  case entry = env.module_class_entry(absolute_type_name)
113
113
  when RBS::Environment::ClassEntry, RBS::Environment::ModuleEntry
@@ -127,11 +127,11 @@ module Steep
127
127
 
128
128
  case
129
129
  when absolute_type_name.interface?
130
- if comment = env.interface_decls[absolute_type_name].decl.comment
130
+ if comment = env.interface_decls.fetch(absolute_type_name).decl.comment
131
131
  comments << comment
132
132
  end
133
133
  when absolute_type_name.alias?
134
- if comment = env.type_alias_decls[absolute_type_name].decl.comment
134
+ if comment = env.type_alias_decls.fetch(absolute_type_name).decl.comment
135
135
  comments << comment
136
136
  end
137
137
  when absolute_type_name.class?
@@ -97,7 +97,7 @@ module Steep
97
97
  relative_path = project.relative_path(path)
98
98
 
99
99
  target = type_check.project.target_for_path(relative_path) or return []
100
- source = type_check.source_files[relative_path]
100
+ source = type_check.source_files.fetch(relative_path)
101
101
  typing, signature = type_check_path(target: target, path: relative_path, content: source.content, line: line, column: column)
102
102
 
103
103
  typing or return []
@@ -163,7 +163,7 @@ module Steep
163
163
 
164
164
  case
165
165
  when target = type_check.project.target_for_source_path(relative_path)
166
- source = type_check.source_files[relative_path] or return []
166
+ source = type_check.source_files.fetch(relative_path, nil) or return []
167
167
  typing, _signature = type_check_path(target: target, path: relative_path, content: source.content, line: line, column: column)
168
168
  if typing
169
169
  node, *parents = typing.source.find_nodes(line: line, column: column)
@@ -284,7 +284,7 @@ module Steep
284
284
  end
285
285
 
286
286
  def type_check_path(target:, path:, content:, line:, column:)
287
- signature_service = type_check.signature_services[target.name]
287
+ signature_service = type_check.signature_services.fetch(target.name)
288
288
  subtyping = signature_service.current_subtyping or return
289
289
  source = Source.parse(content, path: path, factory: subtyping.factory)
290
290
  source = source.without_unrelated_defs(line: line, column: column)
@@ -17,7 +17,7 @@ module Steep
17
17
  end
18
18
 
19
19
  def content_for(target:, path:, line:, column:)
20
- service = self.service.signature_services[target.name]
20
+ service = self.service.signature_services.fetch(target.name)
21
21
 
22
22
  env = service.latest_env
23
23
  buffer = env.buffers.find {|buf| buf.name.to_s == path.to_s } or return
@@ -65,14 +65,14 @@ module Steep
65
65
  def method_definition_for(factory, type_name, singleton_method: nil, instance_method: nil)
66
66
  case
67
67
  when instance_method
68
- factory.definition_builder.build_instance(type_name).methods[instance_method]
68
+ factory.definition_builder.build_instance(type_name).methods.fetch(instance_method)
69
69
  when singleton_method
70
70
  methods = factory.definition_builder.build_singleton(type_name).methods
71
71
 
72
72
  if singleton_method == :new
73
- methods[:new] || methods[:initialize]
73
+ methods[:new] || methods.fetch(:initialize)
74
74
  else
75
- methods[singleton_method]
75
+ methods.fetch(singleton_method)
76
76
  end
77
77
  else
78
78
  raise "One of the instance_method or singleton_method is required"
@@ -80,7 +80,7 @@ module Steep
80
80
  end
81
81
 
82
82
  def typecheck(target, path:, content:, line:, column:)
83
- subtyping = service.signature_services[target.name].current_subtyping or return
83
+ subtyping = service.signature_services.fetch(target.name).current_subtyping or return
84
84
  source = Source.parse(content, path: path, factory: subtyping.factory)
85
85
  source = source.without_unrelated_defs(line: line, column: column)
86
86
  resolver = ::RBS::Resolver::ConstantResolver.new(builder: subtyping.factory.definition_builder)
@@ -145,8 +145,8 @@ module Steep
145
145
  result_node =
146
146
  case parents[0]&.type
147
147
  when :block, :numblock
148
- if node == parents[0].children[0]
149
- parents[0]
148
+ if node == parents.fetch(0).children[0]
149
+ parents.fetch(0)
150
150
  else
151
151
  node
152
152
  end
@@ -145,13 +145,13 @@ module Steep
145
145
  # Cursor is not on the argument (maybe on comma after argument)
146
146
  return 0 if last_argument_nodes.nil? # No arguments
147
147
 
148
- case last_argument_nodes[-2].type
148
+ case last_argument_nodes.fetch(-2).type
149
149
  when :splat
150
150
  method_type.type.required_positionals.size + method_type.type.optional_positionals.size + 1 if method_type.type.rest_positionals
151
151
  when :kwargs
152
- case last_argument_nodes[-3].type
152
+ case last_argument_nodes.fetch(-3).type
153
153
  when :pair
154
- argname = last_argument_nodes[-3].children.first.children.first
154
+ argname = last_argument_nodes.fetch(-3).children.first.children.first
155
155
  if method_type.type.required_keywords.key?(argname)
156
156
  positionals + method_type.type.required_keywords.keys.index(argname).to_i + 1
157
157
  elsif method_type.type.optional_keywords.key?(argname)
@@ -163,7 +163,7 @@ module Steep
163
163
  positionals + method_type.type.required_keywords.size + method_type.type.optional_keywords.size if method_type.type.rest_keywords
164
164
  end
165
165
  else
166
- pos = (node.children[2...] || raise).index { |c| c.location == last_argument_nodes[-2].location }.to_i
166
+ pos = (node.children[2...] || raise).index { |c| c.location == last_argument_nodes.fetch(-2).location }.to_i
167
167
  if method_type.type.rest_positionals
168
168
  [pos + 1, positionals - 1].min
169
169
  else
@@ -172,14 +172,14 @@ module Steep
172
172
  end
173
173
  else
174
174
  # Cursor is on the argument
175
- case argument_nodes[-2].type
175
+ case argument_nodes.fetch(-2).type
176
176
  when :splat
177
177
  method_type.type.required_positionals.size + method_type.type.optional_positionals.size if method_type.type.rest_positionals
178
178
  when :kwargs
179
179
  if argument_nodes[-3]
180
- case argument_nodes[-3].type
180
+ case argument_nodes.fetch(-3).type
181
181
  when :pair
182
- argname = argument_nodes[-3].children.first.children.first
182
+ argname = argument_nodes.fetch(-3).children.first.children.first
183
183
  if method_type.type.required_keywords.key?(argname)
184
184
  positionals + method_type.type.required_keywords.keys.index(argname).to_i
185
185
  elsif method_type.type.optional_keywords.key?(argname)
@@ -192,7 +192,7 @@ module Steep
192
192
  end
193
193
  end
194
194
  else
195
- pos = (node.children[2...] || raise).index { |c| c.location == argument_nodes[-2].location }.to_i
195
+ pos = (node.children[2...] || raise).index { |c| c.location == argument_nodes.fetch(-2).location }.to_i
196
196
  [pos, positionals - 1].min
197
197
  end
198
198
  end
@@ -48,17 +48,18 @@ module Steep
48
48
  end
49
49
 
50
50
  class LoadedStatus
51
- attr_reader :files, :builder
51
+ attr_reader :files, :builder, :implicitly_returns_nil
52
52
 
53
- def initialize(files:, builder:)
53
+ def initialize(files:, builder:, implicitly_returns_nil:)
54
54
  @files = files
55
55
  @builder = builder
56
+ @implicitly_returns_nil = implicitly_returns_nil
56
57
  end
57
58
 
58
59
  def subtyping
59
60
  @subtyping ||= begin
60
61
  factory = AST::Types::Factory.new(builder: builder)
61
- interface_builder = Interface::Builder.new(factory)
62
+ interface_builder = Interface::Builder.new(factory, implicitly_returns_nil: implicitly_returns_nil)
62
63
  Subtyping::Check.new(builder: interface_builder)
63
64
  end
64
65
  end
@@ -77,14 +78,17 @@ module Steep
77
78
 
78
79
  FileStatus = _ = Struct.new(:path, :content, :signature, keyword_init: true)
79
80
 
80
- def initialize(env:)
81
+ attr_reader :implicitly_returns_nil
82
+
83
+ def initialize(env:, implicitly_returns_nil:)
81
84
  builder = RBS::DefinitionBuilder.new(env: env)
82
- @status = LoadedStatus.new(builder: builder, files: {})
85
+ @status = LoadedStatus.new(builder: builder, files: {}, implicitly_returns_nil: implicitly_returns_nil)
86
+ @implicitly_returns_nil = implicitly_returns_nil
83
87
  end
84
88
 
85
- def self.load_from(loader)
89
+ def self.load_from(loader, implicitly_returns_nil:)
86
90
  env = RBS::Environment.from_loader(loader).resolve_type_names
87
- new(env: env)
91
+ new(env: env, implicitly_returns_nil: implicitly_returns_nil)
88
92
  end
89
93
 
90
94
  def env_rbs_paths
@@ -222,7 +226,7 @@ module Steep
222
226
  )
223
227
  when RBS::DefinitionBuilder::AncestorBuilder
224
228
  builder2 = update_builder(ancestor_builder: result, paths: paths)
225
- LoadedStatus.new(builder: builder2, files: files)
229
+ LoadedStatus.new(builder: builder2, files: files, implicitly_returns_nil: implicitly_returns_nil)
226
230
  end
227
231
  end
228
232
  end
@@ -82,7 +82,7 @@ module Steep
82
82
  @source_files = {}
83
83
  @signature_services = project.targets.each.with_object({}) do |target, hash| #$ Hash[Symbol, SignatureService]
84
84
  loader = Project::Target.construct_env_loader(options: target.options, project: project)
85
- hash[target.name] = SignatureService.load_from(loader)
85
+ hash[target.name] = SignatureService.load_from(loader, implicitly_returns_nil: target.implicitly_returns_nil)
86
86
  end
87
87
  @signature_validation_diagnostics = project.targets.each.with_object({}) do |target, hash| #$ Hash[Symbol, Hash[Pathname, Array[Diagnostic::Signature::Base]]]
88
88
  hash[target.name] = {}
@@ -94,7 +94,7 @@ module Steep
94
94
  signature_diagnostics = {}
95
95
 
96
96
  project.targets.each do |target|
97
- service = signature_services[target.name]
97
+ service = signature_services.fetch(target.name)
98
98
 
99
99
  service.each_rbs_path do |path|
100
100
  signature_diagnostics[path] ||= []
@@ -105,13 +105,13 @@ module Steep
105
105
  service.status.diagnostics.group_by {|diag| diag.location&.buffer&.name&.to_s }.each do |path_string, diagnostics|
106
106
  if path_string
107
107
  path = Pathname(path_string)
108
- signature_diagnostics[path].push(*diagnostics)
108
+ signature_diagnostics.fetch(path).push(*diagnostics)
109
109
  end
110
110
  end
111
111
  when SignatureService::LoadedStatus
112
112
  validation_diagnostics = signature_validation_diagnostics[target.name] || {}
113
113
  validation_diagnostics.each do |path, diagnostics|
114
- signature_diagnostics[path].push(*diagnostics)
114
+ signature_diagnostics.fetch(path).push(*diagnostics)
115
115
  end
116
116
  end
117
117
  end
@@ -154,7 +154,7 @@ module Steep
154
154
  def validate_signature(path:, target:)
155
155
  Steep.logger.tagged "#validate_signature(path=#{path})" do
156
156
  Steep.measure "validation" do
157
- service = signature_services[target.name]
157
+ service = signature_services.fetch(target.name)
158
158
 
159
159
  raise "#{path} is not library nor signature of #{target.name}" unless target.possible_signature_file?(path) || service.env_rbs_paths.include?(path)
160
160
 
@@ -221,7 +221,7 @@ module Steep
221
221
  end
222
222
  end
223
223
 
224
- signature_validation_diagnostics[target.name][path] = diagnostics
224
+ signature_validation_diagnostics.fetch(target.name)[path] = diagnostics
225
225
  end
226
226
  end
227
227
  end
@@ -231,11 +231,11 @@ module Steep
231
231
 
232
232
  Steep.logger.tagged "#typecheck_source(path=#{path})" do
233
233
  Steep.measure "typecheck" do
234
- signature_service = signature_services[target.name]
234
+ signature_service = signature_services.fetch(target.name)
235
235
  subtyping = signature_service.current_subtyping
236
236
 
237
237
  if subtyping
238
- text = source_files[path].content
238
+ text = source_files.fetch(path).content
239
239
  file = type_check_file(target: target, subtyping: subtyping, path: path, text: text) { signature_service.latest_constant_resolver }
240
240
  source_files[path] = file
241
241
 
@@ -287,7 +287,7 @@ module Steep
287
287
  SourceFile.with_typing(path: path, content: text, node: source.node, typing: typing, ignores: ignores)
288
288
  end
289
289
  rescue AnnotationParser::SyntaxError => exn
290
- error = Diagnostic::Ruby::SyntaxError.new(message: exn.message, location: exn.location)
290
+ error = Diagnostic::Ruby::AnnotationSyntaxError.new(message: exn.message, location: exn.location)
291
291
  SourceFile.with_syntax_error(path: path, content: text, error: error)
292
292
  rescue ::Parser::SyntaxError => exn
293
293
  error = Diagnostic::Ruby::SyntaxError.new(message: exn.message, location: (_ = exn).diagnostic.location)
@@ -130,7 +130,7 @@ module Steep
130
130
  ]
131
131
  when RBS::Types::Alias
132
132
  type_name = env.normalize_type_name?(type.name) or return
133
- entry = env.type_alias_decls[type_name]
133
+ entry = env.type_alias_decls.fetch(type_name)
134
134
 
135
135
  [
136
136
  type_name,
@@ -485,7 +485,7 @@ module Steep
485
485
  location =
486
486
  case ancestor.source
487
487
  when :super
488
- primary_decl = env.class_decls[name].primary.decl
488
+ primary_decl = env.class_decls.fetch(name).primary.decl
489
489
  primary_decl.is_a?(RBS::AST::Declarations::Class) or raise
490
490
  if super_class = primary_decl.super_class
491
491
  super_class.location
@@ -594,7 +594,7 @@ module Steep
594
594
  end
595
595
  end
596
596
 
597
- def validate_one_alias(name, entry = env.type_alias_decls[name])
597
+ def validate_one_alias(name, entry = env.type_alias_decls.fetch(name))
598
598
  *, inner_most_outer_module = entry.outer
599
599
  if inner_most_outer_module
600
600
  class_type = AST::Types::Name::Singleton.new(name: inner_most_outer_module.name)
data/lib/steep/source.rb CHANGED
@@ -88,7 +88,7 @@ module Steep
88
88
 
89
89
  annotations.each do |annot|
90
90
  map[node] ||= []
91
- map[node] << annot
91
+ map.fetch(node) << annot
92
92
  end
93
93
 
94
94
  ignores = comments.filter_map do |comment|
@@ -269,7 +269,7 @@ module Steep
269
269
 
270
270
  associated_annotations.each do |annot|
271
271
  mapping[node] ||= []
272
- mapping[node] << annot
272
+ mapping.fetch(node) << annot
273
273
  end
274
274
 
275
275
  annotations.replace(other_annotations)
@@ -379,7 +379,7 @@ module Steep
379
379
  position = buffer.loc_to_pos([line, column])
380
380
 
381
381
  if heredoc_nodes = find_heredoc_nodes(line, column, position)
382
- Source.each_child_node(heredoc_nodes[0]) do |child|
382
+ Source.each_child_node(heredoc_nodes.fetch(0)) do |child|
383
383
  if nodes = find_nodes_loc(child, position, heredoc_nodes)
384
384
  return nodes
385
385
  end
@@ -442,7 +442,7 @@ module Steep
442
442
 
443
443
  annotations.each do |annot|
444
444
  mapping[node_] ||= []
445
- mapping[node_] << annot
445
+ mapping.fetch(node_) << annot
446
446
  end
447
447
 
448
448
  Source.new(buffer: buffer, path: path, node: node_, mapping: mapping, comments: comments, ignores: ignores)
@@ -515,7 +515,7 @@ module Steep
515
515
  types: relation.sub_type.types
516
516
  )
517
517
 
518
- check_type(Relation.new(sub_type: tuple_element_type, super_type: super_type.args[0]))
518
+ check_type(Relation.new(sub_type: tuple_element_type, super_type: super_type.args.fetch(0)))
519
519
  end
520
520
 
521
521
  when relation.sub_type.is_a?(AST::Types::Tuple)
@@ -1057,10 +1057,10 @@ module Steep
1057
1057
 
1058
1058
  sup_flat_kws.each do |name, _|
1059
1059
  if sub_flat_kws.key?(name)
1060
- pairs << [sub_flat_kws[name], sup_flat_kws[name]]
1060
+ pairs << [sub_flat_kws.fetch(name), sup_flat_kws.fetch(name)]
1061
1061
  else
1062
1062
  if sub_params.rest_keywords
1063
- pairs << [sub_params.rest_keywords, sup_flat_kws[name]]
1063
+ pairs << [sub_params.rest_keywords, sup_flat_kws.fetch(name)]
1064
1064
  else
1065
1065
  return failure
1066
1066
  end
@@ -102,7 +102,7 @@ module Steep
102
102
  end
103
103
 
104
104
  def add(var, sub_type: nil, super_type: nil, skip: false)
105
- subs, supers, skips = dictionary[var]
105
+ subs, supers, skips = dictionary.fetch(var)
106
106
 
107
107
  if sub_type.is_a?(AST::Types::Logic::Base)
108
108
  sub_type = AST::Builtin.bool_type
@@ -204,7 +204,7 @@ module Steep
204
204
  if skip
205
205
  upper_bound = upper_bound_types(var)
206
206
  else
207
- _, upper_bound, _ = dictionary[var]
207
+ _, upper_bound, _ = dictionary.fetch(var)
208
208
  end
209
209
 
210
210
  case upper_bound.size
@@ -320,12 +320,12 @@ module Steep
320
320
  end
321
321
 
322
322
  def lower_bound_types(var_name)
323
- lower, _, _ = dictionary[var_name]
323
+ lower, _, _ = dictionary.fetch(var_name)
324
324
  lower
325
325
  end
326
326
 
327
327
  def upper_bound_types(var_name)
328
- _, upper, skips = dictionary[var_name]
328
+ _, upper, skips = dictionary.fetch(var_name)
329
329
 
330
330
  case
331
331
  when upper.empty?