Update python parser to the latest version from uctags

This version contains fixes related to parsing function parameters.
This commit is contained in:
Jiří Techet 2022-09-03 00:04:47 +02:00
parent 5cdfe35cf2
commit 41b40120ea

View File

@ -23,6 +23,7 @@
#include "debug.h"
#include "xtag.h"
#include "objpool.h"
#include "ptrarray.h"
#define isIdentifierChar(c) \
(isalnum (c) || (c) == '_' || (c) >= 0x80)
@ -935,41 +936,42 @@ static vString *parseReturnTypeAnnotation (tokenInfo *const token)
return NULL;
}
static bool parseClassOrDef (tokenInfo *const token,
const vString *const decorators,
pythonKind kind, bool isCDef)
{
vString *arglist = NULL;
tokenInfo *name = NULL;
tokenInfo *parameterTokens[16] = { NULL };
vString *parameterTypes [ARRAY_SIZE(parameterTokens)] = { NULL };
unsigned int parameterCount = 0;
NestingLevel *lv;
int corkIndex;
struct typedParam {
tokenInfo *token;
vString *type;
};
if (isCDef)
static struct typedParam *makeTypedParam (tokenInfo *token, vString *type)
{
if (! readCDefName (token, &kind))
return false;
}
else
{
readToken (token);
if (token->type != TOKEN_IDENTIFIER)
return false;
struct typedParam *p = xMalloc (1, struct typedParam);
p->token = token;
p->type = type;
return p;
}
name = newToken ();
copyToken (name, token);
static struct typedParam *makeTypedParamWithCopy (const tokenInfo *token, const vString *type)
{
tokenInfo *token_copied = newToken ();
copyToken (token_copied, token);
readToken (token);
/* collect parameters or inheritance */
if (token->type == '(')
vString *type_copied = type? vStringNewCopy (type): NULL;
return makeTypedParam (token_copied, type_copied);
}
static void deleteTypedParam (struct typedParam *p)
{
deleteToken (p->token);
vStringDelete (p->type); /* NULL is acceptable. */
eFree (p);
}
static void parseArglist (tokenInfo *const token, const int kind,
vString *const arglist, ptrArray *const parameters)
{
int prevTokenType = token->type;
int depth = 1;
arglist = vStringNew ();
if (kind != K_CLASS)
reprCat (arglist, token);
@ -998,19 +1000,171 @@ static bool parseClassOrDef (tokenInfo *const token,
else if (kind != K_CLASS && depth == 1 &&
token->type == TOKEN_IDENTIFIER &&
(prevTokenType == '(' || prevTokenType == ',') &&
parameterCount < ARRAY_SIZE (parameterTokens) &&
PythonKinds[K_PARAMETER].enabled)
{
tokenInfo *parameterName = newToken ();
tokenInfo *parameterName;
vString *parameterType;
struct typedParam *parameter;
parameterName = newToken ();
copyToken (parameterName, token);
parameterTokens[parameterCount] = parameterName;
parameterTypes [parameterCount++] = parseParamTypeAnnotation (token, arglist);
parameterType = parseParamTypeAnnotation (token, arglist);
parameter = makeTypedParam (parameterName, parameterType);
ptrArrayAdd (parameters, parameter);
}
}
while (token->type != TOKEN_EOF && depth > 0);
}
static void parseCArglist (tokenInfo *const token, const int kind,
vString *const arglist, ptrArray *const parameters)
{
int depth = 1;
tokenInfo *pname = newToken ();
vString *ptype = vStringNew ();
vStringCat (arglist, token->string); /* '(' */
while (true)
{
readToken (token);
if (token->type == TOKEN_EOF)
{
/* Unexpected input. */
vStringClear (arglist);
ptrArrayClear (parameters);
break;
}
if (depth == 1 && (token->type == ',' || token->type == ')'))
{
if (pname->type == TOKEN_IDENTIFIER)
{
struct typedParam *p;
/*
* Clean up the type string.
* The type string includes the parameter name at the end.
* 1. Trim the parameter name at the end.
* 2. Then, trim the white space at the end of the type string.
* 3. If the type string is not empty,
* 3.a append (the type stirng + ' ' + the parameter name) to arglist.
* 3.b else just append the parameter name to arglist.
*
* FIXME:
* This doesn't work well with an array and a function pointer.
*
* f(..., int seq [dim], ...)
* in this case, dim is extacted as a parameter.
*
* f(..., int (*fn)(int), ...)
* in this case , int is extacted as a parameter.
*/
Assert (vStringLength (ptype) >= vStringLength (pname->string));
size_t ptype_len = vStringLength (ptype) - vStringLength (pname->string);
vStringTruncate (ptype, ptype_len);
if (vStringLength (ptype) > 0)
{
vStringStripTrailing (ptype);
if (vStringLength (ptype) > 0)
{
vStringCat (arglist, ptype);
vStringPut (arglist, ' ');
}
}
vStringCat (arglist, pname->string);
p = makeTypedParamWithCopy (pname, vStringIsEmpty(ptype)? NULL: ptype);
ptrArrayAdd (parameters, p);
}
if (token->type == ')')
{
vStringPut (arglist, ')');
break;
}
vStringCatS (arglist, ", ");
vStringClear (ptype);
pname->type = TOKEN_UNDEFINED;
continue;
}
if (token->type == '(' ||
token->type == '[' ||
token->type == '{')
{
vStringPut (ptype, token->type);
depth ++;
continue;
}
if (token->type == ')' ||
token->type == ']' ||
token->type == '}')
{
vStringPut (ptype, token->type);
depth --;
continue;
}
if (token->type == TOKEN_IDENTIFIER || token->type == TOKEN_KEYWORD)
{
if (vStringLength (ptype) > 0
&& (isalnum ((unsigned char)vStringLast (ptype))
|| vStringLast (ptype) == ','))
vStringPut (ptype, ' ');
vStringCat (ptype, token->string);
if (!isdigit ((unsigned char)vStringLast (token->string)))
copyToken (pname, token);
continue;
}
vStringCat (ptype, token->string);
}
vStringDelete (ptype);
deleteToken (pname);
}
static bool parseClassOrDef (tokenInfo *const token,
const vString *const decorators,
pythonKind kind, bool isCDef)
{
vString *arglist = NULL;
tokenInfo *name = NULL;
ptrArray *parameters = NULL;
NestingLevel *lv;
int corkIndex;
if (isCDef)
{
if (! readCDefName (token, &kind))
return false;
}
else
{
readToken (token);
if (token->type != TOKEN_IDENTIFIER)
return false;
}
name = newToken ();
copyToken (name, token);
readToken (token);
/* collect parameters or inheritance */
if (token->type == '(')
{
arglist = vStringNew ();
parameters = ptrArrayNew ((ptrArrayDeleteFunc)deleteTypedParam);
if (isCDef && kind != K_CLASS)
parseCArglist (token, kind, arglist, parameters);
else
parseArglist (token, kind, arglist, parameters);
}
if (kind == K_CLASS)
corkIndex = makeClassTag (name, arglist, decorators);
else
@ -1022,24 +1176,24 @@ static bool parseClassOrDef (tokenInfo *const token,
deleteToken (name);
vStringDelete (arglist);
if (parameterCount > 0)
if (parameters && !ptrArrayIsEmpty (parameters))
{
unsigned int i;
for (i = 0; i < parameterCount; i++)
for (i = 0; i < ptrArrayCount (parameters); i++)
{
int paramCorkIndex = makeSimplePythonTag (parameterTokens[i], K_PARAMETER);
deleteToken (parameterTokens[i]);
struct typedParam *parameter = ptrArrayItem (parameters, i);
int paramCorkIndex = makeSimplePythonTag (parameter->token, K_PARAMETER);
tagEntryInfo *e = getEntryInCorkQueue (paramCorkIndex);
if (e && parameterTypes[i])
if (e && parameter->type)
{
e->extensionFields.typeRef [0] = eStrdup ("typename");
e->extensionFields.typeRef [1] = vStringDeleteUnwrap (parameterTypes[i]);
parameterTypes[i] = NULL;
}
vStringDelete (parameterTypes[i]); /* NULL is acceptable. */
e->extensionFields.typeRef [1] = vStringDeleteUnwrap (parameter->type);
parameter->type = NULL;
}
}
}
ptrArrayDelete (parameters); /* NULL is acceptable. */
tagEntryInfo *e;
vString *t;