summaryrefslogtreecommitdiff
path: root/variable.c
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2018-12-13 21:49:05 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2019-06-23 01:46:38 +0900
commit93843830198ba436e2ea21a60a11758d47cf521b (patch)
tree0ad4617c10a4474f8a1357006b76bd66ee04f4fb /variable.c
parent5084233b88cc48a74b58690423df1129668d5706 (diff)
Module#constant_source_location [Feature #10771]
Diffstat (limited to 'variable.c')
-rw-r--r--variable.c56
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