[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