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: eaf6c82af8f6f00b5231ea5254db3fb3a2569ad8 https://github.com/geany/geany/commit/eaf6c82af8f6f00b5231ea5254db3fb3a2569a...
Log Message: ----------- ruby: Fix keyword matching
After an identifier there can be anything but an identifier character.
Modified Paths: -------------- tagmanager/ctags/ruby.c tests/ctags/Makefile.am tests/ctags/ruby-block-call.rb tests/ctags/ruby-block-call.rb.tags
Modified: tagmanager/ctags/ruby.c 62 lines changed, 45 insertions(+), 17 deletions(-) =================================================================== @@ -78,7 +78,8 @@ static vString* stringListToScope (const stringList* list) * Returns TRUE if it did, FALSE (and leaves 's' where * it was) otherwise. */ -static boolean canMatch (const unsigned char** s, const char* literal) +static boolean canMatch (const unsigned char** s, const char* literal, + boolean (*end_check) (int)) { const int literal_length = strlen (literal); const int s_length = strlen ((const char *)*s); @@ -92,7 +93,7 @@ static boolean canMatch (const unsigned char** s, const char* literal) return FALSE; } /* Additionally check that we're at the end of a token. */ - if ( ! (next_char == 0 || isspace (next_char) || next_char == '(' || next_char == ';')) + if (! end_check (next_char)) { return FALSE; } @@ -100,6 +101,31 @@ static boolean canMatch (const unsigned char** s, const char* literal) return TRUE; }
+static boolean notIdentChar (int c) +{ + return ! (isalnum (c) || c == '_'); +} + +static boolean notOperatorChar (int c) +{ + return ! (c == '[' || c == ']' || + c == '=' || c == '!' || c == '~' || + c == '+' || c == '-' || + c == '@' || c == '*' || c == '/' || c == '%' || + c == '<' || c == '>' || + c == '&' || c == '^' || c == '|'); +} + +static boolean isWhitespace (int c) +{ + return c == 0 || isspace (c); +} + +static boolean canMatchKeyword (const unsigned char** s, const char* literal) +{ + return canMatch (s, literal, notIdentChar); +} + /* * Attempts to advance 'cp' past a Ruby operator method name. Returns * TRUE if successful (and copies the name into 'name'), FALSE otherwise. @@ -123,7 +149,7 @@ static boolean parseRubyOperator (vString* name, const unsigned char** cp) int i; for (i = 0; RUBY_OPERATORS[i] != NULL; ++i) { - if (canMatch (cp, RUBY_OPERATORS[i])) + if (canMatch (cp, RUBY_OPERATORS[i], notOperatorChar)) { vStringCatS (name, RUBY_OPERATORS[i]); return TRUE; @@ -321,12 +347,12 @@ static void findRubyTags (void) * separators are "do", ";" or newline */ boolean expect_separator = FALSE;
- if (canMatch (&cp, "=begin")) + if (canMatch (&cp, "=begin", isWhitespace)) { inMultiLineComment = TRUE; continue; } - if (canMatch (&cp, "=end")) + if (canMatch (&cp, "=end", isWhitespace)) { inMultiLineComment = FALSE; continue; @@ -353,14 +379,16 @@ static void findRubyTags (void) * puts("hello") \ * unless <exp> */ - if (canMatch (&cp, "for") || canMatch (&cp, "until") || - canMatch (&cp, "while")) + if (canMatchKeyword (&cp, "for") || + canMatchKeyword (&cp, "until") || + canMatchKeyword (&cp, "while")) { expect_separator = TRUE; enterUnnamedScope (); } - else if (canMatch (&cp, "case") || canMatch (&cp, "if") || - canMatch (&cp, "unless")) + else if (canMatchKeyword (&cp, "case") || + canMatchKeyword (&cp, "if") || + canMatchKeyword (&cp, "unless")) { enterUnnamedScope (); } @@ -369,23 +397,23 @@ static void findRubyTags (void) * "module M", "class C" and "def m" should only be at the beginning * of a line. */ - if (canMatch (&cp, "module")) + if (canMatchKeyword (&cp, "module")) { readAndEmitTag (&cp, K_MODULE); } - else if (canMatch (&cp, "class")) + else if (canMatchKeyword (&cp, "class")) { readAndEmitTag (&cp, K_CLASS); } - else if (canMatch (&cp, "def")) + else if (canMatchKeyword (&cp, "def")) { readAndEmitTag (&cp, K_METHOD); } - else if (canMatch (&cp, "describe")) + else if (canMatchKeyword (&cp, "describe")) { readAndEmitTag (&cp, K_DESCRIBE); } - else if (canMatch (&cp, "context")) + else if (canMatchKeyword (&cp, "context")) { readAndEmitTag (&cp, K_CONTEXT); } @@ -410,18 +438,18 @@ static void findRubyTags (void) */ break; } - else if (canMatch (&cp, "begin")) + else if (canMatchKeyword (&cp, "begin")) { enterUnnamedScope (); } - else if (canMatch (&cp, "do")) + else if (canMatchKeyword (&cp, "do")) { if (! expect_separator) enterUnnamedScope (); else expect_separator = FALSE; } - else if (canMatch (&cp, "end") && stringListCount (nesting) > 0) + else if (canMatchKeyword (&cp, "end") && stringListCount (nesting) > 0) { /* Leave the most recent scope. */ vStringDelete (stringListLast (nesting));
Modified: tests/ctags/Makefile.am 1 lines changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -255,6 +255,7 @@ test_sources = \ regexp.js \ return-hint.zep \ return-types.go \ + ruby-block-call.rb \ ruby-doc.rb \ ruby-sf-bug-364.rb \ rules.t2t \
Modified: tests/ctags/ruby-block-call.rb 10 lines changed, 10 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,10 @@ + +def plop + [ 1, 2, 3, 4 ].each do |x| + x > 0 + end.all? +end + +def nothing + puts "nothing" +end
Modified: tests/ctags/ruby-block-call.rb.tags 3 lines changed, 3 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,3 @@ +# format=tagmanager +nothing�128�0 +plop�128�0
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).