You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby运行时能否获取call stack的行列范围而非仅文件名与起始行?

在Ruby中获取调用栈的行列范围

Ruby标准库的caller_locations默认仅返回调用的起始行号,不会包含结束行列信息——这是因为Ruby运行时在执行阶段已将代码编译为字节码,不再保留语法层面的调用范围数据。不过,不借助Prism等外部工具,我们可以通过Ruby内置的Ripper解析器结合调用栈信息,在运行时计算出调用的完整行列范围。

实现思路

  1. 用Ripper解析调用方文件的AST(抽象语法树),提前收集目标方法调用的起始/结束位置;
  2. 在方法内部,通过caller_locations获取调用的起始行和列(Ruby 2.6+支持column方法);
  3. 匹配预收集的位置数据,输出完整的行列区间。

代码示例

修改原sample.rb如下:

# sample.rb
require 'ripper'

# 解析指定文件,收集所有`sample`方法调用的位置范围
def collect_sample_call_ranges(filename)
  code = File.read(filename)
  call_ranges = {}

  # 递归遍历AST节点
  traverse = lambda do |node|
    return unless node.is_a?(Array)

    # 识别`sample`方法调用节点(适配Ripper AST结构)
    if node[0] == :call && 
       node[1].is_a?(Array) && node[1][0] == :var_ref && 
       node[1][1].is_a?(Array) && node[1][1][0] == :@ident && node[1][1][1] == 'sample'
      # 提取调用的起始/结束行列(Ripper节点位置格式:[type, start_line, start_col, end_line, end_col])
      pos = node[2]
      start_key = [pos[1], pos[2]]
      call_ranges[start_key] = [pos[3], pos[4]]
    end

    node.each { |child| traverse.call(child) }
  end

  traverse.call(Ripper.sexp(code))
  call_ranges
end

# 预收集当前文件中`sample`调用的位置范围
SAMPLE_CALL_RANGES = collect_sample_call_ranges(__FILE__)

def sample(a = nil, b = nil, c = nil, &block)
  yield if block_given?
  caller_locations.each do |loc|
    start_line = loc.lineno
    start_col = loc.column
    # 匹配预收集的范围并格式化输出
    if end_pos = SAMPLE_CALL_RANGES[[start_line, start_col]]
      end_line, end_col = end_pos
      puts "#{loc.path}:#{start_line}:#{start_col}-#{end_line}:#{end_col}:in '#{loc.label}'"
    else
      # 无匹配时输出默认格式
      puts loc
    end
  end
end

sample(
  1,
  2,
  3
)

sample do
  puts "lol"
end

执行效果

运行修改后的文件,输出将符合预期:

$ ruby sample.rb
sample.rb:8:0-12:1:in '<main>'
lol
sample.rb:14:0-16:3:in '<main>'

注意事项

  • 该方案依赖静态解析AST,仅能识别静态编写的方法调用,动态生成的调用(如send(:sample))无法匹配;
  • Ripper的AST结构可能随Ruby版本变动,需要根据使用的Ruby版本调整节点判断逻辑;
  • 若方法调用来自其他文件,需要解析对应文件的AST并收集位置信息。

内容的提问来源于stack exchange,提问作者schmijos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 11:27:24