dependabot-nuget 0.247.0 → 0.249.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 (28) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs +57 -0
  3. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/SdkPackageUpdater.cs +1 -1
  4. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +25 -5
  5. data/lib/dependabot/nuget/file_fetcher/import_paths_finder.rb +1 -0
  6. data/lib/dependabot/nuget/file_fetcher/sln_project_paths_finder.rb +2 -0
  7. data/lib/dependabot/nuget/file_fetcher.rb +12 -8
  8. data/lib/dependabot/nuget/file_parser/dotnet_tools_json_parser.rb +1 -0
  9. data/lib/dependabot/nuget/file_parser/global_json_parser.rb +1 -0
  10. data/lib/dependabot/nuget/file_parser/packages_config_parser.rb +1 -0
  11. data/lib/dependabot/nuget/file_parser/project_file_parser.rb +1 -0
  12. data/lib/dependabot/nuget/file_parser/property_value_finder.rb +2 -0
  13. data/lib/dependabot/nuget/file_parser.rb +42 -11
  14. data/lib/dependabot/nuget/file_updater/property_value_updater.rb +1 -0
  15. data/lib/dependabot/nuget/nuget_config_credential_helpers.rb +10 -1
  16. data/lib/dependabot/nuget/requirement.rb +17 -8
  17. data/lib/dependabot/nuget/update_checker/compatibility_checker.rb +28 -7
  18. data/lib/dependabot/nuget/update_checker/dependency_finder.rb +70 -19
  19. data/lib/dependabot/nuget/update_checker/nupkg_fetcher.rb +76 -8
  20. data/lib/dependabot/nuget/update_checker/nuspec_fetcher.rb +25 -3
  21. data/lib/dependabot/nuget/update_checker/property_updater.rb +108 -44
  22. data/lib/dependabot/nuget/update_checker/repository_finder.rb +90 -18
  23. data/lib/dependabot/nuget/update_checker/requirements_updater.rb +32 -9
  24. data/lib/dependabot/nuget/update_checker/tfm_comparer.rb +8 -3
  25. data/lib/dependabot/nuget/update_checker/tfm_finder.rb +51 -13
  26. data/lib/dependabot/nuget/update_checker/version_finder.rb +167 -62
  27. data/lib/dependabot/nuget/update_checker.rb +73 -29
  28. metadata +5 -5
@@ -1,8 +1,10 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "excon"
5
5
  require "nokogiri"
6
+ require "sorbet-runtime"
7
+
6
8
  require "dependabot/errors"
7
9
  require "dependabot/update_checkers/base"
8
10
  require "dependabot/registry_client"
@@ -12,23 +14,34 @@ require "dependabot/nuget/http_response_helpers"
12
14
  module Dependabot
13
15
  module Nuget
14
16
  class RepositoryFinder
17
+ extend T::Sig
18
+
15
19
  DEFAULT_REPOSITORY_URL = "https://api.nuget.org/v3/index.json"
16
20
  DEFAULT_REPOSITORY_API_KEY = "nuget.org"
17
21
 
22
+ sig do
23
+ params(
24
+ dependency: Dependabot::Dependency,
25
+ credentials: T::Array[Dependabot::Credential],
26
+ config_files: T::Array[Dependabot::DependencyFile]
27
+ ).void
28
+ end
18
29
  def initialize(dependency:, credentials:, config_files: [])
19
30
  @dependency = dependency
20
31
  @credentials = credentials
21
32
  @config_files = config_files
22
33
  end
23
34
 
35
+ sig { returns(T::Array[T::Hash[Symbol, String]]) }
24
36
  def dependency_urls
25
37
  find_dependency_urls
26
38
  end
27
39
 
40
+ sig { returns(T::Array[T::Hash[Symbol, String]]) }
28
41
  def known_repositories
29
42
  return @known_repositories if @known_repositories
30
43
 
31
- @known_repositories = []
44
+ @known_repositories ||= T.let([], T.nilable(T::Array[T::Hash[Symbol, String]]))
32
45
  @known_repositories += credential_repositories
33
46
  @known_repositories += config_file_repositories
34
47
 
@@ -40,6 +53,7 @@ module Dependabot
40
53
  @known_repositories.uniq
41
54
  end
42
55
 
56
+ sig { params(dependency_name: String).returns(T::Hash[Symbol, T.untyped]) }
43
57
  def self.get_default_repository_details(dependency_name)
44
58
  {
45
59
  base_url: "https://api.nuget.org/v3-flatcontainer/",
@@ -56,21 +70,33 @@ module Dependabot
56
70
 
57
71
  private
58
72
 
59
- attr_reader :dependency, :credentials, :config_files
73
+ sig { returns(Dependabot::Dependency) }
74
+ attr_reader :dependency
75
+
76
+ sig { returns(T::Array[Dependabot::Credential]) }
77
+ attr_reader :credentials
78
+
79
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
80
+ attr_reader :config_files
60
81
 
82
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
61
83
  def find_dependency_urls
62
84
  @find_dependency_urls ||=
63
- known_repositories.flat_map do |details|
64
- if details.fetch(:url) == DEFAULT_REPOSITORY_URL
65
- # Save a request for the default URL, since we already know how
66
- # it addresses packages
67
- next default_repository_details
68
- end
85
+ T.let(
86
+ known_repositories.flat_map do |details|
87
+ if details.fetch(:url) == DEFAULT_REPOSITORY_URL
88
+ # Save a request for the default URL, since we already know how
89
+ # it addresses packages
90
+ next default_repository_details
91
+ end
69
92
 
70
- build_url_for_details(details)
71
- end.compact.uniq
93
+ build_url_for_details(details)
94
+ end.compact.uniq,
95
+ T.nilable(T::Array[T::Hash[Symbol, T.untyped]])
96
+ )
72
97
  end
73
98
 
99
+ sig { params(repo_details: T::Hash[Symbol, T.untyped]).returns(T.nilable(T::Hash[Symbol, T.untyped])) }
74
100
  def build_url_for_details(repo_details)
75
101
  url = repo_details.fetch(:url)
76
102
  url_obj = URI.parse(url)
@@ -86,6 +112,7 @@ module Dependabot
86
112
  details
87
113
  end
88
114
 
115
+ sig { params(repo_details: T::Hash[Symbol, T.untyped]).returns(T.nilable(T::Hash[Symbol, T.untyped])) }
89
116
  def build_url_for_details_remote(repo_details)
90
117
  response = get_repo_metadata(repo_details)
91
118
  check_repo_response(response, repo_details)
@@ -118,11 +145,12 @@ module Dependabot
118
145
 
119
146
  details
120
147
  rescue JSON::ParserError
121
- build_v2_url(response, repo_details)
148
+ build_v2_url(T.must(response), repo_details)
122
149
  rescue Excon::Error::Timeout, Excon::Error::Socket
123
150
  handle_timeout(repo_metadata_url: repo_details.fetch(:url))
124
151
  end
125
152
 
153
+ sig { params(repo_details: T::Hash[Symbol, T.untyped]).returns(Excon::Response) }
126
154
  def get_repo_metadata(repo_details)
127
155
  url = repo_details.fetch(:url)
128
156
  cache = CacheManager.cache("repo_finder_metadatacache")
@@ -138,6 +166,7 @@ module Dependabot
138
166
  end
139
167
  end
140
168
 
169
+ sig { params(metadata: T::Hash[String, T::Array[T::Hash[String, T.untyped]]]).returns(T.nilable(String)) }
141
170
  def base_url_from_v3_metadata(metadata)
142
171
  metadata
143
172
  .fetch("resources", [])
@@ -145,6 +174,7 @@ module Dependabot
145
174
  &.fetch("@id")
146
175
  end
147
176
 
177
+ sig { params(metadata: T::Hash[String, T::Array[T::Hash[String, T.untyped]]]).returns(T.nilable(String)) }
148
178
  def registration_url_from_v3_metadata(metadata)
149
179
  allowed_registration_types = %w(
150
180
  RegistrationsBaseUrl
@@ -159,6 +189,7 @@ module Dependabot
159
189
  &.fetch("@id")
160
190
  end
161
191
 
192
+ sig { params(metadata: T::Hash[String, T::Array[T::Hash[String, T.untyped]]]).returns(T.nilable(String)) }
162
193
  def search_url_from_v3_metadata(metadata)
163
194
  # allowable values from here: https://learn.microsoft.com/en-us/nuget/api/search-query-service-resource#versioning
164
195
  allowed_search_types = %w(
@@ -173,6 +204,13 @@ module Dependabot
173
204
  &.fetch("@id")
174
205
  end
175
206
 
207
+ sig do
208
+ params(
209
+ response: Excon::Response,
210
+ repo_details: T::Hash[Symbol, T.untyped]
211
+ )
212
+ .returns(T::Hash[Symbol, T.untyped])
213
+ end
176
214
  def build_v2_url(response, repo_details)
177
215
  doc = Nokogiri::XML(response.body)
178
216
 
@@ -194,6 +232,7 @@ module Dependabot
194
232
  }
195
233
  end
196
234
 
235
+ sig { params(response: Excon::Response, details: T::Hash[Symbol, T.untyped]).void }
197
236
  def check_repo_response(response, details)
198
237
  return unless [401, 402, 403].include?(response.status)
199
238
  raise if details.fetch(:url) == DEFAULT_REPOSITORY_URL
@@ -201,19 +240,25 @@ module Dependabot
201
240
  raise PrivateSourceAuthenticationFailure, details.fetch(:url)
202
241
  end
203
242
 
243
+ sig { params(repo_metadata_url: String).returns(T.noreturn) }
204
244
  def handle_timeout(repo_metadata_url:)
205
245
  raise if repo_metadata_url == DEFAULT_REPOSITORY_URL
206
246
 
207
247
  raise PrivateSourceTimedOut, repo_metadata_url
208
248
  end
209
249
 
250
+ sig { returns(T::Array[T::Hash[Symbol, String]]) }
210
251
  def credential_repositories
211
252
  @credential_repositories ||=
212
- credentials
213
- .select { |cred| cred["type"] == "nuget_feed" && cred["url"] }
214
- .map { |c| { url: c.fetch("url"), token: c["token"] } }
253
+ T.let(
254
+ credentials
255
+ .select { |cred| cred["type"] == "nuget_feed" && cred["url"] }
256
+ .map { |c| { url: c.fetch("url"), token: c["token"] } },
257
+ T.nilable(T::Array[T::Hash[Symbol, String]])
258
+ )
215
259
  end
216
260
 
261
+ sig { returns(T::Array[T::Hash[Symbol, String]]) }
217
262
  def config_file_repositories
218
263
  config_files.flat_map { |file| repos_from_config_file(file) }
219
264
  end
@@ -222,13 +267,14 @@ module Dependabot
222
267
  # rubocop:disable Metrics/PerceivedComplexity
223
268
  # rubocop:disable Metrics/MethodLength
224
269
  # rubocop:disable Metrics/AbcSize
270
+ sig { params(config_file: Dependabot::DependencyFile).returns(T::Array[T::Hash[Symbol, String]]) }
225
271
  def repos_from_config_file(config_file)
226
272
  doc = Nokogiri::XML(config_file.content)
227
273
  doc.remove_namespaces!
228
274
  # analogous to having a root config with the default repository
229
275
  base_sources = [{ url: DEFAULT_REPOSITORY_URL, key: "nuget.org" }]
230
276
 
231
- sources = []
277
+ sources = T.let([], T::Array[T::Hash[Symbol, String]])
232
278
 
233
279
  # regular package sources
234
280
  doc.css("configuration > packageSources").children.each do |node|
@@ -269,6 +315,23 @@ module Dependabot
269
315
  known_urls.include?(s.fetch(:url))
270
316
  end
271
317
 
318
+ # filter out based on packageSourceMapping
319
+ package_mapping_elements = doc.xpath("/configuration/packageSourceMapping/packageSource/package[@pattern]")
320
+ matching_package_elements = package_mapping_elements.select do |package_element|
321
+ pattern = package_element.attribute("pattern").value
322
+
323
+ # reusing this function for a case insensitive GLOB pattern patch (e.g., "Microsoft.Azure.*")
324
+ File.fnmatch(pattern, @dependency.name, File::FNM_CASEFOLD)
325
+ end
326
+ longest_matching_package_element = matching_package_elements.max_by do |package_element|
327
+ package_element.attribute("pattern").value.length
328
+ end
329
+ matching_key = longest_matching_package_element&.parent&.attribute("key")&.value
330
+ if matching_key
331
+ # found a matching source, only keep that one
332
+ sources.select! { |s| s.fetch(:key) == matching_key }
333
+ end
334
+
272
335
  add_config_file_credentials(sources: sources, doc: doc)
273
336
  sources.each { |details| details.delete(:key) }
274
337
 
@@ -279,11 +342,13 @@ module Dependabot
279
342
  # rubocop:enable Metrics/PerceivedComplexity
280
343
  # rubocop:enable Metrics/CyclomaticComplexity
281
344
 
345
+ sig { returns(T::Hash[Symbol, T.untyped]) }
282
346
  def default_repository_details
283
347
  RepositoryFinder.get_default_repository_details(dependency.name)
284
348
  end
285
349
 
286
350
  # rubocop:disable Metrics/PerceivedComplexity
351
+ sig { params(doc: Nokogiri::XML::Document).returns(T::Array[String]) }
287
352
  def disabled_sources(doc)
288
353
  doc.css("configuration > disabledPackageSources > add").filter_map do |node|
289
354
  value = node.attribute("value")&.value ||
@@ -298,6 +363,13 @@ module Dependabot
298
363
  # rubocop:enable Metrics/PerceivedComplexity
299
364
 
300
365
  # rubocop:disable Metrics/PerceivedComplexity
366
+ sig do
367
+ params(
368
+ sources: T::Array[T::Hash[Symbol, T.nilable(String)]],
369
+ doc: Nokogiri::XML::Document
370
+ )
371
+ .void
372
+ end
301
373
  def add_config_file_credentials(sources:, doc:)
302
374
  sources.each do |source_details|
303
375
  key = source_details.fetch(:key)
@@ -329,11 +401,10 @@ module Dependabot
329
401
  # Any non-ascii characters in the tag with cause a syntax error
330
402
  next source_details[:token] = nil
331
403
  end
332
-
333
- sources
334
404
  end
335
405
  # rubocop:enable Metrics/PerceivedComplexity
336
406
 
407
+ sig { params(string: String).returns(String) }
337
408
  def expand_windows_style_environment_variables(string)
338
409
  # NuGet.Config files can have Windows-style environment variables that need to be replaced
339
410
  # https://learn.microsoft.com/en-us/nuget/reference/nuget-config-file#using-environment-variables
@@ -352,6 +423,7 @@ module Dependabot
352
423
  end
353
424
  end
354
425
 
426
+ sig { params(token: T.nilable(String)).returns(T::Hash[String, String]) }
355
427
  def auth_header_for_token(token)
356
428
  return {} unless token
357
429
 
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  #######################################################################
@@ -6,6 +6,8 @@
6
6
  # https://docs.microsoft.com/en-us/nuget/reference/package-versioning #
7
7
  #######################################################################
8
8
 
9
+ require "sorbet-runtime"
10
+
9
11
  require "dependabot/update_checkers/base"
10
12
  require "dependabot/nuget/version"
11
13
 
@@ -13,14 +15,25 @@ module Dependabot
13
15
  module Nuget
14
16
  class UpdateChecker < Dependabot::UpdateCheckers::Base
15
17
  class RequirementsUpdater
18
+ extend T::Sig
19
+
20
+ sig do
21
+ params(
22
+ requirements: T::Array[T::Hash[Symbol, T.untyped]],
23
+ latest_version: T.nilable(T.any(String, Dependabot::Nuget::Version)),
24
+ source_details: T.nilable(T::Hash[Symbol, T.untyped])
25
+ )
26
+ .void
27
+ end
16
28
  def initialize(requirements:, latest_version:, source_details:)
17
29
  @requirements = requirements
18
30
  @source_details = source_details
19
31
  return unless latest_version
20
32
 
21
- @latest_version = version_class.new(latest_version)
33
+ @latest_version = T.let(version_class.new(latest_version), Dependabot::Nuget::Version)
22
34
  end
23
35
 
36
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
24
37
  def updated_requirements
25
38
  return requirements unless latest_version
26
39
 
@@ -52,32 +65,42 @@ module Dependabot
52
65
 
53
66
  private
54
67
 
55
- attr_reader :requirements, :latest_version, :source_details
68
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
69
+ attr_reader :requirements
70
+
71
+ sig { returns(T.nilable(Dependabot::Nuget::Version)) }
72
+ attr_reader :latest_version
73
+
74
+ sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
75
+ attr_reader :source_details
56
76
 
77
+ sig { returns(T.class_of(Dependabot::Nuget::Version)) }
57
78
  def version_class
58
- Nuget::Version
79
+ Dependabot::Nuget::Version
59
80
  end
60
81
 
82
+ sig { params(req_string: String).returns(String) }
61
83
  def update_wildcard_requirement(req_string)
62
84
  return req_string if req_string == "*-*"
63
85
 
64
86
  return req_string if req_string == "*"
65
87
 
66
- precision = req_string.split("*").first.split(/\.|\-/).count
88
+ precision = T.must(req_string.split("*").first).split(/\.|\-/).count
67
89
  wildcard_section = req_string.partition(/(?=[.\-]\*)/).last
68
90
 
69
- version_parts = latest_version.segments.first(precision)
91
+ version_parts = T.must(latest_version).segments.first(precision)
70
92
  version = version_parts.join(".")
71
93
 
72
94
  version + wildcard_section
73
95
  end
74
96
 
97
+ sig { returns(T::Hash[Symbol, T.untyped]) }
75
98
  def updated_source
76
99
  {
77
100
  type: "nuget_repo",
78
- url: source_details.fetch(:repo_url),
79
- nuspec_url: source_details.fetch(:nuspec_url),
80
- source_url: source_details.fetch(:source_url)
101
+ url: source_details&.fetch(:repo_url),
102
+ nuspec_url: source_details&.fetch(:nuspec_url),
103
+ source_url: source_details&.fetch(:source_url)
81
104
  }
82
105
  end
83
106
  end
@@ -1,6 +1,8 @@
1
- # typed: true
1
+ # typed: strong
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "sorbet-runtime"
5
+
4
6
  require "dependabot/update_checkers/base"
5
7
  require "dependabot/nuget/version"
6
8
  require "dependabot/nuget/requirement"
@@ -10,19 +12,22 @@ require "dependabot/shared_helpers"
10
12
  module Dependabot
11
13
  module Nuget
12
14
  class TfmComparer
15
+ extend T::Sig
16
+
17
+ sig { params(project_tfms: T::Array[String], package_tfms: T::Array[String]).returns(T::Boolean) }
13
18
  def self.are_frameworks_compatible?(project_tfms, package_tfms)
14
19
  return false if package_tfms.empty?
15
20
  return false if project_tfms.empty?
16
21
 
17
22
  key = "project_ftms:#{project_tfms.sort.join(',')}:package_tfms:#{package_tfms.sort.join(',')}".downcase
18
23
 
19
- @cached_framework_check ||= {}
24
+ @cached_framework_check ||= T.let({}, T.nilable(T::Hash[String, T::Boolean]))
20
25
  unless @cached_framework_check.key?(key)
21
26
  @cached_framework_check[key] =
22
27
  NativeHelpers.run_nuget_framework_check(project_tfms,
23
28
  package_tfms)
24
29
  end
25
- @cached_framework_check[key]
30
+ T.must(@cached_framework_check[key])
26
31
  end
27
32
  end
28
33
  end
@@ -1,8 +1,9 @@
1
- # typed: true
1
+ # typed: strong
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "excon"
5
5
  require "nokogiri"
6
+ require "sorbet-runtime"
6
7
 
7
8
  require "dependabot/update_checkers/base"
8
9
  require "dependabot/nuget/version"
@@ -13,15 +14,25 @@ require "dependabot/shared_helpers"
13
14
  module Dependabot
14
15
  module Nuget
15
16
  class TfmFinder
17
+ extend T::Sig
18
+
16
19
  require "dependabot/nuget/file_parser/packages_config_parser"
17
20
  require "dependabot/nuget/file_parser/project_file_parser"
18
21
 
22
+ sig do
23
+ params(
24
+ dependency_files: T::Array[Dependabot::DependencyFile],
25
+ credentials: T::Array[Dependabot::Credential],
26
+ repo_contents_path: T.nilable(String)
27
+ ).void
28
+ end
19
29
  def initialize(dependency_files:, credentials:, repo_contents_path:)
20
30
  @dependency_files = dependency_files
21
31
  @credentials = credentials
22
32
  @repo_contents_path = repo_contents_path
23
33
  end
24
34
 
35
+ sig { params(dependency: Dependabot::Dependency).returns(T::Array[String]) }
25
36
  def frameworks(dependency)
26
37
  tfms = Set.new
27
38
  tfms += project_file_tfms(dependency)
@@ -31,14 +42,23 @@ module Dependabot
31
42
 
32
43
  private
33
44
 
34
- attr_reader :dependency_files, :credentials, :repo_contents_path
45
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
46
+ attr_reader :dependency_files
47
+
48
+ sig { returns(T::Array[Dependabot::Credential]) }
49
+ attr_reader :credentials
50
+
51
+ sig { returns(T.nilable(String)) }
52
+ attr_reader :repo_contents_path
35
53
 
54
+ sig { params(dependency: Dependabot::Dependency).returns(T::Array[String]) }
36
55
  def project_file_tfms(dependency)
37
56
  project_files_with_dependency(dependency).flat_map do |file|
38
57
  project_file_parser.target_frameworks(project_file: file)
39
58
  end
40
59
  end
41
60
 
61
+ sig { params(dependency: Dependabot::Dependency).returns(T::Array[Dependabot::DependencyFile]) }
42
62
  def project_files_with_dependency(dependency)
43
63
  project_files.select do |file|
44
64
  packages_config_contains_dependency?(file, dependency) ||
@@ -46,6 +66,7 @@ module Dependabot
46
66
  end
47
67
  end
48
68
 
69
+ sig { params(file: Dependabot::DependencyFile, dependency: Dependabot::Dependency).returns(T::Boolean) }
49
70
  def packages_config_contains_dependency?(file, dependency)
50
71
  config_file = find_packages_config_file(file)
51
72
  return false unless config_file
@@ -56,36 +77,48 @@ module Dependabot
56
77
  end
57
78
  end
58
79
 
80
+ sig { params(file: Dependabot::DependencyFile, dependency: Dependabot::Dependency).returns(T::Boolean) }
59
81
  def project_file_contains_dependency?(file, dependency)
60
82
  project_file_parser.dependency_set(project_file: file).dependencies.any? do |d|
61
83
  d.name.casecmp(dependency.name)&.zero?
62
84
  end
63
85
  end
64
86
 
87
+ sig { params(file: Dependabot::DependencyFile).returns(T.nilable(Dependabot::DependencyFile)) }
65
88
  def find_packages_config_file(file)
66
89
  return file if file.name.end_with?("packages.config")
67
90
 
68
91
  filename = File.basename(file.name)
69
92
  search_path = file.name.sub(filename, "packages.config")
70
93
 
71
- dependency_files.find { |f| f.name.casecmp(search_path).zero? }
94
+ dependency_files.find { |f| f.name.casecmp(search_path)&.zero? }
72
95
  end
73
96
 
97
+ sig { returns(T::Array[String]) }
74
98
  def project_import_file_tfms
75
- @project_import_file_tfms ||= project_import_files.flat_map do |file|
76
- project_file_parser.target_frameworks(project_file: file)
77
- end
99
+ @project_import_file_tfms ||=
100
+ T.let(
101
+ project_import_files.flat_map do |file|
102
+ project_file_parser.target_frameworks(project_file: file)
103
+ end,
104
+ T.nilable(T::Array[String])
105
+ )
78
106
  end
79
107
 
108
+ sig { returns(FileParser::ProjectFileParser) }
80
109
  def project_file_parser
81
110
  @project_file_parser ||=
82
- FileParser::ProjectFileParser.new(
83
- dependency_files: dependency_files,
84
- credentials: credentials,
85
- repo_contents_path: repo_contents_path
111
+ T.let(
112
+ FileParser::ProjectFileParser.new(
113
+ dependency_files: dependency_files,
114
+ credentials: credentials,
115
+ repo_contents_path: repo_contents_path
116
+ ),
117
+ T.nilable(FileParser::ProjectFileParser)
86
118
  )
87
119
  end
88
120
 
121
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
89
122
  def project_files
90
123
  projfile = /\.[a-z]{2}proj$/
91
124
  packageprops = /[Dd]irectory.[Pp]ackages.props/
@@ -96,12 +129,14 @@ module Dependabot
96
129
  end
97
130
  end
98
131
 
132
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
99
133
  def packages_config_files
100
134
  dependency_files.select do |f|
101
- f.name.split("/").last.casecmp("packages.config").zero?
135
+ f.name.split("/").last&.casecmp("packages.config")&.zero?
102
136
  end
103
137
  end
104
138
 
139
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
105
140
  def project_import_files
106
141
  dependency_files -
107
142
  project_files -
@@ -111,16 +146,19 @@ module Dependabot
111
146
  [dotnet_tools_json]
112
147
  end
113
148
 
149
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
114
150
  def nuget_configs
115
151
  dependency_files.select { |f| f.name.match?(/nuget\.config$/i) }
116
152
  end
117
153
 
154
+ sig { returns(T.nilable(Dependabot::DependencyFile)) }
118
155
  def global_json
119
- dependency_files.find { |f| f.name.casecmp("global.json").zero? }
156
+ dependency_files.find { |f| f.name.casecmp("global.json")&.zero? }
120
157
  end
121
158
 
159
+ sig { returns(T.nilable(Dependabot::DependencyFile)) }
122
160
  def dotnet_tools_json
123
- dependency_files.find { |f| f.name.casecmp(".config/dotnet-tools.json").zero? }
161
+ dependency_files.find { |f| f.name.casecmp(".config/dotnet-tools.json")&.zero? }
124
162
  end
125
163
  end
126
164
  end