class Tapioca::Gemfile::GemSpec

def ==(other)

def ==(other)
  GemSpec === other && other.name == name && other.version == version
end

def collect_files

def collect_files
  if default_gem?
    # `Bundler::RemoteSpecification` delegates missing methods to
    # `Gem::Specification`, so `files` actually always exists on spec.
    T.unsafe(@spec).files.map do |file|
      resolve_to_ruby_lib_dir(file)
    end
  else
    @spec.full_require_paths.flat_map do |path|
      Pathname.glob((Pathname.new(path) / "**/*.rb").to_s)
    end
  end
end

def contains_path?(path)

def contains_path?(path)
  if default_gem?
    files.any? { |file| file.to_s == to_realpath(path) }
  else
    path_in_dir?(to_realpath(path), full_gem_path) || has_parent_gemspec?(path)
  end
end

def default_gem?

def default_gem?
  @spec.respond_to?(:default_gem?) && @spec.default_gem?
end

def dependencies

def dependencies
  @spec.dependencies
end

def export_rbi_files?

def export_rbi_files?
  exported_rbi_files.any?
end

def exported_rbi_files

def exported_rbi_files
  @exported_rbi_files ||= Dir.glob("#{full_gem_path}/rbi/**/*.rbi").sort
end

def exported_rbi_tree

def exported_rbi_tree
  rewriter = RBI::Rewriters::Merge.new(keep: RBI::Rewriters::Merge::Keep::NONE)
  exported_rbi_files.each do |file|
    rbi = RBI::Parser.parse_file(file)
    rewriter.merge(rbi)
  end
  rewriter.tree
end

def gem_ignored?

def gem_ignored?
  IGNORED_GEMS.include?(name)
end

def has_parent_gemspec?(path)

def has_parent_gemspec?(path)
  # For some Git installed gems the location of the loaded file can
  # be different from the gem path as indicated by the spec file
  #
  # To compensate for these cases, we walk up the directory hierarchy
  # from the given file and try to match a <gem-name.gemspec> file in
  # one of those folders to see if the path really belongs in the given gem
  # or not.
  return false unless Bundler::Source::Git === @spec.source
  parent = Pathname.new(path)
  until parent.root?
    parent = parent.parent.expand_path
    return true if parent.join("#{name}.gemspec").file?
  end
  false
end

def ignore?(gemfile_dir)

def ignore?(gemfile_dir)
  gem_ignored? || gem_in_app_dir?(gemfile_dir, full_gem_path)
end

def initialize(spec)

def initialize(spec)
  @spec = T.let(spec, Tapioca::Gemfile::Spec)
  real_gem_path = to_realpath(@spec.full_gem_path)
  @full_gem_path = T.let(real_gem_path, String)
  @version = T.let(version_string, String)
  @exported_rbi_files = T.let(nil, T.nilable(T::Array[String]))
  @files = T.let(collect_files, T::Array[Pathname])
end

def name

def name
  @spec.name
end

def parse_yard_docs

def parse_yard_docs
  files.each do |path|
    YARD.parse(path.to_s, [], Logger::Severity::FATAL)
  rescue RangeError
    # In some circumstances, YARD will raise an error when parsing a file
    # that is actually valid Ruby. We don't want tapioca to halt in these
    # cases, so we'll rescue the error, pretend like there was no
    # documentation, and move on.
    #
    # This can be removed when https://github.com/lsegal/yard/issues/1536
    # is resolved and released.
    []
  end
end

def rbi_file_name

def rbi_file_name
  "#{name}@#{version}.rbi"
end

def relative_path_for(file)

def relative_path_for(file)
  if default_gem?
    file.realpath.relative_path_from(RbConfig::CONFIG["rubylibdir"])
  else
    file.realpath.relative_path_from(full_gem_path)
  end
end

def require_paths_prefix_matcher

def require_paths_prefix_matcher
  @require_paths_prefix_matcher ||= T.let(
    begin
      require_paths = T.unsafe(@spec).require_paths
      prefix_matchers = require_paths.map { |rp| Regexp.new("^#{rp}/") }
      Regexp.union(prefix_matchers)
    end,
    T.nilable(Regexp),
  )
end

def resolve_to_ruby_lib_dir(file)

def resolve_to_ruby_lib_dir(file)
  # We want to match require prefixes but fallback to an empty match
  # if none of the require prefixes actually match. This is so that
  # we can always replace the match with the Ruby lib directory and
  # we would have properly resolved the file under the Ruby lib dir.
  prefix_matcher = Regexp.union(require_paths_prefix_matcher, //)
  ruby_lib_dir = RbConfig::CONFIG["rubylibdir"]
  file = file.sub(prefix_matcher, "#{ruby_lib_dir}/")
  Pathname.new(file).expand_path
end

def spec_lookup_by_file_path

def spec_lookup_by_file_path
  @lookup ||= T.let(
    [*::Gem::Specification.default_stubs, *::Gem::Specification.stubs]
      .map! { |spec| new(spec.to_spec) }
      .flat_map do |spec|
        spec.files.filter_map { |file| [file.realpath.to_s, spec] if file.exist? }
      end.to_h,
    T.nilable(T::Hash[String, Gemfile::GemSpec]),
  )
end

def version_string

def version_string
  version = @spec.version.to_s
  version += "-#{@spec.source.revision}" if Bundler::Source::Git === @spec.source
  version
end