Branch: refs/heads/master Author: Colomban Wendling ban@herbesfolles.org Committer: Colomban Wendling ban@herbesfolles.org Date: Sat, 15 Jun 2024 20:14:11 UTC Commit: 4ce9018b8fcd580d667d1462326dcf887d5c2218 https://github.com/geany/geany/commit/4ce9018b8fcd580d667d1462326dcf887d5c22...
Log Message: ----------- Merge pull request #3877 from techee/ctags_sync6
Update ctags to p6.1.20240519.0
Modified Paths: -------------- ctags/libreadtags/readtags.c ctags/libreadtags/readtags.h ctags/main/repoinfo.h ctags/parsers/jscript.c ctags/parsers/matlab.c ctags/parsers/pascal.c ctags/parsers/powershell.c scripts/update-ctags.py src/tagmanager/tm_parser.c tests/ctags/enum.ps1.tags tests/ctags/matlab_backtracking.m.tags tests/ctags/matlab_test.m.tags
Modified: ctags/libreadtags/readtags.c 298 lines changed, 212 insertions(+), 86 deletions(-) =================================================================== @@ -32,28 +32,39 @@ typedef struct { char *buffer; } vstring;
+/* Define readtags' own off_t. */ +#ifdef _WIN32 +typedef long long rt_off_t; +#else +typedef off_t rt_off_t; +#endif + /* Information about current tag file */ struct sTagFile { /* has the file been opened and this structure initialized? */ - short initialized; + unsigned char initialized; /* format of tag file */ - short format; + unsigned char format; + /* 1 "u-ctags" is set to !_TAG_OUTPUT_MODE pseudo tag + * and "slash" is set to !_TAG_OUTPUT_FILESEP + * pseudo tag in the tags file. */ + unsigned char inputUCtagsMode; /* how is the tag file sorted? */ tagSortType sortMethod; /* pointer to file structure */ FILE* fp; /* file position of first character of `line' */ - off_t pos; + rt_off_t pos; /* size of tag file in seekable positions */ - off_t size; + rt_off_t size; /* last line read */ vstring line; /* name of tag in last line read */ vstring name; /* defines tag search state */ struct { /* file position of last match for tag */ - off_t pos; + rt_off_t pos; /* name of tag last searched for */ char *name; /* length of name for partial matches */ @@ -97,8 +108,34 @@ static const size_t PseudoTagPrefixLength = 2; * FUNCTION DEFINITIONS */
+static rt_off_t readtags_ftell(FILE *fp) +{ + rt_off_t pos; + +#ifdef _WIN32 + pos = _ftelli64(fp); +#else + pos = ftell(fp); +#endif + + return pos; +} + +static int readtags_fseek(FILE *fp, rt_off_t pos, int whence) +{ + int ret; + +#ifdef _WIN32 + ret = _fseeki64(fp, pos, whence); +#else + ret = fseek(fp, pos, whence); +#endif + + return ret; +} + /* Converts a hexadecimal digit to its value */ -static int xdigitValue (char digit) +static int xdigitValue (unsigned char digit) { if (digit >= '0' && digit <= '9') return digit - '0'; @@ -114,39 +151,42 @@ static int xdigitValue (char digit) * Reads the first character from the string, possibly un-escaping it, and * advances *s to the start of the next character. */ -static int readTagCharacter (const char **s) +static int readTagCharacter (const char **const s) { - int c = **(const unsigned char **)s; + const unsigned char *p = (const unsigned char *) *s; + int c = *p;
- (*s)++; + p++;
if (c == '\') { - switch (**s) + switch (*p) { - case 't': c = '\t'; (*s)++; break; - case 'r': c = '\r'; (*s)++; break; - case 'n': c = '\n'; (*s)++; break; - case '\': c = '\'; (*s)++; break; + case 't': c = '\t'; p++; break; + case 'r': c = '\r'; p++; break; + case 'n': c = '\n'; p++; break; + case '\': c = '\'; p++; break; /* Universal-CTags extensions */ - case 'a': c = '\a'; (*s)++; break; - case 'b': c = '\b'; (*s)++; break; - case 'v': c = '\v'; (*s)++; break; - case 'f': c = '\f'; (*s)++; break; + case 'a': c = '\a'; p++; break; + case 'b': c = '\b'; p++; break; + case 'v': c = '\v'; p++; break; + case 'f': c = '\f'; p++; break; case 'x': - if (isxdigit ((*s)[1]) && isxdigit ((*s)[2])) + if (isxdigit (p[1]) && isxdigit (p[2])) { - int val = (xdigitValue ((*s)[1]) << 4) | xdigitValue ((*s)[2]); + int val = (xdigitValue (p[1]) << 4) | xdigitValue (p[2]); if (val < 0x80) { - (*s) += 3; + p += 3; c = val; } } break; } }
+ *s = (const char *) p; + return c; }
@@ -285,7 +325,7 @@ static int readTagLineRaw (tagFile *const file, int *err) char *const pLastChar = file->line.buffer + file->line.size - 2; char *line;
- file->pos = ftell (file->fp); + file->pos = readtags_ftell (file->fp); if (file->pos < 0) { *err = errno; @@ -312,7 +352,8 @@ static int readTagLineRaw (tagFile *const file, int *err) *err = ENOMEM; result = 0; } - if (fseek (file->fp, file->pos, SEEK_SET) < 0) + + if (readtags_fseek (file->fp, file->pos, SEEK_SET) < 0) { *err = errno; result = 0; @@ -485,26 +526,15 @@ static unsigned int countContinuousBackslashesBackward(const char *from, return counter; }
-static tagResult parseTagLine (tagFile *file, tagEntry *const entry, int *err) +/* When unescaping, the input string becomes shorter. + * e.g. \t occupies two bytes on the tag file. + * It is converted to 0x9 and occupies one byte. + * memmove called here for shortening the line + * buffer. */ +static char *unescapeInPlace (char *q, char **tab, size_t *p_len) { - int i; - char *p = file->line.buffer; - size_t p_len = strlen (p); - char *tab = strchr (p, TAB); - - memset(entry, 0, sizeof(*entry)); + char *p = q;
- entry->name = p; - if (tab != NULL) - { - *tab = '\0'; - } - - /* When unescaping, the input string becomes shorter. - * e.g. \t occupies two bytes on the tag file. - * It is converted to 0x9 and occupies one byte. - * memmove called here for shortening the line - * buffer. */ while (*p != '\0') { const char *next = p; @@ -513,21 +543,50 @@ static tagResult parseTagLine (tagFile *file, tagEntry *const entry, int *err)
*p = (char) ch; p++; - p_len -= skip; + *p_len -= skip; if (skip > 1) { /* + 1 is for moving the area including the last '\0'. */ - memmove (p, next, p_len + 1); - if (tab) - tab -= skip - 1; + memmove (p, next, *p_len + 1); + if (*tab) + *tab -= skip - 1; } }
+ return p; +} + +static tagResult parseTagLine (tagFile *file, tagEntry *const entry, int *err) +{ + int i; + char *p = file->line.buffer; + size_t p_len = strlen (p); + char *tab = strchr (p, TAB); + + memset(entry, 0, sizeof(*entry)); + + entry->name = p; + if (tab != NULL) + { + *tab = '\0'; + } + + p = unescapeInPlace (p, &tab, &p_len); + if (tab != NULL) { p = tab + 1; entry->file = p; tab = strchr (p, TAB); + if (file->inputUCtagsMode) + { + if (tab != NULL) + { + *tab = '\0'; + } + p = unescapeInPlace (p, &tab, &p_len); + } + if (tab != NULL) { int fieldsPresent; @@ -554,12 +613,12 @@ static tagResult parseTagLine (tagFile *file, tagEntry *const entry, int *err) else ++p; } - else if (isdigit ((int) *(unsigned char*) p)) + else if (isdigit (*(unsigned char*) p)) { /* parse line number */ entry->address.pattern = p; entry->address.lineNumber = atol (p); - while (isdigit ((int) *(unsigned char*) p)) + while (isdigit (*(unsigned char*) p)) ++p; if (p) { @@ -636,6 +695,8 @@ static tagResult readPseudoTags (tagFile *const file, tagFileInfo *const info) int err = 0; tagResult result = TagSuccess; const size_t prefixLength = strlen (PseudoTagPrefix); + int tag_output_mode_u_ctags = 0; + int tag_output_filesep_slash = 0;
info->file.format = 1; info->file.sort = TAG_UNSORTED; @@ -683,7 +744,7 @@ static tagResult readPseudoTags (tagFile *const file, tagFileInfo *const info) err = TagErrnoUnexpectedFormat; break; } - file->format = (short) m; + file->format = (unsigned char) m; } else if (strcmp (key, "TAG_PROGRAM_AUTHOR") == 0) { @@ -721,6 +782,16 @@ static tagResult readPseudoTags (tagFile *const file, tagFileInfo *const info) break; } } + else if (strcmp (key, "TAG_OUTPUT_MODE") == 0) + { + if (strcmp (value, "u-ctags") == 0) + tag_output_mode_u_ctags = 1; + } + else if (strcmp (key, "TAG_OUTPUT_FILESEP") == 0) + { + if (strcmp (value, "slash") == 0) + tag_output_filesep_slash = 1; + }
info->file.format = file->format; info->file.sort = file->sortMethod; @@ -730,6 +801,10 @@ static tagResult readPseudoTags (tagFile *const file, tagFileInfo *const info) info->program.version = file->program.version; } } + + if (tag_output_mode_u_ctags && tag_output_filesep_slash) + file->inputUCtagsMode = 1; + if (fsetpos (file->fp, &startOfLine) < 0) err = errno;
@@ -748,7 +823,7 @@ static tagResult gotoFirstLogicalTag (tagFile *const file) { fpos_t startOfLine;
- if (fseek(file->fp, 0L, SEEK_SET) == -1) + if (readtags_fseek(file->fp, 0, SEEK_SET) == -1) { file->err = errno; return TagFailure; @@ -798,37 +873,55 @@ static tagFile *initialize (const char *const filePath, tagFileInfo *const info) result->fields.max, sizeof (tagExtensionField)); if (result->fields.list == NULL) goto mem_error; - result->fp = fopen (filePath, "rb"); + +#if defined(__GLIBC__) && (__GLIBC__ >= 2) \ + && defined(__GLIBC_MINOR__) && (__GLIBC_MINOR__ >= 3) + result->fp = fopen (filePath, "rbm"); +#endif + if (result->fp == NULL) + { + errno = 0; + result->fp = fopen (filePath, "rb"); + } if (result->fp == NULL) { info->status.error_number = errno; goto file_error; } - else - { - if (fseek (result->fp, 0, SEEK_END) == -1) - { - info->status.error_number = errno; - goto file_error; - } - result->size = ftell (result->fp); - if (result->size == -1) - { - info->status.error_number = errno; - goto file_error; - } - if (fseek(result->fp, 0L, SEEK_SET) == -1) - { - info->status.error_number = errno; - goto file_error; - }
- if (readPseudoTags (result, info) == TagFailure) - goto file_error; + /* Record the size of the tags file to `size` field of result. */ + if (readtags_fseek (result->fp, 0, SEEK_END) == -1) + { + info->status.error_number = errno; + goto file_error; + } + result->size = readtags_ftell (result->fp); + if (result->size == -1) + { + /* fseek() retruns an int value. + * We observed following behavior on Windows; + * if sizeof(int) of the platform is too small for + * representing the size of the tags file, fseek() + * returns -1 and it doesn't set errno. + */ + info->status.error_number = errno; + if (info->status.error_number == 0) + info->status.error_number = TagErrnoFileMaybeTooBig;
- info->status.opened = 1; - result->initialized = 1; + goto file_error; + } + if (readtags_fseek(result->fp, 0, SEEK_SET) == -1) + { + info->status.error_number = errno; + goto file_error; } + + if (readPseudoTags (result, info) == TagFailure) + goto file_error; + + info->status.opened = 1; + result->initialized = 1; + return result; mem_error: info->status.error_number = ENOMEM; @@ -905,9 +998,9 @@ static const char *readFieldValue ( return result; }
-static int readTagLineSeek (tagFile *const file, const off_t pos) +static int readTagLineSeek (tagFile *const file, const rt_off_t pos) { - if (fseek (file->fp, pos, SEEK_SET) < 0) + if (readtags_fseek (file->fp, pos, SEEK_SET) < 0) { file->err = errno; return 0; @@ -951,11 +1044,11 @@ static tagResult findFirstNonMatchBefore (tagFile *const file) #define JUMP_BACK 512 int more_lines; int comp; - off_t start = file->pos; - off_t pos = start; + rt_off_t start = file->pos; + rt_off_t pos = start; do { - if (pos < (off_t) JUMP_BACK) + if (pos < (rt_off_t) JUMP_BACK) pos = 0; else pos = pos - JUMP_BACK; @@ -971,7 +1064,7 @@ static tagResult findFirstMatchBefore (tagFile *const file) { tagResult result = TagFailure; int more_lines; - off_t start = file->pos; + rt_off_t start = file->pos; if (findFirstNonMatchBefore (file) != TagSuccess) return TagFailure; do @@ -988,10 +1081,10 @@ static tagResult findFirstMatchBefore (tagFile *const file) static tagResult findBinary (tagFile *const file) { tagResult result = TagFailure; - off_t lower_limit = 0; - off_t upper_limit = file->size; - off_t last_pos = 0; - off_t pos = upper_limit / 2; + rt_off_t lower_limit = 0; + rt_off_t upper_limit = file->size; + rt_off_t last_pos = 0; + rt_off_t pos = upper_limit / 2; while (result != TagSuccess) { if (! readTagLineSeek (file, pos)) @@ -1083,18 +1176,18 @@ static tagResult find (tagFile *const file, tagEntry *const entry, file->search.nameLength = strlen (name); file->search.partial = (options & TAG_PARTIALMATCH) != 0; file->search.ignorecase = (options & TAG_IGNORECASE) != 0; - if (fseek (file->fp, 0, SEEK_END) < 0) + if (readtags_fseek (file->fp, 0, SEEK_END) < 0) { file->err = errno; return TagFailure; } - file->size = ftell (file->fp); + file->size = readtags_ftell (file->fp); if (file->size == -1) { file->err = errno; return TagFailure; } - if (fseek(file->fp, 0L, SEEK_SET) == -1) + if (readtags_fseek(file->fp, 0, SEEK_SET) == -1) { file->err = errno; return TagFailure; @@ -1167,7 +1260,7 @@ static tagResult findPseudoTag (tagFile *const file, int rewindBeforeFinding, ta
if (rewindBeforeFinding) { - if (fseek(file->fp, 0L, SEEK_SET) == -1) + if (readtags_fseek(file->fp, 0, SEEK_SET) == -1) { file->err = errno; return TagFailure; @@ -1291,6 +1384,39 @@ extern tagResult tagsNextPseudoTag (tagFile *const file, tagEntry *const entry) return findPseudoTag (file, 0, entry); }
+extern tagResult tagsFindPseudoTag (tagFile *const file, tagEntry *const entry, + const char *const name, const int match) +{ + size_t len; + tagEntry entry0; + tagEntry *entryp = entry? entry: &entry0; + + tagResult r = tagsFirstPseudoTag (file, entryp); + if (r != TagSuccess) + return r; + + if (match & TAG_PARTIALMATCH) + len = strlen (name); + + do + { + if (match & TAG_PARTIALMATCH) + { + if (strncmp (entryp->name, name, len) == 0) + return TagSuccess; + } + else + { + if (strcmp (entryp->name, name) == 0) + return TagSuccess; + } + r = tagsNextPseudoTag (file, entryp); + } + while (r == TagSuccess); + + return r; +} + extern tagResult tagsClose (tagFile *const file) { tagResult result = TagFailure;
Modified: ctags/libreadtags/readtags.h 20 lines changed, 18 insertions(+), 2 deletions(-) =================================================================== @@ -39,7 +39,7 @@ typedef enum { #define sortType tagSortType #endif
-/* Options for tagsFind() */ +/* Options for tagsFind() and tagsFindPseudoTag() */ #define TAG_FULLMATCH 0x0 #define TAG_PARTIALMATCH 0x1
@@ -59,6 +59,7 @@ typedef enum { * (Zero or a positive integer is expected.) */ TagErrnoInvalidArgument = -4, /* Unexpected argument passed to the API * function */ + TagErrnoFileMaybeTooBig = -5, /* Maybe the tags file is too big */ } tagErrno;
struct sTagFile; @@ -258,7 +259,7 @@ extern tagResult tagsFindNext (tagFile *const file, tagEntry *const entry);
/* * Does the same as tagsFirst(), but is specialized to pseudo tags. -* If tagFileInfo doesn't contain pseudo tags you are interested, read +* If tagFileInfo doesn't contain pseudo tags you are interested in, read * them sequentially with this function and tagsNextPseudoTag(). */ extern tagResult tagsFirstPseudoTag (tagFile *const file, tagEntry *const entry); @@ -269,6 +270,21 @@ extern tagResult tagsFirstPseudoTag (tagFile *const file, tagEntry *const entry) */ extern tagResult tagsNextPseudoTag (tagFile *const file, tagEntry *const entry);
+/* +* Does the same as tagsFind(), but is specialized to pseudo tags. +* The available values for `match' are: +* +* TAG_PARTIALMATCH +* Tags whose leading characters match `name' will qualify. +* +* TAG_FULLMATCH +* Only tags whose full lengths match `name' will qualify. +* +* NOTE: unlike tagsFind(), this function uses liner-searching even if +* the tags file is sorted. +*/ +extern tagResult tagsFindPseudoTag (tagFile *const file, tagEntry *const entry, const char *const name, const int match); + /* * Call tagsClose() at completion of reading the tag file, which will * close the file and free any internal memory allocated. The function will
Modified: ctags/main/repoinfo.h 2 lines changed, 1 insertions(+), 1 deletions(-) =================================================================== @@ -1 +1 @@ -#define CTAGS_REPOINFO "p6.1.20240421.0" +#define CTAGS_REPOINFO "p6.1.20240519.0"
Modified: ctags/parsers/jscript.c 166 lines changed, 111 insertions(+), 55 deletions(-) =================================================================== @@ -135,6 +135,7 @@ typedef struct sTokenInfo { MIOPos filePosition; int nestLevel; bool dynamicProp; + int c; } tokenInfo;
/* @@ -367,6 +368,7 @@ static void copyToken (tokenInfo *const dest, const tokenInfo *const src, dest->type = src->type; dest->keyword = src->keyword; dest->dynamicProp = src->dynamicProp; + dest->c = src->c; vStringCopy(dest->string, src->string); if (include_non_read_info) { @@ -464,7 +466,7 @@ static int makeJsRefTagsForNameChain (char *name_chain, const tokenInfo *token, e.extensionFields.scopeIndex = scope;
index = makeTagEntry (&e); - /* We shold remove This condition. We should fix the callers passing + /* We should remove this condition. We should fix the callers passing * an empty name instead. makeTagEntry() returns CORK_NIL if the tag * name is empty. */ if (index != CORK_NIL) @@ -996,6 +998,32 @@ static void parseTemplateString (vString *const string) while (c != EOF); }
+static void reprToken (const tokenInfo *const token, vString *const repr) +{ + switch (token->type) + { + case TOKEN_DOTS: + vStringCatS (repr, "..."); + break; + + case TOKEN_STRING: + case TOKEN_TEMPLATE_STRING: + vStringPut (repr, token->c); + vStringCat (repr, token->string); + vStringPut (repr, token->c); + break; + + case TOKEN_IDENTIFIER: + case TOKEN_KEYWORD: + vStringCat (repr, token->string); + break; + + default: + vStringPut (repr, token->c); + break; + } +} + static void readTokenFullRaw (tokenInfo *const token, bool include_newlines, vString *const repr) { int c; @@ -1005,9 +1033,12 @@ static void readTokenFullRaw (tokenInfo *const token, bool include_newlines, vSt /* if we've got a token held back, emit it */ if (NextToken) { + TRACE_PRINT("Emitting held token"); copyToken (token, NextToken, false); deleteToken (NextToken); NextToken = NULL; + if (repr) + reprToken (token, repr); return; }
@@ -1029,12 +1060,11 @@ static void readTokenFullRaw (tokenInfo *const token, bool include_newlines, vSt token->lineNumber = getInputLineNumber (); token->filePosition = getInputFilePosition ();
- if (repr && c != EOF) - { - if (i > 1) - vStringPut (repr, ' '); - vStringPut (repr, c); - } + /* special case to insert a separator */ + if (repr && c != EOF && i > 1) + vStringPut (repr, ' '); + + token->c = c;
switch (c) { @@ -1063,14 +1093,6 @@ static void readTokenFullRaw (tokenInfo *const token, bool include_newlines, vSt }
token->type = TOKEN_DOTS; - if (repr) - { - /* Adding two dots is enough here. - * The first one is already added with - * vStringPut (repr, c). - */ - vStringCatS (repr, ".."); - } break; } case ':': token->type = TOKEN_COLON; break; @@ -1125,23 +1147,13 @@ static void readTokenFullRaw (tokenInfo *const token, bool include_newlines, vSt parseString (token->string, c); token->lineNumber = getInputLineNumber (); token->filePosition = getInputFilePosition (); - if (repr) - { - vStringCat (repr, token->string); - vStringPut (repr, c); - } break;
case '`': token->type = TOKEN_TEMPLATE_STRING; parseTemplateString (token->string); token->lineNumber = getInputLineNumber (); token->filePosition = getInputFilePosition (); - if (repr) - { - vStringCat (repr, token->string); - vStringPut (repr, c); - } break;
case '/': @@ -1173,8 +1185,6 @@ static void readTokenFullRaw (tokenInfo *const token, bool include_newlines, vSt } else { - if (repr) /* remove the / we added */ - vStringChop(repr); if (d == '*') { skipToCharacterInInputFile2('*', '/'); @@ -1228,8 +1238,6 @@ static void readTokenFullRaw (tokenInfo *const token, bool include_newlines, vSt token->type = TOKEN_IDENTIFIER; else token->type = TOKEN_KEYWORD; - if (repr && vStringLength (token->string) > 1) - vStringCatS (repr, vStringValue (token->string) + 1); } break; } @@ -1278,15 +1286,58 @@ static void readTokenFullRaw (tokenInfo *const token, bool include_newlines, vSt token->type = TOKEN_SEMICOLON; token->keyword = KEYWORD_NONE; vStringClear (token->string); - if (repr) - vStringPut (token->string, '\n'); + token->c = '\n'; }
#undef IS_STMT_SEPARATOR #undef IS_BINARY_OPERATOR }
LastTokenType = token->type; + + if (repr) + reprToken (token, repr); +} + +/* whether something we consider a keyword (either because it sometimes is or + * because of the parser's perks) is actually valid as a function name + * See https://tc39.es/ecma262/multipage/ecmascript-language-lexical-grammar.html#s... */ +static bool canBeFunctionName (const tokenInfo *const token, bool strict_mode) +{ + switch (token->keyword) + { + /* non-keywords specific to this parser */ + case KEYWORD_capital_function: + case KEYWORD_capital_object: + case KEYWORD_prototype: + case KEYWORD_sap: + /* syntactic, but not keyword: + * as async from get meta of set target + * "await" is OK as well */ + case KEYWORD_async: + case KEYWORD_get: + case KEYWORD_set: + return true; + + /* strict-mode keywords + * let static implements interface package private protected public + * we need to also include those which are OK as function names + * yield + */ + case KEYWORD_let: + case KEYWORD_static: + return ! strict_mode; + + default: + return isType (token, TOKEN_IDENTIFIER); + } +} + +static bool canBePropertyName (const tokenInfo *const token) +{ + /* property names are pretty relaxed, any non reserved word is OK, even + * strict-mode ones in strict-mode */ + return canBeFunctionName (token, false); }
/* See https://babeljs.io/blog/2018/09/17/decorators */ @@ -1760,9 +1811,11 @@ static bool parseFunction (tokenInfo *const token, tokenInfo *const lhs_name, co copyToken (name, token, true); readToken (name); if (isType (name, TOKEN_KEYWORD) && - (isKeyword (name, KEYWORD_get) || isKeyword (name, KEYWORD_set))) + canBeFunctionName (name, false /* true if we're in strict mode */)) { - name->type = TOKEN_IDENTIFIER; // treat as function name + // treat as function name + name->type = TOKEN_IDENTIFIER; + name->keyword = KEYWORD_NONE; }
if (isType (name, TOKEN_STAR)) @@ -1981,27 +2034,24 @@ static bool parseMethods (tokenInfo *const token, int class_index, { bool is_setter = false; bool is_getter = false; - bool is_static = false; /* For recognizing static {...} block. */
if (!dont_read) readToken (token); dont_read = false;
+start: if (isType (token, TOKEN_CLOSE_CURLY)) { goto cleanUp; }
- if (isKeyword (token, KEYWORD_async)) - readToken (token); - else if (isKeyword (token, KEYWORD_static)) - is_static = true; - else if (isType (token, TOKEN_KEYWORD) && - (isKeyword (token, KEYWORD_get) || isKeyword (token, KEYWORD_set))) + if (isType (token, TOKEN_KEYWORD) && canBePropertyName (token)) { tokenInfo *saved_token = newToken (); copyToken (saved_token, token, true); readToken (token); + + /* it wasn't actually a keyword after all, make it an identifier */ if (isType(token, TOKEN_OPEN_PAREN) || isType(token, TOKEN_COLON)) { Assert (NextToken == NULL); @@ -2011,10 +2061,25 @@ static bool parseMethods (tokenInfo *const token, int class_index, token->type = TOKEN_IDENTIFIER; /* process as identifier */ token->keyword = KEYWORD_NONE; } + else if (isKeyword (saved_token, KEYWORD_static) && + isType (token, TOKEN_OPEN_CURLY)) + { + /* static initialization block */ + deleteToken (saved_token); + parseBlock (token, class_index); + continue; + } else if (isKeyword (saved_token, KEYWORD_get)) is_getter = true; - else + else if (isKeyword (saved_token, KEYWORD_set)) is_setter = true; + else if (isKeyword (saved_token, KEYWORD_async) || + isKeyword (saved_token, KEYWORD_static)) + { + /* can be a qualifier for another "keyword", so start over */ + deleteToken (saved_token); + goto start; + }
deleteToken (saved_token); } @@ -2025,9 +2090,8 @@ static bool parseMethods (tokenInfo *const token, int class_index, continue; }
- if ((! isType (token, TOKEN_KEYWORD) && + if (! isType (token, TOKEN_KEYWORD) && ! isType (token, TOKEN_SEMICOLON)) - || is_static) { bool is_generator = false; bool is_shorthand = false; /* ES6 shorthand syntax */ @@ -2202,15 +2266,6 @@ static bool parseMethods (tokenInfo *const token, int class_index,
vStringDelete (signature); } - else if (is_static) - { - if (isType (token, TOKEN_OPEN_CURLY)) - /* static initialization block */ - parseBlock (token, class_index); - else - dont_read = true; - continue; - } else { bool is_property = isType (token, TOKEN_COMMA); @@ -2409,10 +2464,11 @@ static bool parsePrototype (tokenInfo *const name, tokenInfo *const token, state * Handle CASE 1 */ readToken (token); - if (isType (token, TOKEN_KEYWORD) && - (isKeyword (token, KEYWORD_get) || isKeyword (token, KEYWORD_set))) + if (isType (token, TOKEN_KEYWORD) && canBePropertyName (token)) { - token->type = TOKEN_IDENTIFIER; // treat as function name + // treat as function name + token->type = TOKEN_IDENTIFIER; + token->keyword = KEYWORD_NONE; }
if (! isType(token, TOKEN_KEYWORD))
Modified: ctags/parsers/matlab.c 11 lines changed, 6 insertions(+), 5 deletions(-) =================================================================== @@ -19,19 +19,20 @@
static tagRegexTable matlabTagRegexTable [] = { /* function [x,y,z] = asdf */ - { "^[ \t]*function[ \t]*\[.*\][ \t]*=[ \t]*([.a-zA-Z0-9_]+)", + { "^[ \t]*function[ \t]+\[.*\][ \t]*=[ \t]*([.a-zA-Z0-9_]+)", "\1", "f,function", NULL}, /* function x = asdf */ - {"^[ \t]*function[ \t]*[a-zA-Z0-9_]+[ \t]*=[ \t]*([.a-zA-Z0-9_]+)", + {"^[ \t]*function[ \t]+[a-zA-Z0-9_]+[ \t]*=[ \t]*([.a-zA-Z0-9_]+)", "\1", "f,function", NULL}, - /* function asdf */ - {"^[ \t]*function[ \t]*([.a-zA-Z0-9_]+)[^=]*$", "\1", + /* function asdf + * function asdf % some comment */ + {"^[ \t]*function[ \t]+([.a-zA-Z0-9_]+)[^=%]*($|%)", "\1", "f,function", NULL}, /* variables */ {"^[ \t]*([a-zA-Z0-9_]+)[ \t]*=[ \t]", "\1", "v,variable", NULL}, /* class definitions */ - {"^[ \t]*classdef[ \t]*([a-zA-Z0-9_]+)", "\1", + {"^[ \t]*classdef[ \t]+([a-zA-Z0-9_]+)", "\1", "c,class", NULL}, };
Modified: ctags/parsers/pascal.c 11 lines changed, 11 insertions(+), 0 deletions(-) =================================================================== @@ -178,6 +178,9 @@ static void findPascalTags (void)
if (c == '\0') /* if end of line */ { + if (incomment && comment_char == '/') + incomment = false; + dbp = readLineFromInputFile (); if (dbp == NULL || *dbp == '\0') continue; @@ -213,6 +216,14 @@ static void findPascalTags (void) incomment = true; comment_char = c; continue; + case '/': + if (*dbp == '/') /* found one line // comment */ + { + incomment = true; + comment_char = c; + dbp++; + } + continue; case '(': if (*dbp == '*') /* found open (* comment */ {
Modified: ctags/parsers/powershell.c 35 lines changed, 35 insertions(+), 0 deletions(-) =================================================================== @@ -42,6 +42,7 @@ typedef enum { K_CLASS, K_FILTER, K_ENUM, + K_ENUMLABEL, COUNT_KIND } powerShellKind;
@@ -51,6 +52,7 @@ static kindDefinition PowerShellKinds[COUNT_KIND] = { { true, 'c', "class", "classes" }, { true, 'i', "filter", "filter" }, { true, 'g', "enum", "enum names" }, + { true, 'e', "enumlabel", "enum labels" }, };
@@ -648,6 +650,30 @@ static bool parseEnum (tokenInfo *const token) return readNext; }
+/* parses declarations of the form + * <label> [= <int-value>] + * that is, contents of an enum + */ +static bool parseEnumLabel (tokenInfo *const token) +{ + bool readNext = true; + + if (token->parentKind != K_ENUM) + return false; + + if (token->type != TOKEN_IDENTIFIER) + return false; + + makeSimplePowerShellTag (token, K_ENUMLABEL, ACCESS_UNDEFINED); + readToken (token); + if (token->type != TOKEN_EQUAL_SIGN) + readNext = false; + else /* skip int-value */ + readToken (token); + + return readNext; +} + /* parses declarations of the form * $var = VALUE */ @@ -735,6 +761,11 @@ static void enterScope (tokenInfo *const parentToken, readNext = parseVariable (token); break;
+ case TOKEN_IDENTIFIER: + if (parentKind == K_ENUM) + readNext = parseEnumLabel (token); + break; + default: break; }
@@ -770,5 +801,9 @@ extern parserDefinition* PowerShellParser (void) def->parser = findPowerShellTags; def->keywordTable = PowerShellKeywordTable; def->keywordCount = ARRAY_SIZE (PowerShellKeywordTable); + + def->versionCurrent = 1; + def->versionAge = 1; + return def; }
Modified: scripts/update-ctags.py 4 lines changed, 4 insertions(+), 0 deletions(-) =================================================================== @@ -33,6 +33,10 @@ for f in ['dsl/es.c', 'dsl/es.h', 'dsl/optscript.c', 'dsl/optscript.h']: shutil.copy(srcdir + '/' + f, dstdir + '/' + f)
+print('Copying libreadtags files...') +for f in ['libreadtags/readtags.c', 'libreadtags/readtags.h']: + shutil.copy(srcdir + '/' + f, dstdir + '/' + f) + os.chdir(srcdir) main_src_files = glob.glob('main/*.c') + glob.glob('main/*.h') os.chdir(dstdir)
Modified: src/tagmanager/tm_parser.c 16 lines changed, 8 insertions(+), 8 deletions(-) =================================================================== @@ -669,13 +669,12 @@ static TMParserMapGroup group_FORTRAN[] = {
static TMParserMapEntry map_MATLAB[] = { {'f', tm_tag_function_t}, // function - {'v', tm_tag_variable_t}, // variable + {'v', tm_tag_undef_t}, // variable {'c', tm_tag_class_t}, // class }; static TMParserMapGroup group_MATLAB[] = { {N_("Classes"), TM_ICON_CLASS, tm_tag_class_t}, {N_("Functions"), TM_ICON_METHOD, tm_tag_function_t}, - {N_("Variables"), TM_ICON_VAR, tm_tag_variable_t}, };
#define map_CUDA map_C @@ -946,17 +945,18 @@ static TMParserMapGroup group_JSON[] = { #define group_ZEPHIR group_PHP
static TMParserMapEntry map_POWERSHELL[] = { - {'f', tm_tag_function_t}, // function - {'v', tm_tag_variable_t}, // variable - {'c', tm_tag_class_t}, // class - {'i', tm_tag_function_t}, // filter - {'g', tm_tag_enum_t}, // enum + {'f', tm_tag_function_t}, // function + {'v', tm_tag_variable_t}, // variable + {'c', tm_tag_class_t}, // class + {'i', tm_tag_function_t}, // filter + {'g', tm_tag_enum_t}, // enum + {'e', tm_tag_enumerator_t}, // enumlabel }; static TMParserMapGroup group_POWERSHELL[] = { {N_("Classes"), TM_ICON_CLASS, tm_tag_class_t}, {N_("Functions"), TM_ICON_METHOD, tm_tag_function_t}, {N_("Enums"), TM_ICON_STRUCT, tm_tag_enum_t}, - {N_("Variables"), TM_ICON_VAR, tm_tag_variable_t}, + {N_("Variables"), TM_ICON_VAR, tm_tag_variable_t | tm_tag_enumerator_t}, };
static TMParserMapEntry map_JULIA[] = {
Modified: tests/ctags/enum.ps1.tags 16 lines changed, 16 insertions(+), 0 deletions(-) =================================================================== @@ -6,3 +6,19 @@ EnumName3 enum: EnumName3 EnumName4�2�0 enum: EnumName4 +Label11�4�EnumName1�0 +enumerator: EnumName1 :: Label11 +Label12�4�EnumName1�0 +enumerator: EnumName1 :: Label12 +Label21�4�EnumName2�0 +enumerator: EnumName2 :: Label21 +Label22�4�EnumName2�0 +enumerator: EnumName2 :: Label22 +Label31�4�EnumName3�0 +enumerator: EnumName3 :: Label31 +Label32�4�EnumName3�0 +enumerator: EnumName3 :: Label32 +Label41�4�EnumName4�0 +enumerator: EnumName4 :: Label41 +Label42�4�EnumName4�0 +enumerator: EnumName4 :: Label42
Modified: tests/ctags/matlab_backtracking.m.tags 10 lines changed, 0 insertions(+), 10 deletions(-) =================================================================== @@ -1,12 +1,2 @@ backtrack�16�0 function: backtrack -cDDfnc�16384�0 -variable: cDDfnc -d�16384�0 -variable: d -fcall�16384�0 -variable: fcall -fn�16384�0 -variable: fn -xn�16384�0 -variable: xn
Modified: tests/ctags/matlab_test.m.tags 6 lines changed, 2 insertions(+), 4 deletions(-) =================================================================== @@ -1,5 +1,3 @@ -FAIL6�16�0 -function: FAIL6 func1�16�0 function: func1 func2�16�0 @@ -8,5 +6,5 @@ func3 function: func3 func4�16�0 function: func4 -functionality�16384�0 -variable: functionality +func5�16�0 +function: func5
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).