jeudi 17 mars 2016

How to determine the full class name of an @var when parsing doc comments in PHP?

In PHP I'm parsing the /** */ doc comments for each property of a class. I extract the @var line to determine the type of each property.

This works well for internal types and typically also for classes. However when namespaces and especially the use statement is used I run into trouble.

In my code, the namespace of the class is added to the class name of the @var, completely ignoring the use statement.

Sample class

<?php

namespace My;

use Foo\Bar;
use Qux\FromAbove as Qux;

class Sample
{
  /** @var int */
  public $one;

  /** @var Thing */
  public $two;

  /** @var \Other\Stuff */
  public $three;

  /** @var Bar */
  public $four;

  /** @var Qux */
  public $five;
}

Code to determine type

The code is simplified to showcase this specific issue.

$reflClass = new ReflectionClass(My\Sample::class);

foreach ($reflClass->getProperties as $reflProp) {
   $doc = $reflProp->getDocComment();
   if (!preg_match('~^[/\*\s]*@var\s+(.*?)[\/\*\s]*$~m', $doc, $match)) continue;

   $var = $match[1];

   if (in_array($var, ['int', 'string', 'float', /* ... */])) {
     // Internal type
     $type = $var;
   } elseif ($var[0] === '\\') {
     // Absolute class name
     $type = substr($var, 1);
   } else {
     // Relative class name
     $ns = $reflProp->getDeclaringClass()->getNamespaceName();
     $type = ($ns ? $ns . '\\' : '') . $var;
   }

   $types[$reflProp->getName()] = $type;
}

var_dump($types);

Output

array(5) {
  'one' =>
  string(3) "int"
  'two' =>
  string(8) "My\Thing"
  'three' =>
  string(11) "Other\Stuff"
  'four' =>
  string(6) "My\Bar"
  'five' =>
  string(6) "My\Qux"
}

How can I determine that @var Bar resolved to Foo\Bar and @var Qux resolves to Qux\FromAbove?





Aucun commentaire:

Enregistrer un commentaire