[geany/geany] d0986d: Merge branch 'js-update'

Colomban Wendling git-noreply at xxxxx
Mon Nov 24 02:55:55 UTC 2014


Branch:      refs/heads/master
Author:      Colomban Wendling <ban at herbesfolles.org>
Committer:   Colomban Wendling <ban at herbesfolles.org>
Date:        Mon, 24 Nov 2014 02:55:55 UTC
Commit:      d0986dd3f606dcd564bc99829ff993a94737fd22
             https://github.com/geany/geany/commit/d0986dd3f606dcd564bc99829ff993a94737fd22

Log Message:
-----------
Merge branch 'js-update'

Import back JavaScript parser changes from CTags and fishman/ctags.


Modified Paths:
--------------
    tagmanager/ctags/js.c
    tests/ctags/1795612.js.tags
    tests/ctags/1850914.js.tags
    tests/ctags/1878155.js
    tests/ctags/1878155.js.tags
    tests/ctags/1880687.js.tags
    tests/ctags/2023624.js.tags
    tests/ctags/3470609.js.tags
    tests/ctags/Makefile.am
    tests/ctags/arraylist.js.tags
    tests/ctags/bracematch.js.tags
    tests/ctags/bug1950327.js.tags
    tests/ctags/bug2888482.js.tags
    tests/ctags/bug3036476.js.tags
    tests/ctags/bug3571233.js.tags
    tests/ctags/complex-return.js.tags
    tests/ctags/js-class-related-unterminated.js
    tests/ctags/js-class-related-unterminated.js.tags
    tests/ctags/js-const.js
    tests/ctags/js-const.js.tags
    tests/ctags/js-implicit-semicolons.js
    tests/ctags/js-implicit-semicolons.js.tags
    tests/ctags/js-let.js
    tests/ctags/js-let.js.tags
    tests/ctags/js-scope.js
    tests/ctags/js-scope.js.tags
    tests/ctags/js-signature.js
    tests/ctags/js-signature.js.tags
    tests/ctags/js-sub-block-scope.js
    tests/ctags/js-sub-block-scope.js.tags
    tests/ctags/js-unknown-construct-nesting.js
    tests/ctags/js-unknown-construct-nesting.js.tags
    tests/ctags/jsFunc_tutorial.js.tags
    tests/ctags/no_terminator.js.tags
    tests/ctags/parenthesis-rvalue.js.tags
    tests/ctags/regexp.js.tags
    tests/ctags/secondary_fcn_name.js.tags
    tests/ctags/shebang.js.tags
    tests/ctags/simple.js.tags
    tests/ctags/ui5.controller.js
    tests/ctags/ui5.controller.js.tags

Modified: tagmanager/ctags/js.c
395 lines changed, 293 insertions(+), 102 deletions(-)
===================================================================
@@ -58,6 +58,8 @@ typedef enum eKeywordId {
 	KEYWORD_capital_object,
 	KEYWORD_prototype,
 	KEYWORD_var,
+	KEYWORD_let,
+	KEYWORD_const,
 	KEYWORD_new,
 	KEYWORD_this,
 	KEYWORD_for,
@@ -69,6 +71,7 @@ typedef enum eKeywordId {
 	KEYWORD_try,
 	KEYWORD_catch,
 	KEYWORD_finally,
+	KEYWORD_sap,
 	KEYWORD_return
 } keywordId;
 
@@ -99,7 +102,9 @@ typedef enum eTokenType {
 	TOKEN_FORWARD_SLASH,
 	TOKEN_OPEN_SQUARE,
 	TOKEN_CLOSE_SQUARE,
-	TOKEN_REGEXP
+	TOKEN_REGEXP,
+	TOKEN_POSTFIX_OPERATOR,
+	TOKEN_BINARY_OPERATOR
 } tokenType;
 
 typedef struct sTokenInfo {
@@ -128,6 +133,7 @@ typedef enum {
 	JSTAG_CLASS,
 	JSTAG_METHOD,
 	JSTAG_PROPERTY,
+	JSTAG_CONSTANT,
 	JSTAG_VARIABLE,
 	JSTAG_COUNT
 } jsKind;
@@ -137,6 +143,7 @@ static kindOption JsKinds [] = {
 	{ TRUE,  'c', "class",		  "classes"			   },
 	{ TRUE,  'm', "method",		  "methods"			   },
 	{ TRUE,  'p', "member",		  "properties"		   },
+	{ TRUE,  'C', "macro",		  "constants"		   },
 	{ TRUE,  'v', "variable",	  "global variables"   }
 };
 
@@ -147,6 +154,8 @@ static const keywordDesc JsKeywordTable [] = {
 	{ "Object",		KEYWORD_capital_object		},
 	{ "prototype",	KEYWORD_prototype			},
 	{ "var",		KEYWORD_var					},
+	{ "let",		KEYWORD_let					},
+	{ "const",		KEYWORD_const				},
 	{ "new",		KEYWORD_new					},
 	{ "this",		KEYWORD_this				},
 	{ "for",		KEYWORD_for					},
@@ -158,6 +167,7 @@ static const keywordDesc JsKeywordTable [] = {
 	{ "try",		KEYWORD_try					},
 	{ "catch",		KEYWORD_catch				},
 	{ "finally",	KEYWORD_finally				},
+	{ "sap",	    KEYWORD_sap    				},
 	{ "return",		KEYWORD_return				}
 };
 
@@ -167,8 +177,9 @@ static const keywordDesc JsKeywordTable [] = {
 
 /* Recursive functions */
 static void parseFunction (tokenInfo *const token);
-static boolean parseBlock (tokenInfo *const token, tokenInfo *const parent);
-static boolean parseLine (tokenInfo *const token, boolean is_inside_class);
+static boolean parseBlock (tokenInfo *const token, tokenInfo *const orig_parent);
+static boolean parseLine (tokenInfo *const token, tokenInfo *const parent, boolean is_inside_class);
+static void parseUI5 (tokenInfo *const token);
 
 static boolean isIdentChar (const int c)
 {
@@ -216,7 +227,7 @@ static void deleteToken (tokenInfo *const token)
  *	 Tag generation functions
  */
 
-static void makeJsTag (tokenInfo *const token, const jsKind kind)
+static void makeJsTag (tokenInfo *const token, const jsKind kind, vString *const signature)
 {
 	if (JsKinds [kind].enabled && ! token->ignoreTag )
 	{
@@ -253,14 +264,30 @@ static void makeJsTag (tokenInfo *const token, const jsKind kind)
 			e.extensionFields.scope[1] = vStringValue (fullscope);
 		}
 
-		makeTagEntry (&e);
+		if (signature && vStringLength(signature))
+		{
+			size_t i;
+			/* sanitize signature by replacing all control characters with a
+			 * space (because it's simple).
+			 * there should never be any junk in a valid signature, but who
+			 * knows what the user wrote and CTags doesn't cope well with weird
+			 * characters. */
+			for (i = 0; i < signature->length; i++)
+			{
+				unsigned char c = (unsigned char) signature->buffer[i];
+				if (c < 0x20 /* below space */ || c == 0x7F /* DEL */)
+					signature->buffer[i] = ' ';
+			}
+			e.extensionFields.arglist = vStringValue(signature);
+		}
 
+		makeTagEntry (&e);
 		vStringDelete (fullscope);
 	}
 }
 
-static void makeClassTag (tokenInfo *const token)
-{ 
+static void makeClassTag (tokenInfo *const token, vString *const signature)
+{
 	vString *	fulltag;
 
 	if ( ! token->ignoreTag )
@@ -280,14 +307,14 @@ static void makeClassTag (tokenInfo *const token)
 		if ( ! stringListHas(ClassNames, vStringValue (fulltag)) )
 		{
 			stringListAdd (ClassNames, vStringNewCopy (fulltag));
-			makeJsTag (token, JSTAG_CLASS);
+			makeJsTag (token, JSTAG_CLASS, signature);
 		}
 		vStringDelete (fulltag);
 	}
 }
 
-static void makeFunctionTag (tokenInfo *const token)
-{ 
+static void makeFunctionTag (tokenInfo *const token, vString *const signature)
+{
 	vString *	fulltag;
 
 	if ( ! token->ignoreTag )
@@ -307,7 +334,7 @@ static void makeFunctionTag (tokenInfo *const token)
 		if ( ! stringListHas(FunctionNames, vStringValue (fulltag)) )
 		{
 			stringListAdd (FunctionNames, vStringNewCopy (fulltag));
-			makeJsTag (token, JSTAG_FUNCTION);
+			makeJsTag (token, JSTAG_FUNCTION, signature);
 		}
 		vStringDelete (fulltag);
 	}
@@ -387,8 +414,7 @@ static void parseIdentifier (vString *const string, const int firstChar)
 		c = fileGetc ();
 	} while (isIdentChar (c));
 	vStringTerminate (string);
-	if (!isspace (c))
-		fileUngetc (c);		/* unget non-identifier character */
+	fileUngetc (c);		/* unget non-identifier character */
 }
 
 static keywordId analyzeToken (vString *const name)
@@ -401,24 +427,35 @@ static keywordId analyzeToken (vString *const name)
 	return result;
 }
 
-static void readToken (tokenInfo *const token)
+static void readTokenFull (tokenInfo *const token, boolean include_newlines, vString *const repr)
 {
 	int c;
+	int i;
 
 	token->type			= TOKEN_UNDEFINED;
 	token->keyword		= KEYWORD_NONE;
 	vStringClear (token->string);
 
 getNextChar:
+	i = 0;
 	do
 	{
 		c = fileGetc ();
+		i++;
 	}
-	while (c == '\t'  ||  c == ' ' ||  c == '\n');
+	while (c == '\t'  ||  c == ' ' ||
+		   ((c == '\r' || c == '\n') && ! include_newlines));
 
 	token->lineNumber   = getSourceLineNumber ();
 	token->filePosition = getInputFilePosition ();
 
+	if (repr)
+	{
+		if (i > 1)
+			vStringPut (repr, ' ');
+		vStringPut (repr, c);
+	}
+
 	switch (c)
 	{
 		case EOF: longjmp (Exception, (int)ExceptionEOF);	break;
@@ -434,12 +471,76 @@ static void readToken (tokenInfo *const token)
 		case '[': token->type = TOKEN_OPEN_SQUARE;			break;
 		case ']': token->type = TOKEN_CLOSE_SQUARE;			break;
 
+		case '+':
+		case '-':
+			{
+				int d = fileGetc ();
+				if (d == c) /* ++ or -- */
+					token->type = TOKEN_POSTFIX_OPERATOR;
+				else
+				{
+					fileUngetc (d);
+					token->type = TOKEN_BINARY_OPERATOR;
+				}
+				break;
+			}
+
+		case '*':
+		case '%':
+		case '?':
+		case '>':
+		case '<':
+		case '^':
+		case '|':
+		case '&':
+			token->type = TOKEN_BINARY_OPERATOR;
+			break;
+
+		case '\r':
+		case '\n':
+			/* This isn't strictly correct per the standard, but following the
+			 * real rules means understanding all statements, and that's not
+			 * what the parser currently does.  What we do here is a guess, by
+			 * avoiding inserting semicolons that would make the statement on
+			 * the left invalid.  Hopefully this should not have false negatives
+			 * (e.g. should not miss insertion of a semicolon) but might have
+			 * false positives (e.g. it will wrongfully emit a semicolon for the
+			 * newline in "foo\n+bar").
+			 * This should however be mostly harmless as we only deal with
+			 * newlines in specific situations where we know a false positive
+			 * wouldn't hurt too bad. */
+			switch (LastTokenType)
+			{
+				/* these cannot be the end of a statement, so hold the newline */
+				case TOKEN_EQUAL_SIGN:
+				case TOKEN_COLON:
+				case TOKEN_PERIOD:
+				case TOKEN_FORWARD_SLASH:
+				case TOKEN_BINARY_OPERATOR:
+				/* and these already end one, no need to duplicate it */
+				case TOKEN_SEMICOLON:
+				case TOKEN_COMMA:
+				case TOKEN_CLOSE_CURLY:
+				case TOKEN_OPEN_CURLY:
+					include_newlines = FALSE; /* no need to recheck */
+					goto getNextChar;
+					break;
+				default:
+					token->type = TOKEN_SEMICOLON;
+			}
+			break;
+
 		case '\'':
 		case '"':
 				  token->type = TOKEN_STRING;
 				  parseString (token->string, c);
 				  token->lineNumber = getSourceLineNumber ();
 				  token->filePosition = getInputFilePosition ();
+				  if (repr)
+				  {
+					  vStringCat (repr, token->string);
+					  vStringPut (repr, c);
+				  }
 				  break;
 
 		case '\\':
@@ -479,6 +580,8 @@ static void readToken (tokenInfo *const token)
 					  }
 					  else
 					  {
+						  if (repr) /* remove the / we added */
+							  repr->buffer[--repr->length] = 0;
 						  if (d == '*')
 						  {
 							  do
@@ -495,6 +598,9 @@ static void readToken (tokenInfo *const token)
 						  else if (d == '/')	/* is this the start of a comment?  */
 						  {
 							  skipToCharacter ('\n');
+							  /* if we care about newlines, put it back so it is seen */
+							  if (include_newlines)
+								  fileUngetc ('\n');
 							  goto getNextChar;
 						  }
 					  }
@@ -530,6 +636,8 @@ static void readToken (tokenInfo *const token)
 						  token->type = TOKEN_IDENTIFIER;
 					  else
 						  token->type = TOKEN_KEYWORD;
+					  if (repr && vStringLength (token->string) > 1)
+						  vStringCatS (repr, vStringValue (token->string) + 1);
 				  }
 				  break;
 	}
@@ -537,6 +645,11 @@ static void readToken (tokenInfo *const token)
 	LastTokenType = token->type;
 }
 
+static void readToken (tokenInfo *const token)
+{
+	readTokenFull (token, FALSE, NULL);
+}
+
 static void copyToken (tokenInfo *const dest, tokenInfo *const src)
 {
 	dest->nestLevel = src->nestLevel;
@@ -552,7 +665,7 @@ static void copyToken (tokenInfo *const dest, tokenInfo *const src)
  *	 Token parsing functions
  */
 
-static void skipArgumentList (tokenInfo *const token)
+static void skipArgumentList (tokenInfo *const token, boolean include_newlines, vString *const repr)
 {
 	int nest_level = 0;
 
@@ -566,9 +679,11 @@ static void skipArgumentList (tokenInfo *const token)
 	if (isType (token, TOKEN_OPEN_PAREN))	/* arguments? */
 	{
 		nest_level++;
+		if (repr)
+			vStringPut (repr, '(');
 		while (! (isType (token, TOKEN_CLOSE_PAREN) && (nest_level == 0)))
 		{
-			readToken (token);
+			readTokenFull (token, FALSE, repr);
 			if (isType (token, TOKEN_OPEN_PAREN))
 			{
 				nest_level++;
@@ -581,11 +696,11 @@ static void skipArgumentList (tokenInfo *const token)
 				}
 			}
 		}
-		readToken (token);
+		readTokenFull (token, include_newlines, NULL);
 	}
 }
 
-static void skipArrayList (tokenInfo *const token)
+static void skipArrayList (tokenInfo *const token, boolean include_newlines)
 {
 	int nest_level = 0;
 
@@ -613,7 +728,7 @@ static void skipArrayList (tokenInfo *const token)
 				}
 			}
 		}
-		readToken (token);
+		readTokenFull (token, include_newlines, NULL);
 	}
 }
 
@@ -641,7 +756,7 @@ static void addToScope (tokenInfo* const token, vString* const extra)
  *	 Scanning functions
  */
 
-static void findCmdTerm (tokenInfo *const token)
+static boolean findCmdTerm (tokenInfo *const token, boolean include_newlines)
 {
 	/*
 	 * Read until we find either a semicolon or closing brace.
@@ -654,27 +769,29 @@ static void findCmdTerm (tokenInfo *const token)
 		if ( isType (token, TOKEN_OPEN_CURLY))
 		{
 			parseBlock (token, token);
-			readToken (token);
+			readTokenFull (token, include_newlines, NULL);
 		}
 		else if ( isType (token, TOKEN_OPEN_PAREN) )
 		{
-			skipArgumentList(token);
+			skipArgumentList(token, include_newlines, NULL);
 		}
 		else if ( isType (token, TOKEN_OPEN_SQUARE) )
 		{
-			skipArrayList(token);
+			skipArrayList(token, include_newlines);
 		}
 		else
 		{
-			readToken (token);
+			readTokenFull (token, include_newlines, NULL);
 		}
 	}
+
+	return isType (token, TOKEN_SEMICOLON);
 }
 
 static void parseSwitch (tokenInfo *const token)
 {
 	/*
-	 * switch (expression){
+	 * switch (expression) {
 	 * case value1:
 	 *	   statement;
 	 *	   break;
@@ -693,23 +810,16 @@ static void parseSwitch (tokenInfo *const token)
 		 * Handle nameless functions, these will only
 		 * be considered methods.
 		 */
-		skipArgumentList(token);
+		skipArgumentList(token, FALSE, NULL);
 	}
 
 	if (isType (token, TOKEN_OPEN_CURLY))
 	{
-		/*
-		 * This will be either a function or a class.
-		 * We can only determine this by checking the body
-		 * of the function.  If we find a "this." we know
-		 * it is a class, otherwise it is a function.
-		 */
 		parseBlock (token, token);
 	}
-
 }
 
-static boolean parseLoop (tokenInfo *const token)
+static boolean parseLoop (tokenInfo *const token, tokenInfo *const parent)
 {
 	/*
 	 * Handles these statements
@@ -744,7 +854,7 @@ static boolean parseLoop (tokenInfo *const token)
 			 * Handle nameless functions, these will only
 			 * be considered methods.
 			 */
-			skipArgumentList(token);
+			skipArgumentList(token, FALSE, NULL);
 		}
 
 		if (isType (token, TOKEN_OPEN_CURLY))
@@ -755,11 +865,11 @@ static boolean parseLoop (tokenInfo *const token)
 			 * of the function.  If we find a "this." we know
 			 * it is a class, otherwise it is a function.
 			 */
-			parseBlock (token, token);
+			parseBlock (token, parent);
 		}
 		else
 		{
-			is_terminated = parseLine(token, FALSE);
+			is_terminated = parseLine(token, parent, FALSE);
 		}
 	}
 	else if (isKeyword (token, KEYWORD_do))
@@ -774,11 +884,11 @@ static boolean parseLoop (tokenInfo *const token)
 			 * of the function.  If we find a "this." we know
 			 * it is a class, otherwise it is a function.
 			 */
-			parseBlock (token, token);
+			parseBlock (token, parent);
 		}
 		else
 		{
-			is_terminated = parseLine(token, FALSE);
+			is_terminated = parseLine(token, parent, FALSE);
 		}
 
 		if (is_terminated)
@@ -794,7 +904,7 @@ static boolean parseLoop (tokenInfo *const token)
 				 * Handle nameless functions, these will only
 				 * be considered methods.
 				 */
-				skipArgumentList(token);
+				skipArgumentList(token, TRUE, NULL);
 			}
 			if (! isType (token, TOKEN_SEMICOLON))
 				is_terminated = FALSE;
@@ -804,7 +914,7 @@ static boolean parseLoop (tokenInfo *const token)
 	return is_terminated;
 }
 
-static boolean parseIf (tokenInfo *const token)
+static boolean parseIf (tokenInfo *const token, tokenInfo *const parent)
 {
 	boolean read_next_token = TRUE;
 	/*
@@ -863,7 +973,7 @@ static boolean parseIf (tokenInfo *const token)
 		 * Handle nameless functions, these will only
 		 * be considered methods.
 		 */
-		skipArgumentList(token);
+		skipArgumentList(token, FALSE, NULL);
 	}
 
 	if (isType (token, TOKEN_OPEN_CURLY))
@@ -874,15 +984,13 @@ static boolean parseIf (tokenInfo *const token)
 		 * of the function.  If we find a "this." we know
 		 * it is a class, otherwise it is a function.
 		 */
-		parseBlock (token, token);
+		parseBlock (token, parent);
 	}
 	else
 	{
-		findCmdTerm (token);
-
 		/* The next token should only be read if this statement had its own
 		 * terminator */
-		read_next_token = isType (token, TOKEN_SEMICOLON);
+		read_next_token = findCmdTerm (token, TRUE);
 	}
 	return read_next_token;
 }
@@ -890,6 +998,7 @@ static boolean parseIf (tokenInfo *const token)
 static void parseFunction (tokenInfo *const token)
 {
 	tokenInfo *const name = newToken ();
+	vString *const signature = vStringNew ();
 	boolean is_class = FALSE;
 
 	/*
@@ -913,27 +1022,32 @@ static void parseFunction (tokenInfo *const token)
 	}
 
 	if ( isType (token, TOKEN_OPEN_PAREN) )
-		skipArgumentList(token);
+		skipArgumentList(token, FALSE, signature);
 
 	if ( isType (token, TOKEN_OPEN_CURLY) )
 	{
 		is_class = parseBlock (token, name);
 		if ( is_class )
-			makeClassTag (name);
+			makeClassTag (name, signature);
 		else
-			makeFunctionTag (name);
+			makeFunctionTag (name, signature);
 	}
 
-	findCmdTerm (token);
+	findCmdTerm (token, FALSE);
 
+	vStringDelete (signature);
 	deleteToken (name);
 }
 
-static boolean parseBlock (tokenInfo *const token, tokenInfo *const parent)
+static boolean parseBlock (tokenInfo *const token, tokenInfo *const orig_parent)
 {
 	boolean is_class = FALSE;
 	boolean read_next_token = TRUE;
 	vString * saveScope = vStringNew ();
+	tokenInfo *const parent = newToken ();
+
+	/* backup the parent token to allow calls like parseBlock(token, token) */
+	copyToken (parent, orig_parent);
 
 	token->nestLevel++;
 	/*
@@ -967,11 +1081,13 @@ static boolean parseBlock (tokenInfo *const token, tokenInfo *const parent)
 				 * Ignore the remainder of the line
 				 * findCmdTerm(token);
 				 */
-				parseLine (token, is_class);
+				read_next_token = parseLine (token, parent, is_class);
 
 				vStringCopy(token->scope, saveScope);
 			}
-			else if (isKeyword (token, KEYWORD_var))
+			else if (isKeyword (token, KEYWORD_var) ||
+					 isKeyword (token, KEYWORD_let) ||
+					 isKeyword (token, KEYWORD_const))
 			{
 				/*
 				 * Potentially we have found an inner function.
@@ -979,7 +1095,7 @@ static boolean parseBlock (tokenInfo *const token, tokenInfo *const parent)
 				 */
 				vStringCopy(saveScope, token->scope);
 				addToScope (token, parent->string);
-				parseLine (token, is_class);
+				read_next_token = parseLine (token, parent, is_class);
 				vStringCopy(token->scope, saveScope);
 			}
 			else if (isKeyword (token, KEYWORD_function))
@@ -1002,7 +1118,7 @@ static boolean parseBlock (tokenInfo *const token, tokenInfo *const parent)
 				 * parseLine will detect this case and indicate
 				 * whether we should read an additional token.
 				 */
-				read_next_token = parseLine (token, is_class);
+				read_next_token = parseLine (token, parent, is_class);
 			}
 
 			/*
@@ -1019,6 +1135,7 @@ static boolean parseBlock (tokenInfo *const token, tokenInfo *const parent)
 		} while (! isType (token, TOKEN_CLOSE_CURLY) && read_next_token );
 	}
 
+	deleteToken (parent);
 	vStringDelete(saveScope);
 	token->nestLevel--;
 
@@ -1061,17 +1178,19 @@ static boolean parseMethods (tokenInfo *const token, tokenInfo *const class)
 				readToken (token);
 				if ( isKeyword (token, KEYWORD_function) )
 				{
+					vString *const signature = vStringNew ();
+
 					readToken (token);
 					if ( isType (token, TOKEN_OPEN_PAREN) )
 					{
-						skipArgumentList(token);
+						skipArgumentList(token, FALSE, signature);
 					}
 
 					if (isType (token, TOKEN_OPEN_CURLY))
 					{
 						has_methods = TRUE;
 						addToScope (name, class->string);
-						makeJsTag (name, JSTAG_METHOD);
+						makeJsTag (name, JSTAG_METHOD, signature);
 						parseBlock (token, name);
 
 						/*
@@ -1080,6 +1199,8 @@ static boolean parseMethods (tokenInfo *const token, tokenInfo *const class)
 						 */
 						readToken (token);
 					}
+
+					vStringDelete (signature);
 				}
 				else
 				{
@@ -1100,11 +1221,11 @@ static boolean parseMethods (tokenInfo *const token, tokenInfo *const class)
 							}
 							else if (isType (token, TOKEN_OPEN_PAREN))
 							{
-								skipArgumentList (token);
+								skipArgumentList (token, FALSE, NULL);
 							}
 							else if (isType (token, TOKEN_OPEN_SQUARE))
 							{
-								skipArrayList (token);
+								skipArrayList (token, FALSE);
 							}
 							else
 							{
@@ -1116,15 +1237,15 @@ static boolean parseMethods (tokenInfo *const token, tokenInfo *const class)
 						has_methods = TRUE;
 						addToScope (name, class->string);
 						if (has_child_methods)
-							makeJsTag (name, JSTAG_CLASS);
+							makeJsTag (name, JSTAG_CLASS, NULL);
 						else
-							makeJsTag (name, JSTAG_PROPERTY);
+							makeJsTag (name, JSTAG_PROPERTY, NULL);
 				}
 			}
 		}
 	} while ( isType(token, TOKEN_COMMA) );
 
-	findCmdTerm (token);
+	findCmdTerm (token, FALSE);
 
 cleanUp:
 	deleteToken (name);
@@ -1132,7 +1253,7 @@ static boolean parseMethods (tokenInfo *const token, tokenInfo *const class)
 	return has_methods;
 }
 
-static boolean parseStatement (tokenInfo *const token, boolean is_inside_class)
+static boolean parseStatement (tokenInfo *const token, tokenInfo *const parent, boolean is_inside_class)
 {
 	tokenInfo *const name = newToken ();
 	tokenInfo *const secondary_name = newToken ();
@@ -1140,6 +1261,7 @@ static boolean parseStatement (tokenInfo *const token, boolean is_inside_class)
 	vString * saveScope = vStringNew ();
 	boolean is_class = FALSE;
 	boolean is_var = FALSE;
+	boolean is_const = FALSE;
 	boolean is_terminated = TRUE;
 	boolean is_global = FALSE;
 	boolean has_methods = FALSE;
@@ -1179,8 +1301,11 @@ static boolean parseStatement (tokenInfo *const token, boolean is_inside_class)
 	/*
 	 * var can preceed an inner function
 	 */
-	if ( isKeyword(token, KEYWORD_var) )
+	if ( isKeyword(token, KEYWORD_var) ||
+		 isKeyword(token, KEYWORD_let) ||
+		 isKeyword(token, KEYWORD_const) )
 	{
+		is_const = isKeyword(token, KEYWORD_const);
 		/*
 		 * Only create variables for global scope
 		 */
@@ -1206,6 +1331,9 @@ static boolean parseStatement (tokenInfo *const token, boolean is_inside_class)
 	       ! isType (token, TOKEN_SEMICOLON)   &&
 	       ! isType (token, TOKEN_EQUAL_SIGN)  )
 	{
+		if (isType (token, TOKEN_OPEN_CURLY))
+			parseBlock (token, parent);
+
 		/* Potentially the name of the function */
 		readToken (token);
 		if (isType (token, TOKEN_PERIOD))
@@ -1221,11 +1349,12 @@ static boolean parseStatement (tokenInfo *const token, boolean is_inside_class)
 				{
 					if ( is_class )
 					{
-						vStringCopy(saveScope, token->scope);
 						addToScope(token, name->string);
 					}
 					else
 						addContext (name, token);
+
+					readToken (token);
 				}
 				else if ( isKeyword(token, KEYWORD_prototype) )
 				{
@@ -1251,7 +1380,7 @@ static boolean parseStatement (tokenInfo *const token, boolean is_inside_class)
 					 *     }
 					 *
 					 */
-					makeClassTag (name);
+					makeClassTag (name, NULL);
 					is_class = TRUE;
 
 					/*
@@ -1266,9 +1395,10 @@ static boolean parseStatement (tokenInfo *const token, boolean is_inside_class)
 						readToken (token);
 						if ( isKeyword(token, KEYWORD_NONE) )
 						{
+							vString *const signature = vStringNew ();
+
 							vStringCopy(saveScope, token->scope);
 							addToScope(token, name->string);
-							makeJsTag (token, JSTAG_METHOD);
 
 							readToken (method_body_token);
 							vStringCopy (method_body_token->scope, token->scope);
@@ -1278,15 +1408,22 @@ static boolean parseStatement (tokenInfo *const token, boolean is_inside_class)
 							           isType (method_body_token, TOKEN_OPEN_CURLY)) )
 							{
 								if ( isType (method_body_token, TOKEN_OPEN_PAREN) )
-									skipArgumentList(method_body_token);
+									skipArgumentList(method_body_token, FALSE,
+													 vStringLength (signature) == 0 ? signature : NULL);
 								else
 									readToken (method_body_token);
 							}
 
+							makeJsTag (token, JSTAG_METHOD, signature);
+							vStringDelete (signature);
+
 							if ( isType (method_body_token, TOKEN_OPEN_CURLY))
+							{
 								parseBlock (method_body_token, token);
-
-							is_terminated = TRUE;
+								is_terminated = TRUE;
+							}
+							else
+								is_terminated = isType (method_body_token, TOKEN_SEMICOLON);
 							goto cleanUp;
 						}
 					}
@@ -1308,22 +1445,23 @@ static boolean parseStatement (tokenInfo *const token, boolean is_inside_class)
 							/*
 							 * Find to the end of the statement
 							 */
-							findCmdTerm (token);
+							findCmdTerm (token, FALSE);
 							token->ignoreTag = FALSE;
 							is_terminated = TRUE;
 							goto cleanUp;
 						}
 					}
 				}
-				readToken (token);
+				else
+					readToken (token);
 			} while (isType (token, TOKEN_PERIOD));
 		}
 
 		if ( isType (token, TOKEN_OPEN_PAREN) )
-			skipArgumentList(token);
+			skipArgumentList(token, FALSE, NULL);
 
 		if ( isType (token, TOKEN_OPEN_SQUARE) )
-			skipArrayList(token);
+			skipArrayList(token, FALSE);
 
 		/*
 		if ( isType (token, TOKEN_OPEN_CURLY) )
@@ -1356,7 +1494,7 @@ static boolean parseStatement (tokenInfo *const token, boolean is_inside_class)
 			 *	   var g_var2;
 			 */
 			if (isType (token, TOKEN_SEMICOLON))
-				makeJsTag (name, JSTAG_VARIABLE);
+				makeJsTag (name, is_const ? JSTAG_CONSTANT : JSTAG_VARIABLE, NULL);
 		}
 		/*
 		 * Statement has ended.
@@ -1381,6 +1519,8 @@ static boolean parseStatement (tokenInfo *const token, boolean is_inside_class)
 
 		if ( isKeyword (token, KEYWORD_function) )
 		{
+			vString *const signature = vStringNew ();
+
 			readToken (token);
 
 			if ( isKeyword (token, KEYWORD_NONE) &&
@@ -1408,7 +1548,7 @@ static boolean parseStatement (tokenInfo *const token, boolean is_inside_class)
 			}
 
 			if ( isType (token, TOKEN_OPEN_PAREN) )
-				skipArgumentList(token);
+				skipArgumentList(token, FALSE, signature);
 
 			if (isType (token, TOKEN_OPEN_CURLY))
 			{
@@ -1420,23 +1560,25 @@ static boolean parseStatement (tokenInfo *const token, boolean is_inside_class)
 				 */
 				if ( is_inside_class )
 				{
-					makeJsTag (name, JSTAG_METHOD);
+					makeJsTag (name, JSTAG_METHOD, signature);
 					if ( vStringLength(secondary_name->string) > 0 )
-						makeFunctionTag (secondary_name);
+						makeFunctionTag (secondary_name, signature);
 					parseBlock (token, name);
 				}
 				else
 				{
 					is_class = parseBlock (token, name);
 					if ( is_class )
-						makeClassTag (name);
+						makeClassTag (name, signature);
 					else
-						makeFunctionTag (name);
+						makeFunctionTag (name, signature);
 
 					if ( vStringLength(secondary_name->string) > 0 )
-						makeFunctionTag (secondary_name);
+						makeFunctionTag (secondary_name, signature);
 				}
 			}
+
+			vStringDelete (signature);
 		}
 		else if (isType (token, TOKEN_OPEN_CURLY))
 		{
@@ -1451,7 +1593,7 @@ static boolean parseStatement (tokenInfo *const token, boolean is_inside_class)
 			 */
 			has_methods = parseMethods(token, name);
 			if (has_methods)
-				makeJsTag (name, JSTAG_CLASS);
+				makeJsTag (name, JSTAG_CLASS, NULL);
 			else
 			{
 				/*
@@ -1487,7 +1629,7 @@ static boolean parseStatement (tokenInfo *const token, boolean is_inside_class)
 					if ( ! stringListHas(FunctionNames, vStringValue (fulltag)) &&
 							! stringListHas(ClassNames, vStringValue (fulltag)) )
 					{
-						makeJsTag (name, JSTAG_VARIABLE);
+						makeJsTag (name, is_const ? JSTAG_CONSTANT : JSTAG_VARIABLE, NULL);
 					}
 					vStringDelete (fulltag);
 				}
@@ -1515,7 +1657,7 @@ static boolean parseStatement (tokenInfo *const token, boolean is_inside_class)
 
 				readToken (token);
 				if ( isType (token, TOKEN_OPEN_PAREN) )
-					skipArgumentList(token);
+					skipArgumentList(token, TRUE, NULL);
 
 				if (isType (token, TOKEN_SEMICOLON))
 				{
@@ -1523,15 +1665,18 @@ static boolean parseStatement (tokenInfo *const token, boolean is_inside_class)
 					{
 						if ( is_var )
 						{
-							makeJsTag (name, JSTAG_VARIABLE);
+							makeJsTag (name, is_const ? JSTAG_CONSTANT : JSTAG_VARIABLE, NULL);
 						}
 						else
 						{
 							if ( is_class )
 							{
-								makeClassTag (name);
+								makeClassTag (name, NULL);
 							} else {
-								makeFunctionTag (name);
+								/* FIXME: we cannot really get a meaningful
+								 * signature from a `new Function()` call,
+								 * so for now just don't set any */
+								makeFunctionTag (name, NULL);
 							}
 						}
 					}
@@ -1575,7 +1720,7 @@ static boolean parseStatement (tokenInfo *const token, boolean is_inside_class)
 				if ( ! stringListHas(FunctionNames, vStringValue (fulltag)) &&
 						! stringListHas(ClassNames, vStringValue (fulltag)) )
 				{
-					makeJsTag (name, JSTAG_VARIABLE);
+					makeJsTag (name, is_const ? JSTAG_CONSTANT : JSTAG_VARIABLE, NULL);
 				}
 				vStringDelete (fulltag);
 			}
@@ -1589,7 +1734,7 @@ static boolean parseStatement (tokenInfo *const token, boolean is_inside_class)
 					parenDepth++;
 				else if (isType (token, TOKEN_CLOSE_PAREN))
 					parenDepth--;
-				readToken (token);
+				readTokenFull (token, TRUE, NULL);
 			}
 			if (isType (token, TOKEN_CLOSE_CURLY))
 				is_terminated = FALSE;
@@ -1601,8 +1746,6 @@ static boolean parseStatement (tokenInfo *const token, boolean is_inside_class)
 	if (! isType (token, TOKEN_CLOSE_CURLY) &&
 	    ! isType (token, TOKEN_SEMICOLON))
 	{
-		findCmdTerm (token);
-
 		/*
 		 * Statements can be optionally terminated in the case of
 		 * statement prior to a close curly brace as in the
@@ -1615,8 +1758,7 @@ static boolean parseStatement (tokenInfo *const token, boolean is_inside_class)
 		 *	   return 1;
 		 * }
 		 */
-		if (isType (token, TOKEN_CLOSE_CURLY))
-			is_terminated = FALSE;
+		is_terminated = findCmdTerm (token, TRUE);
 	}
 
 cleanUp:
@@ -1629,7 +1771,55 @@ static boolean parseStatement (tokenInfo *const token, boolean is_inside_class)
 	return is_terminated;
 }
 
-static boolean parseLine (tokenInfo *const token, boolean is_inside_class)
+static void parseUI5 (tokenInfo *const token)
+{
+	tokenInfo *const name = newToken ();
+	/*
+	 * SAPUI5 is built on top of jQuery.
+	 * It follows a standard format:
+	 *     sap.ui.controller("id.of.controller", {
+	 *         method_name : function... {
+	 *         },
+	 *
+	 *         method_name : function ... {
+	 *         }
+	 *     }
+	 *
+	 * Handle the parsing of the initial controller (and the 
+	 * same for "view") and then allow the methods to be
+	 * parsed as usual.
+	 */
+
+	readToken (token);
+
+	if (isType (token, TOKEN_PERIOD))
+	{
+		readToken (token);
+		while (! isType (token, TOKEN_OPEN_PAREN) )
+		{
+			readToken (token);
+		}
+		readToken (token);
+
+		if (isType (token, TOKEN_STRING))
+		{
+			copyToken(name, token);
+			readToken (token);
+		}
+
+		if (isType (token, TOKEN_COMMA))
+			readToken (token);
+
+		do
+		{
+			parseMethods (token, name);
+		} while (! isType (token, TOKEN_CLOSE_CURLY) );
+	}
+
+	deleteToken (name);
+}
+
+static boolean parseLine (tokenInfo *const token, tokenInfo *const parent, boolean is_inside_class)
 {
 	boolean is_terminated = TRUE;
 	/*
@@ -1649,7 +1839,7 @@ static boolean parseLine (tokenInfo *const token, boolean is_inside_class)
 			case KEYWORD_for:
 			case KEYWORD_while:
 			case KEYWORD_do:
-				is_terminated = parseLoop (token);
+				is_terminated = parseLoop (token, parent);
 				break;
 			case KEYWORD_if:
 			case KEYWORD_else:
@@ -1657,17 +1847,16 @@ static boolean parseLine (tokenInfo *const token, boolean is_inside_class)
 			case KEYWORD_catch:
 			case KEYWORD_finally:
 				/* Common semantics */
-				is_terminated = parseIf (token);
+				is_terminated = parseIf (token, parent);
 				break;
 			case KEYWORD_switch:
 				parseSwitch (token);
 				break;
 			case KEYWORD_return:
-				findCmdTerm (token);
-				is_terminated = isType (token, TOKEN_SEMICOLON);
+				is_terminated = findCmdTerm (token, TRUE);
 				break;
 			default:
-				is_terminated = parseStatement (token, is_inside_class);
+				is_terminated = parseStatement (token, parent, is_inside_class);
 				break;
 		}
 	}
@@ -1678,7 +1867,7 @@ static boolean parseLine (tokenInfo *const token, boolean is_inside_class)
 		 * SEMICOLON terminated.  parseBlock needs to know this
 		 * so that it does not read the next token.
 		 */
-		is_terminated = parseStatement (token, is_inside_class);
+		is_terminated = parseStatement (token, parent, is_inside_class);
 	}
 	return is_terminated;
 }
@@ -1691,8 +1880,10 @@ static void parseJsFile (tokenInfo *const token)
 
 		if (isType (token, TOKEN_KEYWORD) && token->keyword == KEYWORD_function)
 			parseFunction (token);
+		else if (isType (token, TOKEN_KEYWORD) && token->keyword == KEYWORD_sap)
+			parseUI5 (token);
 		else
-			parseLine (token, FALSE);
+			parseLine (token, token, FALSE);
 	} while (TRUE);
 }
 


Modified: tests/ctags/1795612.js.tags
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -1,5 +1,5 @@
 # format=tagmanager
 RPC�1�Test�0
-asyncMethod�128�Test.RPC�0
-asyncRequest�128�Test.RPC�0
+asyncMethod�128�(  uri,  method,  params,  callback)�Test.RPC�0
+asyncRequest�128�(  uri,  data,  callback)�Test.RPC�0
 request_id�64�Test.RPC�0


Modified: tests/ctags/1850914.js.tags
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -1,4 +1,4 @@
 # format=tagmanager
-objLiteralMethod�128�objectLiteral�0
+objLiteralMethod�128�()�objectLiteral�0
 objLiteralProperty�64�objectLiteral�0
 objectLiteral�1�0


Modified: tests/ctags/1878155.js
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -8,7 +8,7 @@
 //
 
 // This should handle the escaped quote
-var RE={/foo\"/: "bar"};
+var RE={"bar":/foo\"/};
 
 // This should also handle the escaped quote
 // A tag should be created for the global variable "foo".


Modified: tests/ctags/1878155.js.tags
3 lines changed, 2 insertions(+), 1 deletions(-)
===================================================================
@@ -1,4 +1,5 @@
 # format=tagmanager
 RE�1�0
+bar�64�RE�0
 foo�16384�0
-my_function�16�0
+my_function�16�()�0


Modified: tests/ctags/1880687.js.tags
80 lines changed, 40 insertions(+), 40 deletions(-)
===================================================================
@@ -1,42 +1,42 @@
 # format=tagmanager
 MyClass�1�0
-MyClass_sub1�128�MyClass�0
-MyClass_sub2�128�MyClass�0
-a�16�0
-aa�16�0
-aa_sub1�16�aa�0
-aa_sub2�16�aa�0
-b�16�0
-baz�16�f�0
-c�16�0
-d�16�0
-e�16�0
-f�16�0
-g�16�0
-h�16�0
-i�16�0
-j�16�0
-k�16�0
-l�16�0
-m�16�0
-n�16�0
-o�16�0
-p�16�0
-q�16�0
-r�16�0
-s�16�0
-t�16�0
-u�16�0
-v�16�0
-w�16�0
-w_sub1�16�w�0
-w_sub2�16�w�0
-x�16�0
-x_sub1�16�x�0
-x_sub2�16�x�0
-y�16�0
-y_sub1�16�y�0
-y_sub2�16�y�0
-z�16�0
-z_sub1�16�z�0
-z_sub2�16�z�0
+MyClass_sub1�128�(x)�MyClass�0
+MyClass_sub2�128�(x)�MyClass�0
+a�16�(flag)�0
+aa�16�()�0
+aa_sub1�16�()�aa�0
+aa_sub2�16�()�aa�0
+b�16�()�0
+baz�16�()�f�0
+c�16�(flag)�0
+d�16�()�0
+e�16�(flag)�0
+f�16�()�0
+g�16�(flag)�0
+h�16�()�0
+i�16�(flag)�0
+j�16�()�0
+k�16�(flag)�0
+l�16�()�0
+m�16�(flag)�0
+n�16�()�0
+o�16�()�0
+p�16�()�0
+q�16�()�0
+r�16�(flag)�0
+s�16�()�0
+t�16�(flag)�0
+u�16�(flag)�0
+v�16�(flag)�0
+w�16�()�0
+w_sub1�16�(x)�w�0
+w_sub2�16�()�w�0
+x�16�()�0
+x_sub1�16�()�x�0
+x_sub2�16�()�x�0
+y�16�()�0
+y_sub1�16�()�y�0
+y_sub2�16�()�y�0
+z�16�()�0
+z_sub1�16�()�z�0
+z_sub2�16�()�z�0


Modified: tests/ctags/2023624.js.tags
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -1,3 +1,3 @@
 # format=tagmanager
-f1�16�0
-f2�16�0
+f1�16�()�0
+f2�16�()�0


Modified: tests/ctags/3470609.js.tags
6 lines changed, 3 insertions(+), 3 deletions(-)
===================================================================
@@ -1,13 +1,13 @@
 # format=tagmanager
 array�64�root�0
 decimal�64�root�0
-f�16�0
+f�16�()�0
 id�64�root�0
-method�128�root�0
+method�128�()�root�0
 neg�64�root�0
 parentheses�64�root�0
 root�1�0
 string�64�root�0
-subFunction�128�root.subObject�0
+subFunction�128�()�root.subObject�0
 subObject�1�root�0
 subProperty�64�root.subObject�0


Modified: tests/ctags/Makefile.am
9 lines changed, 9 insertions(+), 0 deletions(-)
===================================================================
@@ -159,6 +159,14 @@ test_sources = \
 	intro.tex						\
 	invalid_name.f90				\
 	java_enum.java					\
+	js-class-related-unterminated.js	\
+	js-const.js						\
+	js-implicit-semicolons.js		\
+	js-let.js						\
+	js-scope.js						\
+	js-signature.js					\
+	js-sub-block-scope.js			\
+	js-unknown-construct-nesting.js	\
 	jsFunc_tutorial.js				\
 	keyword_abstract.cs				\
 	keyword_catch_try.cs			\
@@ -258,6 +266,7 @@ test_sources = \
 	test_input2.rs					\
 	traffic_signal.v				\
 	traits.php						\
+	ui5.controller.js				\
 	union.f							\
 	value.f							\
 	whitespaces.php					\


Modified: tests/ctags/arraylist.js.tags
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -3,7 +3,7 @@ a
 b�16384�0
 bar�64�class.test1�0
 c�16384�0
-class�1�0
+class�1�()�0
 foo�64�class.test1�0
 test1�1�class�0
-test3�128�class�0
+test3�128�()�class�0


Modified: tests/ctags/bracematch.js.tags
10 lines changed, 5 insertions(+), 5 deletions(-)
===================================================================
@@ -1,7 +1,7 @@
 # format=tagmanager
-Container�16�0
+Container�16�()�0
 MyClass�1�0
-insert�128�MyClass�0
-wrap�128�MyClass�0
-x�16�Container�0
-y�16�Container�0
+insert�128�(element, insertions)�MyClass�0
+wrap�128�(element, wrapper, attributes)�MyClass�0
+x�16�()�Container�0
+y�16�()�Container�0


Modified: tests/ctags/bug1950327.js.tags
12 lines changed, 6 insertions(+), 6 deletions(-)
===================================================================
@@ -2,13 +2,13 @@
 *�64�container.dirtyTab�0
 Different�1�0
 TabChrome�1�0
-createTabTile�128�Different�0
-createTabTile�128�TabChrome�0
-destroyTabTile�128�Different�0
-destroyTabTile�128�TabChrome�0
+createTabTile�128�(browser)�Different�0
+createTabTile�128�(browser)�TabChrome�0
+destroyTabTile�128�(tile)�Different�0
+destroyTabTile�128�(tile)�TabChrome�0
 dirtyTab�1�container�0
-init�128�Different�0
-init�128�TabChrome�0
+init�128�()�Different�0
+init�128�()�TabChrome�0
 snapshot�64�container.dirtyTab�0
 title�64�container.dirtyTab�0
 url�64�container.dirtyTab�0


Modified: tests/ctags/bug2888482.js.tags
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -1,3 +1,3 @@
 # format=tagmanager
-onsubmit�16�editFormEl�0
-scrollEditBox�16�0
+onsubmit�16�()�editFormEl�0
+scrollEditBox�16�()�0


Modified: tests/ctags/bug3036476.js.tags
6 lines changed, 3 insertions(+), 3 deletions(-)
===================================================================
@@ -1,5 +1,5 @@
 # format=tagmanager
 container�16384�0
-method1�16�container.object�0
-method2�16�container.object�0
-object�16�container�0
+method1�16�()�container.object�0
+method2�16�()�container.object�0
+object�16�()�container�0


Modified: tests/ctags/bug3571233.js.tags
18 lines changed, 9 insertions(+), 9 deletions(-)
===================================================================
@@ -1,11 +1,11 @@
 # format=tagmanager
 MyClass�1�0
-MyClass�16�0
-function1�16�0
-function2�16�0
-method2�128�MyClass�0
-nestedFunction1�16�MyClass.method2�0
-nestedFunction2�16�MyClass.method2�0
-nestedFunction3�16�function1�0
-nestedFunction4�16�function2�0
-nestedFunction5�16�function2�0
+MyClass�16�()�0
+function1�16�()�0
+function2�16�()�0
+method2�128�()�MyClass�0
+nestedFunction1�16�()�MyClass.method2�0
+nestedFunction2�16�()�MyClass.method2�0
+nestedFunction3�16�()�function1�0
+nestedFunction4�16�()�function2�0
+nestedFunction5�16�()�function2�0


Modified: tests/ctags/complex-return.js.tags
34 lines changed, 17 insertions(+), 17 deletions(-)
===================================================================
@@ -1,18 +1,18 @@
 # format=tagmanager
-c2m1�128�class2�0
-c2m2�128�class2�0
-c2m3�128�class2�0
-c3m1�128�class3�0
-c3m2�128�class3�0
-class1�1�0
-class2�1�0
-class3�1�0
-class4�1�0
-func1�16�0
-func2�16�0
-method1�128�class1�0
-method1�128�class4�0
-method2�128�class1�0
-method2�128�class4�0
-method3�128�class1�0
-method4�128�class1�0
+c2m1�128�()�class2�0
+c2m2�128�(f)�class2�0
+c2m3�128�(f)�class2�0
+c3m1�128�()�class3�0
+c3m2�128�()�class3�0
+class1�1�()�0
+class2�1�()�0
+class3�1�()�0
+class4�1�()�0
+func1�16�()�0
+func2�16�()�0
+method1�128�()�class1�0
+method1�128�()�class4�0
+method2�128�()�class1�0
+method2�128�()�class4�0
+method3�128�()�class1�0
+method4�128�()�class1�0


Modified: tests/ctags/js-class-related-unterminated.js
62 lines changed, 62 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,62 @@
+
+var Cls = {
+  // add a member just so Cls is recognized as a class from the start
+  A: {}
+}
+
+Cls.B = function(a, b) {
+  this.a = a;
+  this.b = b;
+}
+
+Cls.B.Sub = function() {
+  this.a = 0
+}
+
+Cls.B.prototype.m1 = function(a) {
+  this.a = a;
+  if (a > 2) {
+    this.a *= 2
+  }
+}
+Cls.B.prototype.m2 = function(b) {
+  var a = b
+}
+Cls.B.prototype.m3 = function(c) {
+  this.c = c
+}
+Cls.B.prototype.m4 = function(d) {
+  this.d = d
+}
+Cls.B.prototype.m5 = function(e) {
+  /* this should rather be written `Cls.B.Sub.prototype.dyn1 = this.m6`, but
+   * then parser then thinks it's a child of this very scope.  it isn't really
+   * possible to fix this as the only reason it's actually not a child of the
+   * current scope is because it exists in the root scope but not in this one */
+  var Sub = Cls.B.Sub;
+  Sub.prototype.dyn1 = this.m4
+}
+Cls.B.prototype.m6 = function(f) {
+}
+
+Cls.C = function () {
+  this.a = 0;
+}
+
+Cls.C.prototype = {
+  n1: function() {
+    Cls.C.prototype = Cls.C.prototype
+  },
+  n2: function() {
+  }
+}
+
+function main() {
+  var c = new Cls.B(1, 2);
+  var d = new Cls.B.Sub();
+  print(d.dyn1);
+  c.m5();
+  print(d.dyn1);
+}
+
+main();


Modified: tests/ctags/js-class-related-unterminated.js.tags
16 lines changed, 16 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,16 @@
+# format=tagmanager
+A�64�Cls�0
+B�1�(a, b)�Cls�0
+C�1�()�Cls�0
+Cls�1�0
+Sub�1�()�Cls.B�0
+dyn1�128�Cls.B.Sub�0
+m1�128�(a)�Cls.B�0
+m2�128�(b)�Cls.B�0
+m3�128�(c)�Cls.B�0
+m4�128�(d)�Cls.B�0
+m5�128�(e)�Cls.B�0
+m6�128�(f)�Cls.B�0
+main�16�()�0
+n1�128�()�Cls.C�0
+n2�128�()�Cls.C�0


Modified: tests/ctags/js-const.js
10 lines changed, 10 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,10 @@
+
+const A = 1;
+const B = 1;
+const Group = {
+  X:1,
+  Y:2,
+  Z:3
+};
+
+const func = function () {}


Modified: tests/ctags/js-const.js.tags
8 lines changed, 8 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,8 @@
+# format=tagmanager
+A�65536�0
+B�65536�0
+Group�1�0
+X�64�Group�0
+Y�64�Group�0
+Z�64�Group�0
+func�16�()�0


Modified: tests/ctags/js-implicit-semicolons.js
16 lines changed, 16 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,16 @@
+var a = 1
+var b = function(){}
+function c() {}
+var d = {}
+function e() {}
+var f = []
+function g() {}
+var h = (1)
+function i() {}
+do {
+} while(0)
+function j() {}
+var k = new Function('a','b','return a+b')
+function l() {}
+var m = 0 // a single comment doesn't eat the newline
+function n() {}


Modified: tests/ctags/js-implicit-semicolons.js.tags
15 lines changed, 15 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,15 @@
+# format=tagmanager
+a�16384�0
+b�16�()�0
+c�16�()�0
+d�16384�0
+e�16�()�0
+f�16384�0
+g�16�()�0
+h�16384�0
+i�16�()�0
+j�16�()�0
+k�16�0
+l�16�()�0
+m�16384�0
+n�16�()�0


Modified: tests/ctags/js-let.js
8 lines changed, 8 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,8 @@
+let a = 1;
+let b = 0;
+let group = {
+  x:1,
+  y:1,
+  z:1,
+};
+let func = function(){}


Modified: tests/ctags/js-let.js.tags
8 lines changed, 8 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,8 @@
+# format=tagmanager
+a�16384�0
+b�16384�0
+func�16�()�0
+group�16384�0
+x�64�group�0
+y�64�group�0
+z�64�group�0


Modified: tests/ctags/js-scope.js
18 lines changed, 18 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,18 @@
+
+function A() {
+    this.a = 1;
+}
+
+A.prototype = {
+    m1 : function() {
+        this.a = 2;
+
+        foo.bar.baz.hello(1);
+        foo.bar.baz.hello(2);
+        foo.bar.baz.hello(3);
+    },
+    
+    m2: function() {
+        return this.a;
+    },
+};


Modified: tests/ctags/js-scope.js.tags
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,4 @@
+# format=tagmanager
+A�1�()�0
+m1�128�()�A�0
+m2�128�()�A�0


Modified: tests/ctags/js-signature.js
38 lines changed, 38 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,38 @@
+
+function f1() {
+}
+function f2(arg1, arg2) {
+}
+function f3(
+  arg1, // first
+  arg2, // second
+  arg3  // last
+) {
+  // ...
+}
+function f4(a, b, c) {
+}
+
+function Cls(name) {
+  this.name = name;
+}
+Cls.prototype = {
+  get_name: function() {
+    return this.name;
+  },
+  set_name: function(name) {
+    this.name = name;
+  },
+}
+
+Cls.prototype.hello = function(tpl) {
+  if (tpl == undefined) tpl = "hello {}";
+  return tpl.replace ('{}', this.name);
+}
+
+main = function() {
+  c = new Cls("John");
+  print(c.hello());
+}
+
+main();


Modified: tests/ctags/js-signature.js.tags
10 lines changed, 10 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,10 @@
+# format=tagmanager
+Cls�1�(name)�0
+f1�16�()�0
+f2�16�(arg1, arg2)�0
+f3�16�( arg1,  arg2,  arg3 )�0
+f4�16�(a, b, c)�0
+get_name�128�()�Cls�0
+hello�128�(tpl)�Cls�0
+main�16�()�0
+set_name�128�(name)�Cls�0


Modified: tests/ctags/js-sub-block-scope.js
17 lines changed, 17 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,17 @@
+
+function parent() {
+  function foo() {
+    if (test) {
+      function hello() {
+      }
+    } else {
+      function hi() {
+      }
+    }
+  }
+
+  function bar() {
+    function hello2() {}
+    function hi2() {}
+  }
+}


Modified: tests/ctags/js-sub-block-scope.js.tags
8 lines changed, 8 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,8 @@
+# format=tagmanager
+bar�16�()�parent�0
+foo�16�()�parent�0
+hello�16�()�parent.foo�0
+hello2�16�()�parent.bar�0
+hi�16�()�parent.foo�0
+hi2�16�()�parent.bar�0
+parent�16�()�0


Modified: tests/ctags/js-unknown-construct-nesting.js
23 lines changed, 23 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,23 @@
+
+var o = {
+  aa: function () {
+    foo: {
+      return ;
+    }
+  },
+  
+  bb: function (a) {
+    switch (a) {
+      case 1:
+        if (1) {
+          return 32
+        }
+        break;
+      case 2:
+        return 31;
+    }
+    return 1;
+  },
+  
+  cc: function() {}
+};


Modified: tests/ctags/js-unknown-construct-nesting.js.tags
5 lines changed, 5 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,5 @@
+# format=tagmanager
+aa�128�()�o�0
+bb�128�(a)�o�0
+cc�128�()�o�0
+o�1�0


Modified: tests/ctags/jsFunc_tutorial.js.tags
88 lines changed, 44 insertions(+), 44 deletions(-)
===================================================================
@@ -1,30 +1,30 @@
 # format=tagmanager
-Ball1�16�0
-Ball3�16�0
-D1�16�0
-D2�16�0
-D2A�16�0
+Ball1�16�()�0
+Ball3�16�()�0
+D1�16�(a, b)�0
+D2�16�(a, b)�0
+D2A�16�(a, b)�0
 D3�16�0
 D4�16�0
-D5�16�0
-DT1�16�0
-DT2�16�0
-DT2A�16�0
-DT3�16�0
-DT4�1�0
-DT5�1�0
-DT6�1�0
-DT7�1�0
-DT7A�1�0
-DT8�1�0
-DT9�1�0
-PT1�16�0
-PT2�1�0
-PT3�1�0
-add�16�myObject�0
-addSalary�128�PT3�0
-addSalaryFunction�1�0
-addSalaryFunctionDT9�1�0
+D5�16�(myOperator)�0
+DT1�16�()�0
+DT2�16�(message)�0
+DT2A�16�(message)�0
+DT3�16�()�0
+DT4�1�(message, specifiedName)�0
+DT5�1�(color, specifiedName, owner, weight)�0
+DT6�1�(name, salary, mySupervisor)�0
+DT7�1�(name, salary)�0
+DT7A�1�(name, salary)�0
+DT8�1�(name, salary)�0
+DT9�1�(name, salary)�0
+PT1�16�()�0
+PT2�1�(name, color)�0
+PT3�1�(name, salary)�0
+add�16�(a,b)�myObject�0
+addSalary�128�(addition)�PT3�0
+addSalaryFunction�1�(addition)�0
+addSalaryFunctionDT9�1�(addition)�0
 ball0�16384�0
 ball1�16384�0
 ball2�16384�0
@@ -40,32 +40,32 @@ boss
 boss1�16384�0
 boss2�16384�0
 boss3�16384�0
-calculate�16�getHalfOf7�0
-calculate�16�getHalfOf8�0
-calculate8�16�0
-getHalfOf7�16�0
-getHalfOf8�16�0
-getSalary�128�DT7�0
-getSalary�128�DT7A�0
-getSalary�128�DT8�0
-getSalary�128�PT3�0
-getSalaryFunctionDT9�16�0
+calculate�16�(number)�getHalfOf7�0
+calculate�16�(number)�getHalfOf8�0
+calculate8�16�(number)�0
+getHalfOf7�16�(num1, num2, num3)�0
+getHalfOf8�16�(num1, num2, num3)�0
+getSalary�128�()�DT7�0
+getSalary�128�()�DT7A�0
+getSalary�128�()�DT8�0
+getSalary�128�()�PT3�0
+getSalaryFunctionDT9�16�()�0
 livesIn�128�PT2�0
 manager�16384�0
-myFunction4�16�0
-myFunction5�16�0
-myFunction6�16�0
-myFunction6A�16�0
-myFunction6AE�16�0
-myFunction6B�16�0
-myFunction6E�16�0
+myFunction4�16�(message)�0
+myFunction5�16�()�0
+myFunction6�16�()�0
+myFunction6A�16�()�0
+myFunction6AE�16�()�0
+myFunction6B�16�()�0
+myFunction6E�16�()�0
 myObject�16384�0
 my_global_var1�16384�0
 object1�16384�0
 object2�16384�0
 object3�16384�0
 price�128�PT2�0
-savedFunc6B�16�0
-sayName4A�16�0
+savedFunc6B�16�()�0
+sayName4A�16�(name)�0
 teamLeader�16384�0
-theAdd�16�0
+theAdd�16�(a, b)�0


Modified: tests/ctags/no_terminator.js.tags
10 lines changed, 5 insertions(+), 5 deletions(-)
===================================================================
@@ -1,6 +1,6 @@
 # format=tagmanager
-checkForUpdate�16�0
-checkForUpdate2�16�0
-getParent�16�0
-ts_resortTable�16�0
-ts_sort_currency�16�0
+checkForUpdate�16�()�0
+checkForUpdate2�16�()�0
+getParent�16�(el, pTagName)�0
+ts_resortTable�16�(lnk)�0
+ts_sort_currency�16�(a,b)�0


Modified: tests/ctags/parenthesis-rvalue.js.tags
24 lines changed, 12 insertions(+), 12 deletions(-)
===================================================================
@@ -5,19 +5,19 @@ a1
 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
+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
+e1�16�()�0
+e1sub�16�()�e1�0
+e2�16�()�0
+e2sub�16�()�e2�0
+e3�16�()�0
+e3sub�16�()�e3�0


Modified: tests/ctags/regexp.js.tags
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -1,6 +1,6 @@
 # format=tagmanager
-func1�16�0
-func2�16�0
+func1�16�()�0
+func2�16�()�0
 no_re1�16384�0
 no_re2�16384�0
 no_re3�16384�0


Modified: tests/ctags/secondary_fcn_name.js.tags
8 lines changed, 4 insertions(+), 4 deletions(-)
===================================================================
@@ -1,6 +1,6 @@
 # format=tagmanager
-D1�16�0
-D2�16�0
-D2A�16�0
+D1�16�(a, b)�0
+D2�16�(a, b)�0
+D2A�16�(a, b)�0
 my_global_var1�16384�0
-theAdd�16�0
+theAdd�16�(a, b)�0


Modified: tests/ctags/shebang.js.tags
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -1,2 +1,2 @@
 # format=tagmanager
-f�16�0
+f�16�()�0


Modified: tests/ctags/simple.js.tags
34 lines changed, 17 insertions(+), 17 deletions(-)
===================================================================
@@ -1,25 +1,25 @@
 # format=tagmanager
 Database�1�0
-ValidClassOne�1�testlib.extras�0
-ValidClassTwo�1�0
-calculate�16�getHalfOf�0
+ValidClassOne�1�(a,b)�testlib.extras�0
+ValidClassTwo�1�()�0
+calculate�16�(number)�getHalfOf�0
 executeQueryString�128�Database�0
-getHalfOf�16�0
+getHalfOf�16�(num1, num2, num3)�0
 getTodaysDate�128�Database�0
-innerThree�16�validFunctionThree�0
-invalidInnerFunction�16�0
+innerThree�16�(a,b)�validFunctionThree�0
+invalidInnerFunction�16�(a,b)�0
 my_global_var1�16384�0
 my_global_var2�16384�0
 my_global_var3�16384�0
-my_global_var4�16�0
+my_global_var4�16�()�0
 my_global_var4�16384�0
-validFunctionFive�16�testlib�0
-validFunctionFour�16�extra�0
-validFunctionOne�16�0
-validFunctionSix�16�testlib.core�0
-validFunctionThree�16�0
-validFunctionTwo�16�0
-validMethodFour�128�ValidClassTwo�0
-validMethodOne�128�testlib.extras.ValidClassOne�0
-validMethodThree�128�ValidClassTwo�0
-validMethodTwo�128�testlib.extras.ValidClassOne�0
+validFunctionFive�16�(a,b)�testlib�0
+validFunctionFour�16�(a,b)�extra�0
+validFunctionOne�16�(a,b)�0
+validFunctionSix�16�(a,b)�testlib.core�0
+validFunctionThree�16�(a,b)�0
+validFunctionTwo�16�(a,b)�0
+validMethodFour�128�()�ValidClassTwo�0
+validMethodOne�128�(a,b)�testlib.extras.ValidClassOne�0
+validMethodThree�128�()�ValidClassTwo�0
+validMethodTwo�128�(a,b)�testlib.extras.ValidClassOne�0


Modified: tests/ctags/ui5.controller.js
31 lines changed, 31 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,31 @@
+sap.ui.controller("app.my_form", {
+
+    successfulRequest: function(data) {
+        switch( data.mParameters.headers.SAAP_SERVICE ) {
+            case SAAP_SERVICE.APPROVAL_DETAIL:
+                if (thisForm.getController().mApproval) {
+                }
+        }
+    },
+
+    onInit : function () {
+        this.selectListView = null;
+        sap.ui.getCore().byId("id_createButton").setEnabled(true);
+    },
+
+    refreshForm : function (AUFNR) {
+        if (AUFNR && AUFNR !== '') {
+            this.objId = this.oView.sId;
+        }
+        return;
+    },
+
+    refreshSettlements : function (AUFNR) {
+    },
+
+    setRefreshed : function (value) {
+        this.refreshed = value;
+    },
+});
+
+


Modified: tests/ctags/ui5.controller.js.tags
6 lines changed, 6 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,6 @@
+# format=tagmanager
+onInit�128�()�app.my_form�0
+refreshForm�128�(AUFNR)�app.my_form�0
+refreshSettlements�128�(AUFNR)�app.my_form�0
+setRefreshed�128�(value)�app.my_form�0
+successfulRequest�128�(data)�app.my_form�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