{"id":13879434,"url":"https://github.com/robotdana/leftovers","last_synced_at":"2025-06-28T17:01:47.226Z","repository":{"id":41745428,"uuid":"182186980","full_name":"robotdana/leftovers","owner":"robotdana","description":"Find unused ruby methods and constants and etc ","archived":false,"fork":false,"pushed_at":"2023-03-23T21:00:15.000Z","size":854,"stargazers_count":85,"open_issues_count":2,"forks_count":4,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-31T16:14:21.671Z","etag":null,"topics":["linter","rails","ruby","static-analysis","unused-code","unused-constants","unused-methods"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/robotdana.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2019-04-19T02:19:27.000Z","updated_at":"2025-02-11T07:39:05.000Z","dependencies_parsed_at":"2024-01-13T20:57:15.898Z","dependency_job_id":"1275c242-26ce-4c82-9f22-bc7d5a566d20","html_url":"https://github.com/robotdana/leftovers","commit_stats":{"total_commits":269,"total_committers":4,"mean_commits":67.25,"dds":"0.052044609665427455","last_synced_commit":"283fda21ab1724be9a90f879e60497b913cc64a8"},"previous_names":[],"tags_count":27,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robotdana%2Fleftovers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robotdana%2Fleftovers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robotdana%2Fleftovers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robotdana%2Fleftovers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/robotdana","download_url":"https://codeload.github.com/robotdana/leftovers/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247704571,"owners_count":20982298,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["linter","rails","ruby","static-analysis","unused-code","unused-constants","unused-methods"],"created_at":"2024-08-06T08:02:21.006Z","updated_at":"2025-04-07T18:13:51.896Z","avatar_url":"https://github.com/robotdana.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"# Leftovers\n[![travis](https://travis-ci.com/robotdana/leftovers.svg?branch=main)](https://travis-ci.com/robotdana/leftovers)\n[![Gem Version](https://badge.fury.io/rb/leftovers.svg)](https://rubygems.org/gems/leftovers)\n\nFind unused `methods`, `Classes`, `CONSTANTS`, `@instance_variables`, `@@class_variables`, and `$global_variables` in your ruby projects.\n\n## Why?\n\nCode that never gets executed is code that you shouldn't need to maintain\n\n- Leftovers from refactoring\n- Partially removed features\n- Typos and THIS NEVER WOULD HAVE WORKED code\n- Code that you only keep around because there are tests of it\n\nLeftovers will use static analysis to find these bits of code for you.\n\nIt's aware of how some gems call methods for you, including support for much of rails.\n\n## Features\n\n- Fully configurable handling of methods that call other methods with literal arguments, and constant assignment\n- magic comments\n- designed to be run as a CI step\n- optimised for speed\n- built in config for some gems. (please make PRs with more gems)\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'leftovers', require: false\n```\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install leftovers\n\n## Usage\n\nRun `leftovers` in your command line in the root of your project.\nThis will output progress as it collects the calls/references and definitions in your project.\nThen it will output any defined methods (or classes etc) which are not called.\n\n```\n$ leftovers\nchecked 25 files, collected 2473 calls, 262 definitions\nOnly directly called in tests:\nlib/hello_world.rb:10:6 tested_unused_method def tested_unused_method\nlib/hello_world.rb:18:6 another_tested_unused_method def another_tested_unused_method\nNot directly called at all:\nlib/hello_world.rb:6:6 generated_method= attr_accessor :generated_method\nlib/hello_world.rb:6:6 generated_method attr_accessor :generated_method\n\nhow to resolve: https://github.com/robotdana/leftovers/tree/main/Readme.md#how-to-resolve\n```\n\nif there is an overwhelming number of results, try using [`--write-todo`](#write-todo)\n\n## How to resolve\n\nWhen running `leftovers` you'll be given a list of method, constant, and variable definitions it thinks are unused. Now what?\n\nthey were unintentionally left when removing their calls:\n  - remove their definitions. (they're still there in your git etc history if you want them back)\n\nthey are called dynamically:\n  - define how they're called dynamically in the [.leftovers.yml](#configuration-file); or\n  - mark the calls with [`# leftovers:call my_unused_method`](#leftovers-call); or\n  - mark the definition with [`# leftovers:keep`](#leftovers-keep)\n\nthey're defined intentionally to only be used by tests:\n  - add [`# leftovers:test_only`](#leftovers-test-only)\n\nthey're from a file that shouldn't be checked by leftovers:\n  - add the paths to the [`exclude_paths:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#exclude_paths) list in the [.leftovers.yml](#configuration-file) file\n\nif there are too many to address when first adding leftovers to your project, try running [`leftovers --write-todo`](#write-todo),\n\n### --write-todo\n\nrunning `leftovers --write-todo` will generate a supplemental configuration file allowing all the currently detected uncalled definitions, which will be read on subsequent runs of `leftovers` without alerting any of the items mentioned in it.\n\ncommit this file so you/your team can gradually address these items while still having leftovers alert you to any newly unused items.\n\n## Magic comments\n\n### `# leftovers:keep`\n_aliases `leftovers:keeps`, `leftovers:skip`, `leftovers:skips`, `leftovers:skipped`, `leftovers:allow`, `leftovers:allows`, `leftovers:allowed`_\nTo mark a method definition as not unused, add the comment `# leftovers:keep` on the same line as the definition\n\n```ruby\nclass MyClass\n  def my_method # leftovers:keep\n    true\n  end\nend\n```\nThis would report `MyClass` is unused, but not my_method\nTo do this for all definitions of this name, instead of adding a comment, add the name to the [`keep:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#keep) list in the [configuration file](#configuration-file).\n\n### `# leftovers:test_only`\n_aliases `leftovers:for_test`, `leftovers:for_tests`, `leftovers:test`, `leftovers:tests`, `leftovers:testing`_\n\nTo mark a definition from a non-test dir, as intentionally only used by tests, use `leftovers:test_only`\n```ruby\n# app/my_class.rb\nclass MyClass\n  def my_method # leftovers:test_only\n    true\n  end\nend\n```\n```ruby\n# spec/my_class_spec.rb\ndescribe MyClass do\n  it { expect(subject.my_method).to be true }\nend\n```\n\nThis would consider `my_method` to be used, even though it is only called by tests.\n\nTo do this for all definitions of this name, instead of adding a comment, add the name to the [`test_only:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#test_only) list in the [configuration file](#configuration-file).\n\n### `# leftovers:call`\n_aliases `leftovers:calls`_\nTo mark a call that doesn't use literal values, use `leftovers:call` with the method name listed\n```ruby\nmethod = [:puts, :warn].sample # leftovers:call puts, warn\nsend(method, 'text')\n```\n\nThis would consider `puts` and `warn` to both have been called\n\n### `# leftovers:dynamic:*`\nTo mark a dynamic call for literal hash and array values without enumerating everything in the comment again, use `leftovers:dynamic:`  on the same line as the beginning of the array or hash\n\n```ruby\n[ # leftovers:dynamic:call_attributes\n  :user,\n  :admin\n].map { |method| send(\"#{method}_attributes\") }\n```\n\nwith the following configuration matching the `name: value` to the `leftovers:dynamic:process_name`\n\n```yaml\ndynamic:\n  name: call_attributes\n  arguments: '*'\n  add_suffix: '_attributes'\n```\nThis would consider `user_attributes` and `admin_attributes` to both have been called.\n\n## Configuration file\n\nThe configuration is read from `.leftovers.yml` in your project root.\nIts presence is optional and all of these settings are optional.\n\n- [`include_paths:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#include_paths)\n- [`exclude_paths:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#exclude_paths)\n- [`test_paths:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#test_paths)\n- [`requires:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#requires)\n- [`precompile:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#precompile)\n- [`gems:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#gems)\n- [`keep:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#keep)\n- [`test_only:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#test_only)\n- [`dynamic:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#dynamic)\n\nsee the [complete config documentation](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md) for details.\nsee the [built in config files](https://github.com/robotdana/leftovers/tree/main/lib/config) or [this repo's own config](https://github.com/robotdana/leftovers/tree/main/.leftovers.yml) for examples.\n\n## Limitations\n\n- Leftovers will report methods/constants you define that are called outside your code (perhaps by gems) as unused\n\n  Add these names to the `keep:` list in the `.leftovers.yml` or add an inline comment with `# leftovers:allow my_method_name`\n- Leftovers doesn't execute your code so isn't aware of e.g. variables in calls to `send` (e.g. `send(variable_method_name)`). (it is aware of static calls (e.g. `send(:my_method_name)`), so using send to bypass method privacy is \"fine\")\n\n  Add the method/pattern to the `dynamic:` list with `skip: true` in the `.leftovers.yml`, or add an inline comment with the list of possibilities `# leftovers:call my_method_1, my_method_2`.\n- Leftovers compares by name only, so multiple definitions with the same name will count as used even if only one is.\n- haml, slim \u0026 erb line and column numbers will be wrong as the files have to be precompiled before checking.\n- dynamic calls \u0026 definitions based on values copied by rails `with_options` method aren't captured by leftovers.\n\n## Other tools\n\n- [rubocop](https://github.com/rubocop-hq/rubocop) has a cop that will alert for unused local variables and method arguments, and a cop that will report unreachable code.\n- [coverband](https://github.com/danmayer/coverband) will report which methods are _actually_ called by your _actual_ production code\n\n## Development\n\nAfter checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests.\n\nTo install this gem onto your local machine, run `bundle exec rake install`.\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/robotdana/leftovers.\n\nI especially encourage issues and improvements to the default config, whether expanding the existing config/*.yml or adding new gems.\nThe file should be named `[rubygems name].yml` and its structure is identical to the [project config](#configuration)\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobotdana%2Fleftovers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobotdana%2Fleftovers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobotdana%2Fleftovers/lists"}