diff --git a/tagmanager/ctags/ruby.c b/tagmanager/ctags/ruby.c index ec9b9ec0..f9a987bd 100644 --- a/tagmanager/ctags/ruby.c +++ b/tagmanager/ctags/ruby.c @@ -43,6 +43,8 @@ static kindOption RubyKinds [] = { static stringList* nesting = NULL; +#define SCOPE_SEPARATOR '.' + /* * FUNCTION DEFINITIONS */ @@ -66,7 +68,8 @@ static vString* stringListToScope (const stringList* list) vString* chunk = stringListItem (list, i); if (vStringLength (chunk) > 0) { - vStringCatS (result, (chunks_output++ > 0) ? "." : ""); + if (chunks_output++ > 0) + vStringPut (result, SCOPE_SEPARATOR); vStringCatS (result, vStringValue (chunk)); } } @@ -165,6 +168,8 @@ static void emitRubyTag (vString* name, rubyKind kind) { tagEntryInfo tag; vString* scope; + const char *unqualified_name; + const char *qualified_name; if (!RubyKinds[kind].enabled) { return; @@ -173,7 +178,23 @@ static void emitRubyTag (vString* name, rubyKind kind) vStringTerminate (name); scope = stringListToScope (nesting); - initTagEntry (&tag, vStringValue (name)); + qualified_name = vStringValue (name); + unqualified_name = strrchr (qualified_name, SCOPE_SEPARATOR); + if (unqualified_name && unqualified_name[1]) + { + if (unqualified_name > qualified_name) + { + if (vStringLength (scope) > 0) + vStringPut (scope, SCOPE_SEPARATOR); + vStringNCatS (scope, qualified_name, + unqualified_name - qualified_name); + } + unqualified_name++; + } + else + unqualified_name = qualified_name; + + initTagEntry (&tag, unqualified_name); if (vStringLength (scope) > 0) { tag.extensionFields.scope [0] = "class"; tag.extensionFields.scope [1] = vStringValue (scope); @@ -215,6 +236,7 @@ static rubyKind parseIdentifier ( * point or equals sign. These are all part of the name. * A method name may also contain a period if it's a singleton method. */ + boolean had_sep = FALSE; const char* also_ok; if (kind == K_METHOD) { @@ -251,11 +273,21 @@ static rubyKind parseIdentifier ( } /* Copy the identifier into 'name'. */ - while (**cp != 0 && (isalnum (**cp) || charIsIn (**cp, also_ok))) + while (**cp != 0 && (**cp == ':' || isalnum (**cp) || charIsIn (**cp, also_ok))) { char last_char = **cp; - vStringPut (name, last_char); + if (last_char == ':') + had_sep = TRUE; + else + { + if (had_sep) + { + vStringPut (name, SCOPE_SEPARATOR); + had_sep = FALSE; + } + vStringPut (name, last_char); + } ++*cp; if (kind == K_METHOD) diff --git a/tests/ctags/Makefile.am b/tests/ctags/Makefile.am index e790cb25..c0670124 100644 --- a/tests/ctags/Makefile.am +++ b/tests/ctags/Makefile.am @@ -257,6 +257,7 @@ test_sources = \ return-types.go \ ruby-block-call.rb \ ruby-doc.rb \ + ruby-namespaced-class.rb \ ruby-sf-bug-364.rb \ rules.t2t \ sample.t2t \ diff --git a/tests/ctags/ruby-namespaced-class.rb b/tests/ctags/ruby-namespaced-class.rb new file mode 100644 index 00000000..17c11c36 --- /dev/null +++ b/tests/ctags/ruby-namespaced-class.rb @@ -0,0 +1,8 @@ +module A + module B + end +end + +class A::B::C; end + +puts A::B::C diff --git a/tests/ctags/ruby-namespaced-class.rb.tags b/tests/ctags/ruby-namespaced-class.rb.tags new file mode 100644 index 00000000..0c272115 --- /dev/null +++ b/tests/ctags/ruby-namespaced-class.rb.tags @@ -0,0 +1,4 @@ +# format=tagmanager +AÌ256Ö0 +BÌ256ÎAÖ0 +CÌ1ÎA.BÖ0