[geany/geany] eaf6c8: ruby: Fix keyword matching
Colomban Wendling
git-noreply at xxxxx
Mon Mar 14 18:27:22 UTC 2016
Branch: refs/heads/master
Author: Colomban Wendling <ban at herbesfolles.org>
Committer: Colomban Wendling <ban at herbesfolles.org>
Date: Mon, 14 Mar 2016 18:27:22 UTC
Commit: eaf6c82af8f6f00b5231ea5254db3fb3a2569ad8
https://github.com/geany/geany/commit/eaf6c82af8f6f00b5231ea5254db3fb3a2569ad8
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).
More information about the Commits
mailing list