Branch: refs/heads/master Author: Colomban Wendling ban@herbesfolles.org Committer: Colomban Wendling ban@herbesfolles.org Date: Mon, 14 Mar 2016 18:27:22 UTC Commit: 1ed29f1d7b948e7d7fde70499491673e65a04954 https://github.com/geany/geany/commit/1ed29f1d7b948e7d7fde70499491673e65a049...
Log Message: ----------- ruby: Fix parsing qualified identifiers
The implementation is a bit hacky, but avoids the need for complex logic to pop several scopes at once.
Closes universal-ctags/ctags#452.
Modified Paths: -------------- tagmanager/ctags/ruby.c tests/ctags/Makefile.am tests/ctags/ruby-namespaced-class.rb tests/ctags/ruby-namespaced-class.rb.tags
Modified: tagmanager/ctags/ruby.c 40 lines changed, 36 insertions(+), 4 deletions(-) =================================================================== @@ -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)
Modified: tests/ctags/Makefile.am 1 lines changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -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 \
Modified: tests/ctags/ruby-namespaced-class.rb 8 lines changed, 8 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,8 @@ +module A + module B + end +end + +class A::B::C; end + +puts A::B::C
Modified: tests/ctags/ruby-namespaced-class.rb.tags 4 lines changed, 4 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,4 @@ +# format=tagmanager +A�256�0 +B�256�A�0 +C�1�A.B�0
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).