dependabot-bundler 0.333.0 → 0.335.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 (25) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/v2/lib/functions/force_updater.rb +7 -2
  3. data/helpers/v2/lib/functions/version_resolver.rb +6 -2
  4. data/helpers/v2/spec/functions/conflicting_dependency_resolver_spec.rb +64 -52
  5. data/helpers/v2/spec/functions/dependency_source_spec.rb +14 -10
  6. data/helpers/v2/spec/functions/version_resolver_spec.rb +4 -2
  7. data/lib/dependabot/bundler/file_fetcher.rb +12 -6
  8. data/lib/dependabot/bundler/file_parser.rb +4 -2
  9. data/lib/dependabot/bundler/file_updater/gemspec_updater.rb +13 -6
  10. data/lib/dependabot/bundler/file_updater/git_pin_replacer.rb +27 -6
  11. data/lib/dependabot/bundler/file_updater/git_source_remover.rb +14 -2
  12. data/lib/dependabot/bundler/file_updater/lockfile_updater.rb +90 -26
  13. data/lib/dependabot/bundler/file_updater/requirement_replacer.rb +92 -17
  14. data/lib/dependabot/bundler/file_updater.rb +48 -19
  15. data/lib/dependabot/bundler/metadata_finder.rb +61 -30
  16. data/lib/dependabot/bundler/package/package_details_fetcher.rb +60 -2
  17. data/lib/dependabot/bundler/requirement.rb +3 -2
  18. data/lib/dependabot/bundler/update_checker/file_preparer.rb +81 -25
  19. data/lib/dependabot/bundler/update_checker/force_updater.rb +11 -5
  20. data/lib/dependabot/bundler/update_checker/latest_version_finder/dependency_source.rb +53 -15
  21. data/lib/dependabot/bundler/update_checker/latest_version_finder.rb +4 -2
  22. data/lib/dependabot/bundler/update_checker/requirements_updater.rb +92 -31
  23. data/lib/dependabot/bundler/update_checker/version_resolver.rb +14 -7
  24. data/lib/dependabot/bundler/update_checker.rb +14 -7
  25. metadata +12 -12
@@ -1,7 +1,8 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "bundler"
5
+ require "sorbet-runtime"
5
6
 
6
7
  require "dependabot/shared_helpers"
7
8
  require "dependabot/errors"
@@ -14,6 +15,8 @@ module Dependabot
14
15
  module Bundler
15
16
  class FileUpdater
16
17
  class LockfileUpdater
18
+ extend T::Sig
19
+
17
20
  require_relative "gemfile_updater"
18
21
  require_relative "gemspec_updater"
19
22
  require_relative "gemspec_sanitizer"
@@ -24,8 +27,37 @@ module Dependabot
24
27
  GIT_DEPENDENCIES_SECTION = /GIT\n.*?\n\n(?!GIT)/m
25
28
  GIT_DEPENDENCY_DETAILS = /GIT\n.*?\n\n/m
26
29
 
30
+ sig do
31
+ params(
32
+ dependencies: T::Array[Dependabot::Dependency],
33
+ dependency_files: T::Array[Dependabot::DependencyFile],
34
+ credentials: T::Array[Dependabot::Credential],
35
+ options: T::Hash[Symbol, T.untyped],
36
+ repo_contents_path: T.nilable(String)
37
+ ).void
38
+ end
39
+ def initialize(
40
+ dependencies:,
41
+ dependency_files:,
42
+ credentials:,
43
+ options:,
44
+ repo_contents_path: nil
45
+ )
46
+ @dependencies = T.let(dependencies, T::Array[Dependabot::Dependency])
47
+ @dependency_files = T.let(dependency_files, T::Array[Dependabot::DependencyFile])
48
+ @repo_contents_path = T.let(repo_contents_path, T.nilable(String))
49
+ @credentials = T.let(credentials, T::Array[Dependabot::Credential])
50
+ @options = T.let(options, T::Hash[Symbol, T.untyped])
51
+ @updated_lockfile_content = T.let(nil, T.nilable(String))
52
+ @gemfile = T.let(nil, T.nilable(Dependabot::DependencyFile))
53
+ @lockfile = T.let(nil, T.nilable(Dependabot::DependencyFile))
54
+ @evaled_gemfiles = T.let(nil, T.nilable(T::Array[Dependabot::DependencyFile]))
55
+ @bundler_version = T.let(nil, T.nilable(String))
56
+ end
57
+
27
58
  # Can't be a constant because some of these don't exist in bundler
28
59
  # 1.15, which Heroku uses, which causes an exception on boot.
60
+ sig { returns(T::Array[T.class_of(::Bundler::Source::Path)]) }
29
61
  def gemspec_sources
30
62
  [
31
63
  ::Bundler::Source::Path,
@@ -33,21 +65,13 @@ module Dependabot
33
65
  ]
34
66
  end
35
67
 
36
- def initialize(dependencies:, dependency_files:,
37
- repo_contents_path: nil, credentials:, options:)
38
- @dependencies = dependencies
39
- @dependency_files = dependency_files
40
- @repo_contents_path = repo_contents_path
41
- @credentials = credentials
42
- @options = options
43
- end
44
-
68
+ sig { returns(String) }
45
69
  def updated_lockfile_content
46
70
  @updated_lockfile_content ||=
47
71
  begin
48
72
  updated_content = build_updated_lockfile
49
73
 
50
- raise "Expected content to change!" if lockfile.content == updated_content
74
+ raise "Expected content to change!" if T.must(lockfile).content == updated_content
51
75
 
52
76
  updated_content
53
77
  end
@@ -55,14 +79,24 @@ module Dependabot
55
79
 
56
80
  private
57
81
 
82
+ sig { returns(T::Array[Dependabot::Dependency]) }
58
83
  attr_reader :dependencies
84
+
85
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
59
86
  attr_reader :dependency_files
87
+
88
+ sig { returns(T.nilable(String)) }
60
89
  attr_reader :repo_contents_path
90
+
91
+ sig { returns(T::Array[Dependabot::Credential]) }
61
92
  attr_reader :credentials
93
+
94
+ sig { returns(T::Hash[Symbol, T.untyped]) }
62
95
  attr_reader :options
63
96
 
97
+ sig { returns(String) }
64
98
  def build_updated_lockfile
65
- base_dir = dependency_files.first.directory
99
+ base_dir = T.must(dependency_files.first).directory
66
100
  lockfile_body =
67
101
  SharedHelpers.in_a_temporary_repo_directory(
68
102
  base_dir,
@@ -75,8 +109,8 @@ module Dependabot
75
109
  function: "update_lockfile",
76
110
  options: options,
77
111
  args: {
78
- gemfile_name: gemfile.name,
79
- lockfile_name: lockfile.name,
112
+ gemfile_name: T.must(gemfile).name,
113
+ lockfile_name: T.must(lockfile).name,
80
114
  dir: tmp_dir,
81
115
  credentials: credentials,
82
116
  dependencies: dependencies.map(&:to_h)
@@ -90,9 +124,10 @@ module Dependabot
90
124
  raise
91
125
  end
92
126
 
127
+ sig { void }
93
128
  def write_temporary_dependency_files
94
- File.write(gemfile.name, prepared_gemfile_content(gemfile))
95
- File.write(lockfile.name, sanitized_lockfile_body)
129
+ File.write(T.must(gemfile).name, prepared_gemfile_content(T.must(gemfile)))
130
+ File.write(T.must(lockfile).name, sanitized_lockfile_body)
96
131
 
97
132
  write_gemspecs(top_level_gemspecs)
98
133
  write_ruby_version_file
@@ -108,22 +143,25 @@ module Dependabot
108
143
  end
109
144
  end
110
145
 
146
+ sig { void }
111
147
  def write_ruby_version_file
112
148
  return unless ruby_version_file
113
149
 
114
- path = ruby_version_file.name
150
+ path = T.must(ruby_version_file).name
115
151
  FileUtils.mkdir_p(Pathname.new(path).dirname)
116
- File.write(path, ruby_version_file.content)
152
+ File.write(path, T.must(ruby_version_file).content)
117
153
  end
118
154
 
155
+ sig { void }
119
156
  def write_tool_versions_file
120
157
  return unless tool_versions_file
121
158
 
122
- path = tool_versions_file.name
159
+ path = T.must(tool_versions_file).name
123
160
  FileUtils.mkdir_p(Pathname.new(path).dirname)
124
- File.write(path, tool_versions_file.content)
161
+ File.write(path, T.must(tool_versions_file).content)
125
162
  end
126
163
 
164
+ sig { params(files: T::Array[Dependabot::DependencyFile]).void }
127
165
  def write_gemspecs(files)
128
166
  files.each do |file|
129
167
  path = file.name
@@ -133,6 +171,7 @@ module Dependabot
133
171
  end
134
172
  end
135
173
 
174
+ sig { void }
136
175
  def write_specification_files
137
176
  specification_files.each do |file|
138
177
  path = file.name
@@ -141,6 +180,7 @@ module Dependabot
141
180
  end
142
181
  end
143
182
 
183
+ sig { void }
144
184
  def write_imported_ruby_files
145
185
  imported_ruby_files.each do |file|
146
186
  path = file.name
@@ -149,38 +189,46 @@ module Dependabot
149
189
  end
150
190
  end
151
191
 
192
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
152
193
  def path_gemspecs
153
194
  all = dependency_files.select { |f| f.name.end_with?(".gemspec") }
154
195
  all - top_level_gemspecs
155
196
  end
156
197
 
198
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
157
199
  def imported_ruby_files
158
200
  dependency_files
159
201
  .select { |f| f.name.end_with?(".rb") }
160
202
  .reject { |f| f.name == "gems.rb" }
161
203
  end
162
204
 
205
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
163
206
  def top_level_gemspecs
164
207
  dependency_files
165
208
  .select { |file| file.name.end_with?(".gemspec") && Pathname.new(file.name).dirname.to_s == "." }
166
209
  end
167
210
 
211
+ sig { returns(T.nilable(Dependabot::DependencyFile)) }
168
212
  def ruby_version_file
169
213
  dependency_files.find { |f| f.name == ".ruby-version" }
170
214
  end
171
215
 
216
+ sig { returns(T.nilable(Dependabot::DependencyFile)) }
172
217
  def tool_versions_file
173
218
  dependency_files.find { |f| f.name == ".tool-versions" }
174
219
  end
175
220
 
221
+ sig { params(lockfile_body: String).returns(String) }
176
222
  def post_process_lockfile(lockfile_body)
177
223
  lockfile_body = reorder_git_dependencies(lockfile_body)
178
224
  replace_lockfile_ending(lockfile_body)
179
225
  end
180
226
 
227
+ sig { params(lockfile_body: String).returns(String) }
181
228
  def reorder_git_dependencies(lockfile_body)
182
229
  new_section = lockfile_body.match(GIT_DEPENDENCIES_SECTION)&.to_s
183
- old_section = lockfile.content.match(GIT_DEPENDENCIES_SECTION)&.to_s
230
+ lockfile_content = T.must(lockfile).content
231
+ old_section = lockfile_content&.match(GIT_DEPENDENCIES_SECTION)&.to_s
184
232
 
185
233
  return lockfile_body unless new_section && old_section
186
234
 
@@ -190,8 +238,10 @@ module Dependabot
190
238
  return lockfile_body unless new_deps.count == old_deps.count
191
239
 
192
240
  reordered_new_section = new_deps.sort_by do |new_dep_details|
193
- remote = new_dep_details.match(/remote: (?<remote>.*\n)/)[:remote]
194
- i = old_deps.index { |details| details.include?(remote) }
241
+ dep_string = T.cast(new_dep_details, String)
242
+ match_result = dep_string.match(/remote: (?<remote>.*\n)/)
243
+ remote = match_result ? match_result[:remote] : ""
244
+ i = old_deps.index { |details| details.include?(T.must(remote)) }
195
245
 
196
246
  # If this dependency isn't in the old lockfile then we can't rely
197
247
  # on that (presumably outdated) lockfile to do reordering.
@@ -205,15 +255,18 @@ module Dependabot
205
255
  lockfile_body.gsub(new_section, reordered_new_section)
206
256
  end
207
257
 
258
+ sig { params(lockfile_body: String).returns(String) }
208
259
  def replace_lockfile_ending(lockfile_body)
209
260
  # Re-add the old `BUNDLED WITH` version (and remove the RUBY VERSION
210
261
  # if it wasn't previously present in the lockfile)
262
+ lockfile_content = T.must(lockfile).content
211
263
  lockfile_body.gsub(
212
264
  LOCKFILE_ENDING,
213
- lockfile.content.match(LOCKFILE_ENDING)&.[](:ending) || "\n"
265
+ lockfile_content&.match(LOCKFILE_ENDING)&.[](:ending) || "\n"
214
266
  )
215
267
  end
216
268
 
269
+ sig { params(path: String, gemspec_content: String).returns(String) }
217
270
  def sanitized_gemspec_content(path, gemspec_content)
218
271
  new_version = replacement_version_for_gemspec(path, gemspec_content)
219
272
 
@@ -222,6 +275,7 @@ module Dependabot
222
275
  .rewrite(gemspec_content)
223
276
  end
224
277
 
278
+ sig { params(path: String, gemspec_content: String).returns(String) }
225
279
  def replacement_version_for_gemspec(path, gemspec_content)
226
280
  return "0.0.1" unless lockfile
227
281
 
@@ -233,9 +287,10 @@ module Dependabot
233
287
  CachedLockfileParser.parse(sanitized_lockfile_body).specs
234
288
  .select { |s| s.name == gem_name && gemspec_sources.include?(s.source.class) }
235
289
 
236
- gemspec_specs.first&.version || "0.0.1"
290
+ gemspec_specs.first&.version&.to_s || "0.0.1"
237
291
  end
238
292
 
293
+ sig { params(file: Dependabot::DependencyFile).returns(String) }
239
294
  def prepared_gemfile_content(file)
240
295
  content = updated_gemfile_content(file)
241
296
 
@@ -246,6 +301,7 @@ module Dependabot
246
301
  content
247
302
  end
248
303
 
304
+ sig { params(file: Dependabot::DependencyFile).returns(String) }
249
305
  def updated_gemfile_content(file)
250
306
  GemfileUpdater.new(
251
307
  dependencies: dependencies,
@@ -253,6 +309,7 @@ module Dependabot
253
309
  ).updated_gemfile_content
254
310
  end
255
311
 
312
+ sig { params(gemspec: Dependabot::DependencyFile).returns(String) }
256
313
  def updated_gemspec_content(gemspec)
257
314
  GemspecUpdater.new(
258
315
  dependencies: dependencies,
@@ -260,11 +317,13 @@ module Dependabot
260
317
  ).updated_gemspec_content
261
318
  end
262
319
 
320
+ sig { returns(T.nilable(Dependabot::DependencyFile)) }
263
321
  def gemfile
264
322
  @gemfile ||= dependency_files.find { |f| f.name == "Gemfile" } ||
265
323
  dependency_files.find { |f| f.name == "gems.rb" }
266
324
  end
267
325
 
326
+ sig { returns(T.nilable(Dependabot::DependencyFile)) }
268
327
  def lockfile
269
328
  @lockfile ||=
270
329
  dependency_files.find { |f| f.name == "Gemfile.lock" } ||
@@ -272,10 +331,13 @@ module Dependabot
272
331
  end
273
332
 
274
333
  # TODO: Stop sanitizing the lockfile once we have bundler 2 installed
334
+ sig { returns(String) }
275
335
  def sanitized_lockfile_body
276
- lockfile.content.gsub(LOCKFILE_ENDING, "")
336
+ content = T.must(lockfile).content
337
+ T.must(content).gsub(LOCKFILE_ENDING, "")
277
338
  end
278
339
 
340
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
279
341
  def evaled_gemfiles
280
342
  @evaled_gemfiles ||=
281
343
  dependency_files
@@ -288,10 +350,12 @@ module Dependabot
288
350
  .reject(&:support_file?)
289
351
  end
290
352
 
353
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
291
354
  def specification_files
292
355
  dependency_files.select { |f| f.name.end_with?(".specification") }
293
356
  end
294
357
 
358
+ sig { returns(String) }
295
359
  def bundler_version
296
360
  @bundler_version ||= Helpers.bundler_version(lockfile)
297
361
  end
@@ -1,20 +1,45 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "parser/current"
5
+ require "sorbet-runtime"
6
+
5
7
  require "dependabot/bundler/file_updater"
6
8
 
7
9
  module Dependabot
8
10
  module Bundler
9
11
  class FileUpdater
10
12
  class RequirementReplacer
13
+ extend T::Sig
14
+
15
+ sig { returns(Dependabot::Dependency) }
11
16
  attr_reader :dependency
17
+
18
+ sig { returns(Symbol) }
12
19
  attr_reader :file_type
20
+
21
+ sig { returns(String) }
13
22
  attr_reader :updated_requirement
23
+
24
+ sig { returns(T.nilable(String)) }
14
25
  attr_reader :previous_requirement
15
26
 
16
- def initialize(dependency:, file_type:, updated_requirement:,
17
- previous_requirement: nil, insert_if_bare: false)
27
+ sig do
28
+ params(
29
+ dependency: Dependabot::Dependency,
30
+ file_type: Symbol,
31
+ updated_requirement: String,
32
+ previous_requirement: T.nilable(String),
33
+ insert_if_bare: T::Boolean
34
+ ).void
35
+ end
36
+ def initialize(
37
+ dependency:,
38
+ file_type:,
39
+ updated_requirement:,
40
+ previous_requirement: nil,
41
+ insert_if_bare: false
42
+ )
18
43
  @dependency = dependency
19
44
  @file_type = file_type
20
45
  @updated_requirement = updated_requirement
@@ -22,7 +47,10 @@ module Dependabot
22
47
  @insert_if_bare = insert_if_bare
23
48
  end
24
49
 
50
+ sig { params(content: T.nilable(String)).returns(String) }
25
51
  def rewrite(content)
52
+ return "" unless content
53
+
26
54
  buffer = Parser::Source::Buffer.new("(gemfile_content)")
27
55
  buffer.source = content
28
56
  ast = Parser::CurrentRuby.new.parse(buffer)
@@ -39,10 +67,12 @@ module Dependabot
39
67
 
40
68
  private
41
69
 
70
+ sig { returns(T::Boolean) }
42
71
  def insert_if_bare?
43
72
  @insert_if_bare
44
73
  end
45
74
 
75
+ sig { params(content: String, updated_content: String).returns(String) }
46
76
  def update_comment_spacing_if_required(content, updated_content)
47
77
  return updated_content unless previous_requirement
48
78
 
@@ -53,43 +83,66 @@ module Dependabot
53
83
  updated_line_index =
54
84
  updated_lines.length
55
85
  .times.find { |i| content.lines[i] != updated_content.lines[i] }
56
- updated_line = updated_lines[updated_line_index]
86
+ return updated_content unless updated_line_index
87
+
88
+ updated_line = T.must(updated_lines[updated_line_index])
57
89
 
58
90
  updated_line =
59
91
  if length_change.positive?
60
92
  updated_line.sub(/(?<=\s)\s{#{length_change}}#/, "#")
61
93
  elsif length_change.negative?
62
94
  updated_line.sub(/(?<=\s{2})#/, (" " * length_change.abs) + "#")
95
+ else
96
+ updated_line
63
97
  end
64
98
 
65
99
  updated_lines[updated_line_index] = updated_line
66
100
  updated_lines.join
67
101
  end
68
102
 
103
+ sig { returns(Integer) }
69
104
  def length_change
70
- return updated_requirement.length - previous_requirement.length unless previous_requirement.start_with?("=")
105
+ return 0 unless previous_requirement
106
+
107
+ prev_req = T.must(previous_requirement)
108
+ return updated_requirement.length - prev_req.length unless prev_req.start_with?("=")
71
109
 
72
110
  updated_requirement.length -
73
- previous_requirement.gsub(/^=/, "").strip.length
111
+ prev_req.gsub(/^=/, "").strip.length
74
112
  end
75
113
 
76
114
  class Rewriter < Parser::TreeRewriter
115
+ extend T::Sig
116
+
77
117
  # TODO: Ideally we wouldn't have to ignore all of these, but
78
118
  # implementing each one will be tricky.
79
- SKIPPED_TYPES = %i(send lvar dstr begin if case splat const or).freeze
80
-
81
- def initialize(dependency:, file_type:, updated_requirement:,
82
- insert_if_bare:)
83
- @dependency = dependency
84
- @file_type = file_type
85
- @updated_requirement = updated_requirement
86
- @insert_if_bare = insert_if_bare
119
+ SKIPPED_TYPES = T.let(%i(send lvar dstr begin if case splat const or).freeze, T::Array[Symbol])
120
+
121
+ sig do
122
+ params(
123
+ dependency: Dependabot::Dependency,
124
+ file_type: Symbol,
125
+ updated_requirement: String,
126
+ insert_if_bare: T::Boolean
127
+ ).void
128
+ end
129
+ def initialize(
130
+ dependency:,
131
+ file_type:,
132
+ updated_requirement:,
133
+ insert_if_bare:
134
+ )
135
+ @dependency = T.let(dependency, Dependabot::Dependency)
136
+ @file_type = T.let(file_type, Symbol)
137
+ @updated_requirement = T.let(updated_requirement, String)
138
+ @insert_if_bare = T.let(insert_if_bare, T::Boolean)
87
139
 
88
140
  return if %i(gemfile gemspec).include?(file_type)
89
141
 
90
142
  raise "File type must be :gemfile or :gemspec. Got #{file_type}."
91
143
  end
92
144
 
145
+ sig { params(node: T.untyped).void }
93
146
  def on_send(node)
94
147
  return unless declares_targeted_gem?(node)
95
148
 
@@ -117,14 +170,21 @@ module Dependabot
117
170
 
118
171
  private
119
172
 
173
+ sig { returns(Dependabot::Dependency) }
120
174
  attr_reader :dependency
175
+
176
+ sig { returns(Symbol) }
121
177
  attr_reader :file_type
178
+
179
+ sig { returns(String) }
122
180
  attr_reader :updated_requirement
123
181
 
182
+ sig { returns(T::Boolean) }
124
183
  def insert_if_bare?
125
184
  @insert_if_bare
126
185
  end
127
186
 
187
+ sig { returns(T::Array[Symbol]) }
128
188
  def declaration_methods
129
189
  return %i(gem) if file_type == :gemfile
130
190
 
@@ -132,12 +192,14 @@ module Dependabot
132
192
  add_development_dependency)
133
193
  end
134
194
 
195
+ sig { params(node: T.untyped).returns(T::Boolean) }
135
196
  def declares_targeted_gem?(node)
136
197
  return false unless declaration_methods.include?(node.children[1])
137
198
 
138
199
  node.children[2].children.first == dependency.name
139
200
  end
140
201
 
202
+ sig { params(requirement_nodes: T::Array[T.untyped]).returns([String, String]) }
141
203
  def extract_quote_characters_from(requirement_nodes)
142
204
  return ['"', '"'] if requirement_nodes.none?
143
205
 
@@ -155,6 +217,7 @@ module Dependabot
155
217
  end
156
218
  end
157
219
 
220
+ sig { params(requirement_nodes: T::Array[T.untyped]).returns(T::Boolean) }
158
221
  def space_after_specifier?(requirement_nodes)
159
222
  return true if requirement_nodes.none?
160
223
 
@@ -174,6 +237,7 @@ module Dependabot
174
237
 
175
238
  EQUALITY_OPERATOR = /(?<![<>!])=/
176
239
 
240
+ sig { params(requirement_nodes: T::Array[T.untyped]).returns(T::Boolean) }
177
241
  def use_equality_operator?(requirement_nodes)
178
242
  return true if requirement_nodes.none?
179
243
 
@@ -188,9 +252,18 @@ module Dependabot
188
252
  req_string.match?(EQUALITY_OPERATOR)
189
253
  end
190
254
 
191
- def new_requirement_string(quote_characters:,
192
- space_after_specifier:,
193
- use_equality_operator:)
255
+ sig do
256
+ params(
257
+ quote_characters: [String, String],
258
+ space_after_specifier: T::Boolean,
259
+ use_equality_operator: T::Boolean
260
+ ).returns(String)
261
+ end
262
+ def new_requirement_string(
263
+ quote_characters:,
264
+ space_after_specifier:,
265
+ use_equality_operator:
266
+ )
194
267
  open_quote, close_quote = quote_characters
195
268
  new_requirement_string =
196
269
  updated_requirement.split(",")
@@ -204,6 +277,7 @@ module Dependabot
204
277
  new_requirement_string
205
278
  end
206
279
 
280
+ sig { params(req: String, use_equality_operator: T::Boolean).returns(String) }
207
281
  def serialized_req(req, use_equality_operator)
208
282
  tmp_req = req
209
283
 
@@ -215,6 +289,7 @@ module Dependabot
215
289
  tmp_req.strip
216
290
  end
217
291
 
292
+ sig { params(nodes: T::Array[T.untyped]).returns(T.untyped) }
218
293
  def range_for(nodes)
219
294
  nodes.first.loc.begin.begin.join(nodes.last.loc.expression)
220
295
  end