Skip to content

Commit

Permalink
Merge pull request universal-ctags#2577 from masatake/php-typed-props
Browse files Browse the repository at this point in the history
PHP: fill the typeref field for variable kind tags appeared as class properties
  • Loading branch information
masatake committed Jun 29, 2020
2 parents ae32548 + 5ed230b commit fe3f312
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 29 deletions.
2 changes: 2 additions & 0 deletions Units/parser-php.r/php-7-4-typed-props.d/args.ctags
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
--sort=no
--fields=+{typeref}{inherits}
9 changes: 9 additions & 0 deletions Units/parser-php.r/php-7-4-typed-props.d/expected.tags
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Person input.php /^class Person$/;" c
age input.php /^ public int $age;$/;" v class:Person typeref:unknown:int
User input.php /^class User extends Person$/;" c inherits:Person
id input.php /^ public int $id;$/;" v class:User typeref:unknown:int
name input.php /^ public ?string $name;$/;" v class:User typeref:unknown:?string
next input.php /^ public self $next;$/;" v class:User typeref:class:User
child input.php /^ public parent $child;$/;" v class:User typeref:class:Person
__construct input.php /^ public function __construct($id, $name) {$/;" f class:User
u input.php /^$u = new User (0, "A");$/;" v
23 changes: 23 additions & 0 deletions Units/parser-php.r/php-7-4-typed-props.d/input.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php
// Derived from https://www.php.net/manual/en/migration74.new-features.php
class Person
{
public int $age;
}

class User extends Person
{
public int $id;
public ?string $name;
public self $next;
public parent $child;
public function __construct($id, $name) {
$this->id = $id;
$this->name = $name;
$this->next = $this;
$this->child = $this;
}
}
$u = new User (0, "A");
echo $u->next->name;
?>
86 changes: 57 additions & 29 deletions parsers/php.c
Original file line number Diff line number Diff line change
Expand Up @@ -356,18 +356,54 @@ static void makePhpTagEntry (tagEntryInfo *const e)
makeTagEntry (e);
makeQualifiedTagEntry (e);
}
static void makeSimplePhpTag (const tokenInfo *const token, const phpKind kind,
const accessType access)

static void fillTypeRefField (tagEntryInfo *const e,
const vString *const rtype, const tokenInfo *const token)
{
if ((vStringLength (rtype) == 4)
&& (strcmp (vStringValue (rtype), "self") == 0)
&& vStringLength (token->scope) > 0)
{
if (token->parentKind == -1)
e->extensionFields.typeRef [0] = "unknown";
else
e->extensionFields.typeRef [0] = PhpKinds [token->parentKind].name;
e->extensionFields.typeRef [1] = vStringValue (token->scope);
}
else if ((vStringLength (rtype) == 6)
&& (strcmp (vStringValue (rtype), "parent") == 0)
&& (ParentClass && vStringLength (ParentClass) > 0))
{
e->extensionFields.typeRef [0] = "class";
e->extensionFields.typeRef [1] = vStringValue (ParentClass);
}
else
{
e->extensionFields.typeRef [0] = "unknown";
e->extensionFields.typeRef [1] = vStringValue (rtype);
}
}

static void makeTypedPhpTag (const tokenInfo *const token, const phpKind kind,
const accessType access, vString* typeName)
{
if (PhpKinds[kind].enabled)
{
tagEntryInfo e;

initPhpEntry (&e, token, kind, access);
if (typeName)
fillTypeRefField (&e, typeName, token);
makePhpTagEntry (&e);
}
}

static void makeSimplePhpTag (const tokenInfo *const token, const phpKind kind,
const accessType access)
{
makeTypedPhpTag (token, kind, access, NULL);
}

static void makeNamespacePhpTag (const tokenInfo *const token, const vString *const name)
{
if (PhpKinds[K_NAMESPACE].enabled)
Expand Down Expand Up @@ -417,30 +453,7 @@ static void makeFunctionTag (const tokenInfo *const token,
if (arglist)
e.extensionFields.signature = vStringValue (arglist);
if (rtype)
{
if ((vStringLength (rtype) == 4)
&& (strcmp (vStringValue (rtype), "self") == 0)
&& vStringLength (token->scope) > 0)
{
if (token->parentKind == -1)
e.extensionFields.typeRef [0] = "unknown";
else
e.extensionFields.typeRef [0] = PhpKinds [token->parentKind].name;
e.extensionFields.typeRef [1] = vStringValue (token->scope);
}
else if ((vStringLength (rtype) == 6)
&& (strcmp (vStringValue (rtype), "parent") == 0)
&& (ParentClass && vStringLength (ParentClass) > 0))
{
e.extensionFields.typeRef [0] = "class";
e.extensionFields.typeRef [1] = vStringValue (ParentClass);
}
else
{
e.extensionFields.typeRef [0] = "unknown";
e.extensionFields.typeRef [1] = vStringValue (rtype);
}
}
fillTypeRefField (&e, rtype, token);

makePhpTagEntry (&e);
}
Expand Down Expand Up @@ -1556,7 +1569,7 @@ static bool parseUse (tokenInfo *const token)
/* parses declarations of the form
* $var = VALUE
* $var; */
static bool parseVariable (tokenInfo *const token)
static bool parseVariable (tokenInfo *const token, vString * typeName)
{
tokenInfo *name;
bool readNext = true;
Expand Down Expand Up @@ -1598,7 +1611,7 @@ static bool parseVariable (tokenInfo *const token)
if (token->parentKind == K_CLASS ||
token->parentKind == K_INTERFACE ||
token->parentKind == K_TRAIT)
makeSimplePhpTag (name, K_VARIABLE, access);
makeTypedPhpTag (name, K_VARIABLE, access, typeName);
}
else
readNext = false;
Expand Down Expand Up @@ -1658,6 +1671,7 @@ static void enterScope (tokenInfo *const parentToken,
const int parentKind)
{
tokenInfo *token = newToken ();
vString *typeName = vStringNew ();
int origParentKind = parentToken->parentKind;

copyToken (token, parentToken, true);
Expand Down Expand Up @@ -1727,8 +1741,21 @@ static void enterScope (tokenInfo *const parentToken,
}
break;

case TOKEN_QMARK:
vStringClear (typeName);
vStringPut (typeName, '?');
readNext = true;
break;
case TOKEN_IDENTIFIER:
vStringCat (typeName, token->string);
readNext = true;
break;
case TOKEN_VARIABLE:
readNext = parseVariable (token);
readNext = parseVariable (token,
vStringIsEmpty(typeName)
? NULL
: typeName);
vStringClear (typeName);
break;

default: break;
Expand All @@ -1740,6 +1767,7 @@ static void enterScope (tokenInfo *const parentToken,

copyToken (parentToken, token, false);
parentToken->parentKind = origParentKind;
vStringDelete (typeName);
deleteToken (token);
}

Expand Down

0 comments on commit fe3f312

Please sign in to comment.