Feature #21543 ยป poc.patch
| compile.c | ||
|---|---|---|
|
rb_id2str(mid),
|
||
|
ISEQ_TYPE_METHOD, line);
|
||
|
#ifdef USE_ISEQ_NODE_ID
|
||
|
// Store the DefNode's node_id in the method iseq location
|
||
|
ISEQ_BODY(method_iseq)->location.node_id = nd_node_id(node);
|
||
|
#endif
|
||
|
debugp_param("defn/iseq", rb_iseqw_new(method_iseq));
|
||
|
ADD_INSN2(ret, node, definemethod, ID2SYM(mid), method_iseq);
|
||
|
RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)method_iseq);
|
||
| ... | ... | |
|
rb_id2str(mid),
|
||
|
ISEQ_TYPE_METHOD, line);
|
||
|
#ifdef USE_ISEQ_NODE_ID
|
||
|
// Store the DefNode's node_id in the singleton method iseq location
|
||
|
ISEQ_BODY(singleton_method_iseq)->location.node_id = nd_node_id(node);
|
||
|
#endif
|
||
|
debugp_param("defs/iseq", rb_iseqw_new(singleton_method_iseq));
|
||
|
CHECK(COMPILE(ret, "defs: recv", RNODE_DEFS(node)->nd_recv));
|
||
|
ADD_INSN2(ret, node, definesmethod, ID2SYM(mid), singleton_method_iseq);
|
||
| lib/error_highlight/base.rb | ||
|---|---|---|
|
when :OP_CDECL
|
||
|
spot_op_cdecl
|
||
|
when :DEFN
|
||
|
raise NotImplementedError if @point_type != :name
|
||
|
spot_defn
|
||
|
when :DEFS
|
||
|
raise NotImplementedError if @point_type != :name
|
||
|
spot_defs
|
||
|
when :call_node
|
||
|
case @point_type
|
||
|
when :name
|
||
| ... | ... | |
|
when :constant_path_operator_write_node
|
||
|
prism_spot_constant_path_operator_write
|
||
|
when :def_node
|
||
|
case @point_type
|
||
|
when :name
|
||
|
prism_spot_def_for_name
|
||
|
when :args
|
||
|
raise NotImplementedError
|
||
|
end
|
||
|
end
|
||
|
if @snippet && @beg_column && @end_column && @beg_column < @end_column
|
||
| ... | ... | |
|
end
|
||
|
end
|
||
|
# Example:
|
||
|
# def bar; end
|
||
|
# ^^^
|
||
|
def spot_defn
|
||
|
mid, = @node.children
|
||
|
fetch_line(@node.first_lineno)
|
||
|
if @snippet.match(/\Gdef\s+(#{ Regexp.quote(mid) }\b)/, @node.first_column)
|
||
|
@beg_column = $~.begin(1)
|
||
|
@end_column = $~.end(1)
|
||
|
end
|
||
|
end
|
||
|
# Example:
|
||
|
# def Foo.bar; end
|
||
|
# ^^^^
|
||
|
def spot_defs
|
||
|
nd_recv, mid, = @node.children
|
||
|
fetch_line(nd_recv.last_lineno)
|
||
|
if @snippet.match(/\G\s*(\.\s*#{ Regexp.quote(mid) }\b)/, nd_recv.last_column)
|
||
|
@beg_column = $~.begin(1)
|
||
|
@end_column = $~.end(1)
|
||
|
end
|
||
|
end
|
||
|
def fetch_line(lineno)
|
||
|
@beg_lineno = @end_lineno = lineno
|
||
|
@snippet = @fetch[lineno]
|
||
| ... | ... | |
|
prism_location(@node.binary_operator_loc.chop)
|
||
|
end
|
||
|
end
|
||
|
def prism_spot_def_for_name
|
||
|
location = @node.name_loc
|
||
|
location = location.join(@node.operator_loc) if @node.operator_loc
|
||
|
prism_location(location)
|
||
|
end
|
||
|
end
|
||
|
private_constant :Spotter
|
||
| lib/error_highlight/core_ext.rb | ||
|---|---|---|
|
module ErrorHighlight
|
||
|
module CoreExt
|
||
|
private def generate_snippet
|
||
|
spot = ErrorHighlight.spot(self)
|
||
|
return "" unless spot
|
||
|
return ErrorHighlight.formatter.message_for(spot)
|
||
|
if ArgumentError === self && message =~ /\Awrong number of arguments/
|
||
|
locs = self.backtrace_locations
|
||
|
return "" if locs.size < 2
|
||
|
callee_loc, caller_loc = locs
|
||
|
callee_spot = ErrorHighlight.spot(self, backtrace_location: callee_loc, point_type: :name)
|
||
|
return "" unless callee_spot
|
||
|
caller_spot = ErrorHighlight.spot(self, backtrace_location: caller_loc, point_type: :name)
|
||
|
return "" unless caller_spot
|
||
|
"\n\n" + [["caller", caller_loc, caller_spot], ["callee", callee_loc, callee_spot]].map do |msg, loc, spot|
|
||
|
_, _, snippet, highlight = ErrorHighlight.formatter.message_for(spot).lines
|
||
|
" #{ loc.path }:#{ loc.lineno }: #{ msg }\n | #{ snippet } #{ highlight }"
|
||
|
end.join("\n")
|
||
|
else
|
||
|
spot = ErrorHighlight.spot(self)
|
||
|
return "" unless spot
|
||
|
return ErrorHighlight.formatter.message_for(spot)
|
||
|
end
|
||
|
end
|
||
|
if Exception.method_defined?(:detailed_message)
|
||
| prism_compile.c | ||
|---|---|---|
|
rb_iseq_t *method_iseq = NEW_ISEQ(&next_scope_node, rb_id2str(method_name), ISEQ_TYPE_METHOD, location.line);
|
||
|
pm_scope_node_destroy(&next_scope_node);
|
||
|
#ifdef USE_ISEQ_NODE_ID
|
||
|
// Store the DefNode's node_id in the method iseq location for Prism
|
||
|
ISEQ_BODY(method_iseq)->location.node_id = (int)location.node_id;
|
||
|
#endif
|
||
|
if (cast->receiver) {
|
||
|
PM_COMPILE_NOT_POPPED(cast->receiver);
|
||
|
PUSH_INSN2(ret, location, definesmethod, ID2SYM(method_name), method_iseq);
|
||
| vm_backtrace.c | ||
|---|---|---|
|
}
|
||
|
if (lineno) *lineno = ISEQ_BODY(iseq)->location.first_lineno;
|
||
|
#ifdef USE_ISEQ_NODE_ID
|
||
|
if (node_id) *node_id = -1;
|
||
|
if (node_id) {
|
||
|
// Use the node_id stored in the iseq location
|
||
|
*node_id = ISEQ_BODY(iseq)->location.node_id;
|
||
|
}
|
||
|
#endif
|
||
|
return 1;
|
||
|
}
|
||
| ... | ... | |
|
static int
|
||
|
location_node_id(rb_backtrace_location_t *loc)
|
||
|
{
|
||
|
if (loc->iseq && loc->pc) {
|
||
|
if (loc->iseq) {
|
||
|
return calc_node_id(loc->iseq, loc->pc);
|
||
|
}
|
||
|
return -1;
|
||