Vylepšení anotací

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
paranoiq
Člen | 392
+
0
-

mám návrh na dvě vylepšení anotací. Nette\Annotations neumí typ NULL a neumí klasické dokumentační anotace bez závorek. pro anotace typu „@anotace text“ vrací místo textu jen TRUE. což je škoda. jednak nejdou číst dokumentační anotace a pak zapisování skalárů bez závorek je pohodlnější

patch:

Index: Annotations.php
===================================================================
--- Annotations.php	(revision 484)
+++ Annotations.php	(working copy)
@@ -109,11 +109,11 @@
 			return $cache;
 		}

-		preg_match_all('#@([a-zA-Z0-9_]+)(?:\(((?>[^\'")]+|\'[^\']*\'|"[^"]*")*)\))?#', $r->getDocComment(), $matches, PREG_SET_ORDER);
+		preg_match_all('#@([a-zA-Z0-9_]+)(?:\(((?>[^\'")]+|\'[^\']*\'|"[^"]*")*)\))?(?:[\t ]+(.+[^\s]))?#', $r->getDocComment(), $matches, PREG_SET_ORDER);
 		$cache = array();
 		foreach ($matches as $match)
 		{
-			if (isset($match[2])) {
+			if (isset($match[2]) && $match[2] != '') {
 				preg_match_all('#[,\s](?>([a-zA-Z0-9_]+)\s*=\s*)?([^\'",\s][^,]*|\'[^\']*\'|"[^"]*")#', ',' . $match[2], $matches, PREG_SET_ORDER);
 				$items = array();
 				$key = '';
@@ -129,6 +129,9 @@
 					} elseif (strcasecmp($val, 'false') === 0) {
 						$val = FALSE;

+					} elseif (strcasecmp($val, 'null') === 0) {
+						$val = NULL;
+
 					} elseif (is_numeric($val)) {
 						$val = 1 * $val;
 					}
@@ -143,6 +146,22 @@

 				$items = count($items) < 2 && $key === '' ? $val : new /*\*/ArrayObject($items, /*\*/ArrayObject::ARRAY_AS_PROPS);

+			} elseif (isset($matches[3])) {
+				$val = $match[3];
+				if (strcasecmp($val, 'true') === 0) {
+					$val = TRUE;
+
+				} elseif (strcasecmp($val, 'false') === 0) {
+					$val = FALSE;
+
+				} elseif (strcasecmp($val, 'null') === 0) {
+					$val = NULL;
+
+				} elseif (is_numeric($val)) {
+					$val = 1 * $val;
+				}
+				$items = $val;
+
 			} else {
 				$items = TRUE;
 			}

@anotace null“ vrátí typ NULL, stejně jako varianta v závorce.

@anotace ‚bla bla‘“ vrátí „‚bla bla‘“. uvozovky se neořezávají. je-li přítomna závorka i text, text se ignoruje: „@anotace(klic='hodnota') bla bla“ tedy vrátí to samé co vrací nyní

Davide, prosím, přidej to tam :]

paranoiq
Člen | 392
+
0
-

haló je tu někdo z „nadace“? :]

mimochodem, v keši Nette\Anotaions je chyba. keš míchá dohromady stejnojmenné metody a vlastnosti tříd

Editoval paranoiq (17. 8. 2009 18:22)

David Grudl
Nette Core | 8220
+
0
-

Neboj, pracuje se na tom ;)

paranoiq
Člen | 392
+
0
-

děkuji :)
pár dalších detailů máš v mejlu. máš zájem o anotace s dědičností?

paranoiq
Člen | 392
+
0
-

k tomu bugu + přeuspořádaná keš a rozšíření o anotace u funkcí

static protected function & init(/*\*/Reflector $r) {
        if ($r instanceof /*\*/ReflectionClass) {
            $class = $r->getName();
            $name  = '';

        } elseif ($r instanceof /*\*/ReflectionProperty) {
            $class = $r->getDeclaringClass()->getName();
            $name  = '$' . $r->getName();

        } elseif ($r instanceof /*\*/ReflectionMethod) {
            $class = $r->getDeclaringClass()->getName();
            $name  = $r->getName();

        } elseif ($r instanceof /*\*/ReflectionFunction) {
            $class = '';
            $name  = $r->getName();

        } else {
            throw new InvalidArgumentException('Cannot get annotations from an ' . get_class($r) . '!');
        }

        $cache = & self::$cache[$class][$name];
        if ($cache !== NULL) {
            return $cache;
        }
...

tu dědičnost zvažuju. nejsem si jistý, zda to bude tak užitečné jak jsem si myslel…

Editoval paranoiq (18. 8. 2009 10:47)

paranoiq
Člen | 392
+
0
-

Davide, díky za opravu a díky za NULL

jak to vidíš s tím parsováním normálních (dokumentačních) anotací?
bylo by to velmi užitečné například pro znovupoužití anotace @var (deserializace atp.)

(viděl jsem to i jinde. je dost zvláštní věc, že hned několik parserů anotací ignoruje zažitou syntaxi anotací, která se používá pro PHPDoc)

David Grudl
Nette Core | 8220
+
0
-

Implementováno

paranoiq
Člen | 392
+
0
-

wow. úžasné. děkuji. (konečně můžu vlastní řešení zahodit ;-)

Patrik Votoček
Člen | 2221
+
0
-

Nechtěl by někdo sepsat do Docky jak to funguje? Protože bych to rád využil ale absolutně to nechápu. A myslím že nejsem jediný.
 Díky.

redhead
Člen | 1313
+
0
-

Je nějaký způsob jak zadávat pole??

zkoušel jsem:

/**
 * @abc ( xyz = (ijk, lmn) )
 * nebo
 * @abc ( xyz = array(ijk, lmn) )
 */

ale nejde, předpokládám, že to není ani implementováno. Ale byla by to zajímavá feature (a pro mě i prospěšná)! Šlo by to implementovat?

Editoval redhead (7. 2. 2010 22:33)

paranoiq
Člen | 392
+
0
-

jednoduché pole lze zadat takto:

/**
 * @abc(ijk)
 * @abc(lmn)
 */

to co chceš ty, ale nevím

podobný dotaz tu už jednou byl. starý parser zanoření neumožňoval. ten nový jsem zatím takto podrobně nezkoumal

redhead
Člen | 1313
+
0
-

někdy se to může hodit, příklad – mám zautomatizovanou podporu cache pro nějaké metody v modelu a podle anotace ‚cache‘ ji chci kešovat:

/** @cache(expire = 604800, tags = (bli, ble, blu)) */
public function necoTahamZDb()
{
	//...
}

a podle toho by se nastavovala cache, ty tagy by byli v poli, aby se s nima dobře pracovalo. Samozřejmě to můžu dát do jiné anotace (třeba cache-tags), ale už to není tak pohodlné..

Petr Motejlek
Člen | 293
+
0
-

redhead napsal(a):

někdy se to může hodit, příklad…

To bych taky ocenil, ale aby to bylo možné prohat třeba fcí eval(), bylo by lepší tam mít napsáno tags = array(ble, ble, ble) ;)

Patrik Votoček
Člen | 2221
+
0
-

Petr Motejlek napsal(a):

…ale aby to bylo možné prohat třeba fcí eval()…

Auuuuuu (právě jsem se moc nechápavě praštil do hlavy)

redhead
Člen | 1313
+
0
-

no ono přes eval by to být nemuselo, ikdyž by bylo hezké psát třeba:

/** @cache(expire = 60*60*24*7) */

ale to klidně oželím, spíš bych byl ale pro, aby to ty vnořené pole parsovalo přes nějaký super ultra mega regulár..

Editoval redhead (15. 2. 2010 22:15)

Petr Motejlek
Člen | 293
+
0
-

Je to můj názor, ale zdá se mi, že je vhodnější, abych i v anotacích musel normálně dodržovat zápisy, které používá daný jazyk. (ble, ble, ble) prostě v PHP nic neznamená a je syntakticky špatně. Úplně nejvíc by se mi líbilo, aby se to zapisovalo jako array(‚ble‘, ‚ble‘, ‚ble‘). Už proto, že například 2 je něco jiného než ‚2‘. Ten eval() jsem naznačil právě kvůli tomu, že si myslím, že by to mělo být syntakticky správně.

Díky té nové podpoře anotací by měla stejně každá anotace způsobit vytvoření instance nějaké třídy, které se předá, co v té anotaci je. Jestli se na ni použije nějakej šílenej regulár, nebo se z toho udělá eval(), a budu moct použít i tu konstrukci typu 24 * 60 * 60, proč ne? Vždyť se to stejně cachuje…

Editoval Petr Motejlek (15. 2. 2010 22:14)

Petr Motejlek
Člen | 293
+
0
-

vrtak-cz napsal(a):

Petr Motejlek napsal(a):

…ale aby to bylo možné prohat třeba fcí eval()…

Auuuuuu (právě jsem se moc nechápavě praštil do hlavy)

Tak to jsem úplně nepochopil…

v6ak
Člen | 206
+
0
-

Proti evalu:

  • výkon
  • cachoevání: co když tam bude složitější výraz?
  • logika: složitější výrazy tam vlastně ani nepatří
  • krása zápisu
Petr Motejlek
Člen | 293
+
0
-

Já ten eval() jako takovej neprosazuju, určitě to není to nejlepší řešení. Mě osobně se strašně líbí, jak jsou řešené anotace například v Javě, a rád bych se podobnýho principu držel i v Nette. Je jasný, že je někde chyba v návrhu, když budu chtít v rámci anotace používat neprimitivní datový typy a funkce. Nicméně by se mi líbilo, abych na první pohled poznal, z titulu, že znám syntax PHP, co daná anotace představuje.

David Grudl
Nette Core | 8220
+
0
-