Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@ Options:
# Default: false
--typed, -t, [--typed-overrides=gem:level [gem:level ...]] # Override for typed sigils for generated gem RBIs
# Default: {"activesupport" => "false"}
[--private-methods], [--no-private-methods], [--skip-private-methods] # Include private methods in generated gem RBIs
# Default: true
[--private-methods-for=gem [gem ...]] # Always include private methods for the given gems
[--verify], [--no-verify], [--skip-verify] # Verify RBIs are up-to-date
# Default: false
[--doc], [--no-doc], [--skip-doc] # Include documentation from sources when generating RBIs
Expand Down Expand Up @@ -1014,6 +1017,16 @@ gem:
doc: true
```

Private methods are included by default. To omit them and keep them only for selected gems, configure `private_methods` and `private_methods_for`:

```yaml
gem:
private_methods: false
private_methods_for:
- rake
- activerecord
```

Additionally, if you always want to exclude the `AASM` and `ActiveRecordFixtures` DSL compilers in your DSL RBI generation runs, your config file would then look like this:

```yaml
Expand Down Expand Up @@ -1060,6 +1073,8 @@ gem:
include_dependencies: false
typed_overrides:
activesupport: 'false'
private_methods: true
private_methods_for: []
verify: false
doc: true
loc: true
Expand Down
11 changes: 11 additions & 0 deletions lib/tapioca/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,15 @@ def dsl(*constant_or_paths)
banner: "gem:level [gem:level ...]",
desc: "Override for typed sigils for generated gem RBIs",
default: DEFAULT_OVERRIDES
option :private_methods,
type: :boolean,
desc: "Include private methods in generated gem RBIs",
default: true
option :private_methods_for,
type: :array,
banner: "gem [gem ...]",
desc: "Always include private methods for the given gems",
default: []
option :verify,
type: :boolean,
desc: "Verify RBIs are up-to-date",
Expand Down Expand Up @@ -299,6 +308,8 @@ def gem(*gems)
prerequire: options[:prerequire],
postrequire: options[:postrequire],
typed_overrides: options[:typed_overrides],
private_methods: options[:private_methods],
private_methods_for: options[:private_methods_for],
outpath: Pathname.new(options[:outdir]),
file_header: options[:file_header],
include_doc: options[:doc],
Expand Down
23 changes: 23 additions & 0 deletions lib/tapioca/commands/abstract_gem.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ class AbstractGem < Command
#| prerequire: String?,
#| postrequire: String,
#| typed_overrides: Hash[String, String],
#| private_methods: bool,
#| private_methods_for: Array[String],
#| outpath: Pathname,
#| file_header: bool,
#| include_doc: bool,
Expand All @@ -35,6 +37,8 @@ def initialize(
prerequire:,
postrequire:,
typed_overrides:,
private_methods:,
private_methods_for:,
outpath:,
file_header:,
include_doc:,
Expand All @@ -54,6 +58,8 @@ def initialize(
@prerequire = prerequire
@postrequire = postrequire
@typed_overrides = typed_overrides
@private_methods = private_methods
@private_methods_for = private_methods_for
@outpath = outpath
@file_header = file_header
@number_of_workers = number_of_workers
Expand Down Expand Up @@ -102,6 +108,7 @@ def compile_gem_rbi(gem)
end

merge_with_exported_rbi(gem, rbi) if @include_exported_rbis
remove_private_methods(rbi.root) if omit_private_methods?(gem)

if rbi.empty?
@rbi_formatter.write_empty_body_comment!(rbi)
Expand Down Expand Up @@ -288,6 +295,22 @@ def merge_with_exported_rbi(gem, file)
say_error("\n\n RBIs exported by `#{gem.name}` contain errors and can't be used:", :yellow)
say_error("Cause: #{e.message} (#{e.location})")
end

#: (Gemfile::GemSpec gem) -> bool
def omit_private_methods?(gem)
!@private_methods && !@private_methods_for.include?(gem.name)
end

#: (RBI::Tree tree) -> void
def remove_private_methods(tree)
tree.nodes.dup.each do |node|
if node.is_a?(RBI::Tree)
remove_private_methods(node)
elsif (node.is_a?(RBI::Method) || node.is_a?(RBI::Attr)) && node.visibility.private?
node.detach
end
end
end
end
end
end
3 changes: 3 additions & 0 deletions lib/tapioca/commands/configure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ def create_tapioca_config
# - gem_name
# doc: true
# workers: 5
# private_methods: false
# private_methods_for:
# - gem_name
dsl:
# Add your `dsl` command parameters here:
#
Expand Down
4 changes: 4 additions & 0 deletions spec/tapioca/cli/config_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,11 @@ class ConfigTest < SpecWithProject
@project.write!("sorbet/tapioca/config.yml", <<~YAML)
gem:
doc: "true"
private_methods: "false"
typed_overrides:
- "true"
- "false"
private_methods_for: [1, false]
workers: "foo"
dsl:
exclude: true
Expand All @@ -87,7 +89,9 @@ class ConfigTest < SpecWithProject
Configuration file sorbet/tapioca/config.yml has the following errors:

- invalid value for option doc for key gem - expected Boolean but found String
- invalid value for option private_methods for key gem - expected Boolean but found String
- invalid value for option typed_overrides for key gem - expected Hash but found Array
- invalid value for option private_methods_for for key gem - expected Array[String] but found [1, false]
- invalid value for option workers for key gem - expected Numeric but found String
- invalid value for option exclude for key dsl - expected Array but found Boolean
ERR
Expand Down
124 changes: 124 additions & 0 deletions spec/tapioca/cli/gem_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,130 @@ module Reopened; end
assert_success_status(result)
end

it "must filter every private method from the complete gem RBI when configured" do
foo = mock_gem("foo", "0.0.1") do
write!("lib/foo.rb", <<~RB)
module Foo
def public_method; end

private

def private_a; end
def private_b; end
def private_c; end
def private_d; end

class << self
def public_class_method; end

private

def private_class_a; end
def private_class_b; end
end
end
RB

write!("rbi/foo.rbi", <<~RBI)
module Foo
def exported_method; end

private def exported_private_a; end
private def exported_private_b; end

class << self
def exported_class_method; end

private def exported_private_class_a; end
private def exported_private_class_b; end
end
end
RBI
end

@project.require_mock_gem(foo)
@project.bundle_install!

expected_with_private_methods = <<~RBI
# typed: true

# DO NOT EDIT MANUALLY
# This is an autogenerated file for types exported from the `foo` gem.
# Please instead update this file by running `bin/tapioca gem foo`.


module Foo
def exported_method; end
def public_method; end

private

def exported_private_a; end
def exported_private_b; end
def private_a; end
def private_b; end
def private_c; end
def private_d; end

class << self
def exported_class_method; end
def public_class_method; end

private

def exported_private_class_a; end
def exported_private_class_b; end
def private_class_a; end
def private_class_b; end
end
end
RBI

result = @project.tapioca("gem foo")

assert_success_status(result)
assert_project_file_equal("sorbet/rbi/gems/foo@0.0.1.rbi", expected_with_private_methods)

@project.write!("sorbet/tapioca/config.yml", <<~YAML)
gem:
private_methods: false
YAML

result = @project.tapioca("gem foo")

assert_success_status(result)
assert_project_file_equal("sorbet/rbi/gems/foo@0.0.1.rbi", <<~RBI)
# typed: true

# DO NOT EDIT MANUALLY
# This is an autogenerated file for types exported from the `foo` gem.
# Please instead update this file by running `bin/tapioca gem foo`.


module Foo
def exported_method; end
def public_method; end

class << self
def exported_class_method; end
def public_class_method; end
end
end
RBI

@project.write!("sorbet/tapioca/config.yml", <<~YAML)
gem:
private_methods: false
private_methods_for:
- foo
YAML

result = @project.tapioca("gem foo")

assert_success_status(result)
assert_project_file_equal("sorbet/rbi/gems/foo@0.0.1.rbi", expected_with_private_methods)
end

it "must output currently compiling status with verbose flag" do
foo = mock_gem("foo", "0.0.1") do
write!("lib/foo.rb", FOO_RB)
Expand Down
Loading