lib/tapioca/gemfile.rb in tapioca-0.7.3 vs lib/tapioca/gemfile.rb in tapioca-0.8.0

- old
+ new

@@ -14,21 +14,66 @@ ::Bundler::StubSpecification, ::Gem::Specification ) end + # This is a module that gets prepended to `Bundler::Dependency` and + # makes sure even gems marked as `require: false` are required during + # `Bundler.require`. + module AutoRequireHook + extend T::Sig + extend T::Helpers + + requires_ancestor { ::Bundler::Dependency } + + @exclude = T.let([], T::Array[String]) + + class << self + extend T::Sig + + sig { params(exclude: T::Array[String]).returns(T::Array[String]) } + attr_writer :exclude + + sig { params(name: T.untyped).returns(T::Boolean) } + def excluded?(name) + @exclude.include?(name) + end + end + + sig { returns(T.untyped).checked(:never) } + def autorequire + value = super + + # If the gem is excluded, we don't want to force require it, in case + # it has side-effects users don't want. For example, `fakefs` gem, if + # loaded, takes over filesystem operations. + return value if AutoRequireHook.excluded?(name) + + # If a gem is marked as `require: false`, then its `autorequire` + # value will be `[]`. But, we want those gems to be loaded for our + # purposes as well, so we return `nil` in those cases, instead, which + # means `require: true`. + return nil if value == [] + + value + end + + ::Bundler::Dependency.prepend(self) + end + sig { returns(Bundler::Definition) } attr_reader(:definition) sig { returns(T::Array[GemSpec]) } attr_reader(:dependencies) sig { returns(T::Array[String]) } attr_reader(:missing_specs) - sig { void } - def initialize + sig { params(exclude: T::Array[String]).void } + def initialize(exclude) + AutoRequireHook.exclude = exclude @gemfile = T.let(File.new(Bundler.default_gemfile), File) @lockfile = T.let(File.new(Bundler.default_lockfile), File) @definition = T.let(Bundler::Dsl.evaluate(gemfile, lockfile, {}), Bundler::Definition) dependencies, missing_specs = load_dependencies @dependencies = T.let(dependencies, T::Array[GemSpec]) @@ -92,11 +137,12 @@ end class GemSpec extend(T::Sig) - IGNORED_GEMS = T.let(["sorbet", "sorbet-static", "sorbet-runtime"].freeze, T::Array[String]) + IGNORED_GEMS = T.let(["sorbet", "sorbet-static", "sorbet-runtime", "sorbet-static-and-runtime"].freeze, + T::Array[String]) sig { returns(String) } attr_reader :full_gem_path, :version sig { returns(T::Array[Pathname]) } @@ -225,9 +271,10 @@ # 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?