diff options
author | Nobuyoshi Nakada <[email protected]> | 2018-12-13 21:49:05 +0900 |
---|---|---|
committer | Nobuyoshi Nakada <[email protected]> | 2019-06-23 01:46:38 +0900 |
commit | 93843830198ba436e2ea21a60a11758d47cf521b (patch) | |
tree | 0ad4617c10a4474f8a1357006b76bd66ee04f4fb /variable.c | |
parent | 5084233b88cc48a74b58690423df1129668d5706 (diff) |
Module#constant_source_location [Feature #10771]
Diffstat (limited to 'variable.c')
-rw-r--r-- | variable.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/variable.c b/variable.c index 296e58a742..9dc1a3052c 100644 --- a/variable.c +++ b/variable.c @@ -2483,6 +2483,62 @@ undefined_constant(VALUE mod, VALUE name) mod, name); } +static VALUE +rb_const_location_from(VALUE klass, ID id, int exclude, int recurse, int visibility) +{ + while (RTEST(klass)) { + rb_const_entry_t *ce; + + while ((ce = rb_const_lookup(klass, id))) { + if (visibility && RB_CONST_PRIVATE_P(ce)) { + return Qnil; + } + if (exclude && klass == rb_cObject) { + goto not_found; + } + if (NIL_P(ce->file)) return rb_ary_new(); + return rb_assoc_new(ce->file, INT2NUM(ce->line)); + } + if (!recurse) break; + klass = RCLASS_SUPER(klass); + } + + not_found: + return Qnil; +} + +static VALUE +rb_const_location(VALUE klass, ID id, int exclude, int recurse, int visibility) +{ + VALUE loc; + + if (klass == rb_cObject) exclude = FALSE; + loc = rb_const_location_from(klass, id, exclude, recurse, visibility); + if (!NIL_P(loc)) return loc; + if (exclude) return loc; + if (BUILTIN_TYPE(klass) != T_MODULE) return loc; + /* search global const too, if klass is a module */ + return rb_const_location_from(rb_cObject, id, FALSE, recurse, visibility); +} + +VALUE +rb_const_source_location_from(VALUE klass, ID id) +{ + return rb_const_location(klass, id, TRUE, TRUE, FALSE); +} + +VALUE +rb_const_source_location(VALUE klass, ID id) +{ + return rb_const_location(klass, id, FALSE, TRUE, FALSE); +} + +VALUE +rb_const_source_location_at(VALUE klass, ID id) +{ + return rb_const_location(klass, id, TRUE, FALSE, FALSE); +} + /* * call-seq: * remove_const(sym) -> obj |