class Dependabot::FileParsers::Base::DependencySet::DependencySlot

dependency is accessible via ‘DependencySet#all_versions_for_name`.
`DependencySet#dependency_for_name`. The list of individual versions of the
The combined dependency is accessible via `DependencySet#dependencies` or
that combines the attributes of these versions.
all added versions and presents a single unified dependency for the entry
dependency may be encountered and added to the set. The `DependencySlot` retains
In some ecosystems (like `npm_and_yarn`), however, multiple versions of a
is assigned a `DependencySlot`.
There can only be one entry per dependency name in a `DependencySet`. Each entry

def <<(dep)

def <<(dep)
  return self if @all_versions.include?(dep)
  @combined = if @combined
                combined_dependency(@combined, dep)
              else
                dep
              end
  index_of_same_version =
    @all_versions.find_index { |other| other.version == dep.version }
  if index_of_same_version.nil?
    @all_versions << dep
  else
    same_version = @all_versions[index_of_same_version]
    @all_versions[index_of_same_version] = combined_dependency(T.must(same_version), dep)
  end
  self
end

def combined_dependency(old_dep, new_dep)

def combined_dependency(old_dep, new_dep)
  version = combined_version(old_dep, new_dep)
  requirements = (old_dep.requirements + new_dep.requirements).uniq
  subdependency_metadata = (
    (old_dep.subdependency_metadata || []) +
    (new_dep.subdependency_metadata || [])
  ).uniq
  Dependency.new(
    name: old_dep.name,
    version: version,
    requirements: requirements,
    package_manager: old_dep.package_manager,
    metadata: old_dep.metadata,
    subdependency_metadata: subdependency_metadata
  )
end

def combined_version(old_dep, new_dep)

def combined_version(old_dep, new_dep)
  if old_dep.version.nil? ^ new_dep.version.nil?
    T.must([old_dep, new_dep].find(&:version)).version
  elsif old_dep.top_level? ^ new_dep.top_level? # Prefer a direct dependency over a transitive one
    T.must([old_dep, new_dep].find(&:top_level?)).version
  elsif !version_class.correct?(new_dep.version)
    old_dep.version
  elsif !version_class.correct?(old_dep.version)
    new_dep.version
  elsif version_class.new(new_dep.version) > version_class.new(old_dep.version)
    old_dep.version
  else
    new_dep.version
  end
end

def initialize

def initialize
  @all_versions = T.let([], T::Array[Dependabot::Dependency])
  @combined = T.let(nil, T.nilable(Dependabot::Dependency))
end

def version_class

def version_class
  @version_class ||= T.let(
    T.must(@combined).version_class,
    T.nilable(T.class_of(Gem::Version))
  )
end