Branch: refs/heads/master Author: Colomban Wendling ban@herbesfolles.org Committer: Colomban Wendling ban@herbesfolles.org Date: Sun, 03 Aug 2014 22:23:13 UTC Commit: 8341228ffa5a69970e85cddc7adb6d1f49f247d9 https://github.com/geany/geany/commit/8341228ffa5a69970e85cddc7adb6d1f49f247...
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_...
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).