[geany/geany] 834122: JavaScript: fix handling of parentheses around an rvalue

Colomban Wendling git-noreply at xxxxx
Sun Aug 3 22:23:13 UTC 2014


Branch:      refs/heads/master
Author:      Colomban Wendling <ban at herbesfolles.org>
Committer:   Colomban Wendling <ban at herbesfolles.org>
Date:        Sun, 03 Aug 2014 22:23:13 UTC
Commit:      8341228ffa5a69970e85cddc7adb6d1f49f247d9
             https://github.com/geany/geany/commit/8341228ffa5a69970e85cddc7adb6d1f49f247d9

Log Message:
-----------
JavaScript: fix handling of parentheses around an rvalue

Properly skip parentheses around an rvalue, and then properly recognize
the surrounded value.  This allows to properly recognize e.g. rvalue
`({...})` as an object, or `(function(){})` as a function.  As the
implementation is tolerant regarding garbage after the statement,
function expressions called straight away (`(function(){})()`) are
implicitly supported.

This however removes support for the following invalid JavaScript
syntax that was previously supported as a function/method declaration:

	var func = () {}

This syntax is not present in the ECMA standard nor is supported by
popular JavaScript engines.

See:
 * http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
   section 13, "Function Definition"
 * http://ecma262-5.com/ELS5_HTML.htm#Section_13
 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope#Defining_functions


Modified Paths:
--------------
    tagmanager/ctags/js.c
    tests/ctags/Makefile.am
    tests/ctags/parenthesis-rvalue.js
    tests/ctags/parenthesis-rvalue.js.tags
    tests/ctags/simple.js

Modified: tagmanager/ctags/js.c
61 lines changed, 25 insertions(+), 36 deletions(-)
===================================================================
@@ -1368,8 +1368,17 @@ static boolean parseStatement (tokenInfo *const token, boolean is_inside_class)
 
 	if ( isType (token, TOKEN_EQUAL_SIGN) )
 	{
+		int parenDepth = 0;
+
 		readToken (token);
 
+		/* rvalue might be surrounded with parentheses */
+		while (isType (token, TOKEN_OPEN_PAREN))
+		{
+			parenDepth++;
+			readToken (token);
+		}
+
 		if ( isKeyword (token, KEYWORD_function) )
 		{
 			readToken (token);
@@ -1426,37 +1435,9 @@ static boolean parseStatement (tokenInfo *const token, boolean is_inside_class)
 
 					if ( vStringLength(secondary_name->string) > 0 )
 						makeFunctionTag (secondary_name);
-
-					/*
-					 * Find to the end of the statement
-					 */
-					goto cleanUp;
 				}
 			}
 		}
-		else if (isType (token, TOKEN_OPEN_PAREN))
-		{
-			/*
-			 * Handle nameless functions
-			 *     this.method_name = () {}
-			 * Also assignments starting with parentheses
-			 *     var foo = (1 + 2) * 3;
-			 */
-			skipArgumentList(token);
-
-			if (isType (token, TOKEN_OPEN_CURLY))
-			{
-				/*
-				 * Nameless functions are only setup as methods.
-				 */
-				makeJsTag (name, JSTAG_METHOD);
-				parseBlock (token, name);
-			}
-			else if (isType (token, TOKEN_CLOSE_CURLY))
-				is_terminated = FALSE;
-			else if (token->nestLevel == 0 && is_global)
-				makeJsTag (name, JSTAG_VARIABLE);
-		}
 		else if (isType (token, TOKEN_OPEN_CURLY))
 		{
 			/*
@@ -1506,11 +1487,7 @@ static boolean parseStatement (tokenInfo *const token, boolean is_inside_class)
 					if ( ! stringListHas(FunctionNames, vStringValue (fulltag)) &&
 							! stringListHas(ClassNames, vStringValue (fulltag)) )
 					{
-						readToken (token);
-						if ( ! isType (token, TOKEN_SEMICOLON)) 
-							findCmdTerm (token);
-						if (isType (token, TOKEN_SEMICOLON)) 
-							makeJsTag (name, JSTAG_VARIABLE);
+						makeJsTag (name, JSTAG_VARIABLE);
 					}
 					vStringDelete (fulltag);
 				}
@@ -1598,13 +1575,25 @@ static boolean parseStatement (tokenInfo *const token, boolean is_inside_class)
 				if ( ! stringListHas(FunctionNames, vStringValue (fulltag)) &&
 						! stringListHas(ClassNames, vStringValue (fulltag)) )
 				{
-					findCmdTerm (token);
-					if (isType (token, TOKEN_SEMICOLON))
-						makeJsTag (name, JSTAG_VARIABLE);
+					makeJsTag (name, JSTAG_VARIABLE);
 				}
 				vStringDelete (fulltag);
 			}
 		}
+
+		if (parenDepth > 0)
+		{
+			while (parenDepth > 0)
+			{
+				if (isType (token, TOKEN_OPEN_PAREN))
+					parenDepth++;
+				else if (isType (token, TOKEN_CLOSE_PAREN))
+					parenDepth--;
+				readToken (token);
+			}
+			if (isType (token, TOKEN_CLOSE_CURLY))
+				is_terminated = FALSE;
+		}
 	}
 
 	/* if we aren't already at the cmd end, advance to it and check whether


Modified: tests/ctags/Makefile.am
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -200,6 +200,7 @@ test_sources = \
 	objectivec_protocol.mm			\
 	Package.pm						\
 	php5_5_class_kw.php				\
+	parenthesis-rvalue.js			\
 	preprocessor.f90				\
 	procedure_pointer_module.f90	\
 	procpoint.f90					\


Modified: tests/ctags/parenthesis-rvalue.js
35 lines changed, 35 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,35 @@
+
+// plain values
+var a1 = 42;
+var a2 = (42);
+
+// functions
+var b1 = function(){
+  function b1sub(){}
+};
+var b2 = (function(){
+  function b2sub(){}
+});
+var b3 = ((function(){
+  function b3sub(){}
+}));
+
+// objects
+var c1 = {};
+var c2 = ({});
+var d1 = {a:'hello',b:'hi'};
+var d2 = ({a:'hello',b:'hi'});
+
+// function expressions called straight away
+var e1 = function(){
+  function e1sub(){}
+  return 42;
+}();
+var e2 = (function(){
+  function e2sub(){}
+  return 42
+})();
+var e3 = ((function(){
+  function e3sub(){}
+  return 42
+})());


Modified: tests/ctags/parenthesis-rvalue.js.tags
23 lines changed, 23 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,23 @@
+# format=tagmanager
+a�64�d1�0
+a�64�d2�0
+a1�16384�0
+a2�16384�0
+b�64�d1�0
+b�64�d2�0
+b1�16�0
+b1sub�16�b1�0
+b2�16�0
+b2sub�16�b2�0
+b3�16�0
+b3sub�16�b3�0
+c1�16384�0
+c2�16384�0
+d1�1�0
+d2�1�0
+e1�16�0
+e1sub�16�e1�0
+e2�16�0
+e2sub�16�e2�0
+e3�16�0
+e3sub�16�e3�0


Modified: tests/ctags/simple.js
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -69,7 +69,7 @@ ValidClassTwo = function ()
     this.validMethodThree = function() {}
 
     // unnamed method
-    this.validMethodFour = () {}
+    this.validMethodFour = function() {}
 }
 
 var my_global_var4 = document.getElementsByTagName("input");



--------------
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