From 7c5da56107033445deed02fd310d6195e2b762fa Mon Sep 17 00:00:00 2001 From: Takumi Shotoku Date: Sat, 14 Feb 2026 14:44:19 +0900 Subject: [PATCH] Add --exclude option to skip files matching glob patterns Some projects contain .rb files that are not valid Ruby syntax. This option allows users to exclude those files from analysis. Examples of such files: - ERB templates with .rb extension https://github.com/heartcombo/devise/blob/v5.0.1/lib/generators/active_record/templates/migration.rb - .rb files embedding RBS syntax for testing https://github.com/ruby/typeprof/tree/v0.31.1/scenario/**/*.rb Usage: typeprof --exclude "**/templates/**/*.rb" lib/ For LSP mode, the "exclude" key can be set in typeprof.conf.jsonc. --- lib/typeprof/cli/cli.rb | 6 +++++- lib/typeprof/core/service.rb | 13 +++++++++++-- lib/typeprof/lsp/server.rb | 1 + test/cli_test.rb | 11 +++++++++++ test/fixtures/exclude_test/lib/main.rb | 5 +++++ test/fixtures/exclude_test/templates/page.rb | 6 ++++++ 6 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 test/fixtures/exclude_test/lib/main.rb create mode 100644 test/fixtures/exclude_test/templates/page.rb diff --git a/lib/typeprof/cli/cli.rb b/lib/typeprof/cli/cli.rb index 88902d474..b2ec1bb5d 100644 --- a/lib/typeprof/cli/cli.rb +++ b/lib/typeprof/cli/cli.rb @@ -12,6 +12,7 @@ def initialize(argv) output = nil rbs_collection_path = nil initialize_config_file = false + exclude_patterns = [] opt.separator "" opt.separator "Options:" @@ -25,6 +26,7 @@ def initialize(argv) opt.on("--version", "Display typeprof version") { cli_options[:display_version] = true } opt.on("--collection PATH", "File path of collection configuration") { |v| rbs_collection_path = v } opt.on("--no-collection", "Ignore collection configuration") { rbs_collection_path = :no } + opt.on("--exclude PATTERN", "Exclude files matching glob PATTERN (can be specified multiple times)") { |v| exclude_patterns << v } opt.on("--lsp", "LSP server mode") do |v| core_options[:display_indicator] = false cli_options[:lsp] = true @@ -65,6 +67,7 @@ def initialize(argv) output_errors: false, output_parameter_names: false, output_source_locations: false, + exclude_patterns: exclude_patterns, }.merge(core_options) @lsp_options = { @@ -189,7 +192,8 @@ def generate_config_file { "typeprof_version": "experimental", "rbs_dir": "sig/", - "analysis_unit_dirs": #{exist_dirs.inspect} + "analysis_unit_dirs": #{exist_dirs.inspect}, + // "exclude": ["**/templates/**/*.rb"], // "diagnostic_severity": "warning" } JSONC diff --git a/lib/typeprof/core/service.rb b/lib/typeprof/core/service.rb index a79ca1c02..0b6dffd07 100644 --- a/lib/typeprof/core/service.rb +++ b/lib/typeprof/core/service.rb @@ -39,10 +39,10 @@ def reset! def add_workspace(rb_folder, rbs_folder) Dir.glob(File.expand_path(rb_folder + "/**/*.{rb,rbs}")) do |path| - update_file(path, nil) + update_file(path, nil) unless exclude_files.include?(path) end Dir.glob(File.expand_path(rbs_folder + "/**/*.{rb,rbs}")) do |path| - update_file(path, nil) + update_file(path, nil) unless exclude_files.include?(path) end end @@ -512,6 +512,7 @@ def batch(files, output) i += 1 end + next if exclude_files.include?(File.expand_path(file)) res = update_file(file, File.read(file)) if res @@ -542,6 +543,14 @@ def batch(files, output) output.puts dump_declarations(file) end end + + private + + def exclude_files + @exclude_files ||= (@options[:exclude_patterns] || []).each_with_object(::Set.new) { |pattern, set| + Dir.glob(File.expand_path(pattern)) { |path| set << path } + } + end end end diff --git a/lib/typeprof/lsp/server.rb b/lib/typeprof/lsp/server.rb index 287224c0d..ac811a883 100644 --- a/lib/typeprof/lsp/server.rb +++ b/lib/typeprof/lsp/server.rb @@ -104,6 +104,7 @@ def add_workspaces(folders) puts "unknown severity: #{ severity }" end end + @core_options[:exclude_patterns] = conf[:exclude] if conf[:exclude] conf[:analysis_unit_dirs].each do |dir| dir = File.expand_path(dir, path) core = @cores[dir] = TypeProf::Core::Service.new(@core_options) diff --git a/test/cli_test.rb b/test/cli_test.rb index 79ecde028..258ab0981 100644 --- a/test/cli_test.rb +++ b/test/cli_test.rb @@ -111,6 +111,17 @@ def check: -> :ok end) end + def test_e2e_exclude + assert_equal(<<~END, test_run("exclude_test", ["--exclude", "**/templates/**", "."])) + # TypeProf #{ TypeProf::VERSION } + + # ./lib/main.rb + class Object + def foo: (String) -> String + end + END + end + def test_lsp_options_with_lsp_mode assert_nothing_raised { TypeProf::CLI::CLI.new(["--lsp", "--stdio"]) } end diff --git a/test/fixtures/exclude_test/lib/main.rb b/test/fixtures/exclude_test/lib/main.rb new file mode 100644 index 000000000..f0c4841cf --- /dev/null +++ b/test/fixtures/exclude_test/lib/main.rb @@ -0,0 +1,5 @@ +def foo(n) + n +end + +foo("str") diff --git a/test/fixtures/exclude_test/templates/page.rb b/test/fixtures/exclude_test/templates/page.rb new file mode 100644 index 000000000..3d0743103 --- /dev/null +++ b/test/fixtures/exclude_test/templates/page.rb @@ -0,0 +1,6 @@ + + +

<%= title %>

+

<%= content %>

+ +