runtimeanalyz.ing

← All capabilities

what_calls

CLI · LSP · MCP free

The callers of a method. Every caller of a method in the recorded runs, with the file and line of each call and how often it was made, including calls made through public_send. what_it_calls lists the methods it calls.

Invoice app code
debit ( total Money )
invoice.rb:53 · 1 call
Finance::Accounts receives
module Finance
  class Accounts
    def debit(account, amount, memo:) = …
  end
end
Transfer app code
public_send ( :debit Symbol )
transfer.rb:9 · 5 calls
Refund app code
debit ( amount Money )
refund.rb:9 · 7 calls
NightlyFeesJob grep match only
debit
Ledger#debit, a different class
Each recorded edge gives the method that made the call, the line it was made from, and the method that received it. A call through public_send goes through the same wrapper as a direct call and is recorded. A method of the same name on another class is a different method and is not listed.

The problem

You’re about to change Finance::Accounts#debit and want to know who calls it, so you search:

$ grep -rn "debit" app lib
app/models/invoice.rb:53:    accounts.debit(account, total, memo: number)
app/models/ledger.rb:6:  def debit(amount, memo:)
app/models/ledger.rb:7:    @lines << [:debit, amount, memo]
app/finance/finance/accounts.rb:14:    def debit(account, amount, memo:)
app/jobs/nightly_fees_job.rb:7:      ledger.debit(account.plan.monthly_fee, memo: "fees #{account.id}")
app/services/refund.rb:9:    entry = ledger.debit(@invoice.account, @invoice.total, memo: "refund #{@invoice.number}")
app/services/fee_schedule.rb:6:    accounts.debit(account, fee, memo: "fee")
app/services/transfer.rb:2:  def initialize(account, amount, direction: :debit)
app/billing/billing/checkout.rb:12:      Finance::Accounts.new.debit(order.account, order.total, memo: "#{order.number} #{card.masked}")

The list includes lines that are not callers and leaves out a caller. Two lines are in Ledger, a different class with its own #debit. ledger.debit appears twice, in Refund and in the nightly job, and neither line says whether ledger is a Ledger or a Finance::Accounts. Transfer matches only on a default argument. Its call is on line 9, through public_send(@direction, ...), where the word debit does not appear.

An agent asked the same question runs the same search and gets the same list.

The fix

Ask the recording:

$ ra what_calls Finance::Accounts#debit

Finance::Accounts#debit
· 7 callers in 2 recorded runs
  Billing::Checkout#complete     app/billing/billing/checkout.rb:12  63
  FeeSchedule#charge             app/services/fee_schedule.rb:6      12
  Refund#process                 app/services/refund.rb:9             7
  Transfer#call                  app/services/transfer.rb:9           5  via public_send
  spec/finance/accounts_spec.rb  spec/finance/accounts_spec.rb:7      2  its own spec
  Invoice#settle                 app/models/invoice.rb:53             1
  bin/traffic                    bin/traffic:44                       1

The report lists seven callers. They include the public_send call in Transfer#call, which grep had no line for. Refund#process is among them, so its ledger is a Finance::Accounts, and the nightly job is absent, so its ledger is the other class. The two recorded runs are the spec suite and a scripted traffic run, so the counts say how often each caller called the method in those runs. The change affects five callers in app code, a spec and a script.

what_it_calls answers the reverse question and lists the methods it calls:

$ ra what_it_calls Finance::Accounts#debit

Finance::Accounts#debit
· calls 10 methods
  Account#balance                              182
  Money#-                                      178
  Money#<=>                                     91
  Account#balance=                              89
  Money.zero                                    89
  Finance::Ledger#record                        89
  Reporting::Formatters::Currency#initialize    89
  Reporting::Formatters::Currency#to_ledger_s   89
  Finance::Audit#log                            89
  Money#to_s                                     4

Where it shows up

  • In your editor (LSP), “Find references” on a method returns the recorded call sites, with the file and line each call was made from.
  • Over MCP, what_calls returns the same table as structured blocks. Your agent can ask it before editing a method and get the callers in one call, in place of a page of grep output.
  • On the command line, ra what_calls and ra what_it_calls take any Class#method or Class.method, or a bare method name when one class alone defines it.

How it works

Every call into a method defined in your app is recorded as an edge: the method that made the call, the file and line it was made from, and the method that received it. what_calls groups those edges by caller and counts them. A call made from code that is not traced, a spec body or a script, has no calling method, so it is listed under its file, and a spec file named after the class is marked as the method’s own spec.

The recorder wraps the method itself, so every way of calling it is recorded the same way. A direct call, send, public_send, a callback or a method name built from a string all go through the same wrapper. The via public_send note comes from reading the source line at the call site.

The receiver’s class is part of the edge, so Finance::Accounts#debit and Ledger#debit are recorded as two separate methods.

Run it on your app

The output on this page comes from our example Rails app, and it is regenerated whenever a tool changes. These are the commands behind it. On your own app, run ra record first, then put your own class, method or file in their place.

ra what_calls 'Finance::Accounts#debit'
ra what_it_calls 'Finance::Accounts#debit'

The method is app/finance/finance/accounts.rb:14. The public_send caller is app/services/transfer.rb:9 and the other debit, Ledger#debit, is app/models/ledger.rb:6.

Reading the result

  • Calls into your own classes are recorded. A caller inside a gem that calls back into your code is listed at the point where it enters your code, and the gem method’s own name is not shown.
  • The counts measure traffic in what you recorded. The 63 calls from Billing::Checkout#complete are the checkouts the traffic script ran. They are not a measure of how often production calls it.

Every tool reads the same recording. What gets recorded and how far to trust an answer are on the questions page.

how_it_got_here

CLI · MCP Pro

How execution got here. The call chains that reached a method, in call order, taken from recorded runs. It is the stack trace you'd have got if the method had raised, for every route into it.

See more →

what_a_change_touches

CLI · MCP Pro

What a signature change affects. For each caller of a method, the argument classes it passed and the messages it sent to the return value, so you can see which callers a signature change affects before you make it.

See more →

dead_api

LSP · CLI Pro

Find dead public API. The public methods that no caller reached in any recorded run, including those whose only caller is their own spec. Shown as a hint in your editor.

See more →