Generované (překládané) zdrojáky a čísla řádků // typicky šablony

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

Zdravím,
již dříve jsem se s setkal s problémy s čísly řádků a zdrojových souborů. Problém nastává, když dojde k chybě a Laděnka se mě snaží navigovat. To u ručně psaného kódu problém není, ale jakmile začne být generován, musím upravit původní zdroják. Čísla řádků apod. se samozřejmě často liší, což situaci poněkud znesnadňuje. Problém je také v názvech souborů, pokud je název vygenerovaného souboru nicříkající, což u šablon spolehlivě je.

Co s tím? Nejsme první, kdo podobná problém řeší. Dávno tento problém byl vyřešen v Javě. Tedy, je možné uvést zdrojový soubor pomocí atributu SourceFile (SourceFile v knihovně BCEL) a z offsetů bytecode je možné získat původní řádky pomocí atributu LineNumberTable (LineNumberTable v knihovně BCEL).

V praxi by to znamenalo zhruba toto:

  1. Vymyslet nějaký způsob a formát zaznamenávání těchto údajů v komentářích. Jedna z možností je to, že by soubor obsahoval pouze odkaz na tyto atributy.
  2. Naučit Laděnku tyto informace smysluplně využívat. Nejsem proti možnosti přepnutí na generovaný kód.
  3. Umožnit v templatovacím engine tyto informace co nejjednodušeji generovat.
  4. Upravit LatteFilter tak, aby tyto informace generoval.

// Předpokládám, že v současné době to není kdekoli mimo šablony používáno.

Možné rozdíly mezi Javou a situací v Nette:

  • Zatímco SourceFile je v Javě jeden na třídu a zároveň jeden na soubor (vnitřní třída si při kompilaci vyžádá zvláštní soubor), v PHP to bude jeden na soubor, který obsahuje žádnou nebo více tříd. IMHO žádný problém, jen SourceFile nelze psát pomocí anotací. (To v Javě teda taky nejsou, ty mimochodem vznikly později.)
  • Zatímco v jazyce Java asi není problém určit přesně řádek, u LatteFilter by to (zvlášť s extra makry) problém být mohl. (Nejsem si jist, zda makro lze napsat na více řádků.) V takovém případě by se hodilo navrhnout formát jinak a umožnit jednomu řádku generovaného kódu přiřadit rozsah řádků kódu zdrojového. V tuto chvíli si nejsem jist, jak moc to bude nutné.
  • Zatímco v bytecode má každá operace jiný offset, v generovaném PHP může (ale při šikovném generování nemusí) být více operací uvedeno na jednom řádku.
  • Teoreticky tu můžeme mít více po sobě jdoucích přegenerování, ale to bych až tak neřešil. (V Javě řešeno dost specificky.)

Jaké je nadšení k těmto úpravám?

jakubkulhan
Člen | 55
+
0
-

Nadšení je evidentně pramalé :-)

Implementovat by to znamenalo trochu poupravit chování vyhodnocování šablon i filtrů šablon (tzn. i LatteFilteru). Nyní je filtr prostý callback, jenž převezme vstupní kód a vychrlí přežvýkaný kód. Každý filtr by musel vracet převodní tabulku. Možností je více:

  • callback bude vracet pole/objekt s přežvýkaným textem a převodní tabulkou
  • místo callbacku bude filtr objekt s definovaným interfacem

Jednodušší se mi zdá první možnost s tím, že callback bude vracet objekt. Aby se zachovala zpětná kompatiblita, callback bude moci vrátit i pouze přežvýkaný řetězec. Otázka zní, co s tím, když některý z filtrů vrátí pouze řetězec? Navrhoval bych následující heuristiku: jestli se počet řádků zachoval (přežvýkaný řetězec má stejně řádků jako vstupní), tabulka se nemění, je-li na výstupu jiný počet řádků, vypne se fce převádění řádků.

Výsledná převodní tabulka (je-li dostupná; nebo-li jestliže některý z filtrů nedonutil převádění řádků vypnout) se nakešuje stejně jako zkompilovaná šablona.

Nechávat na Laděnce, aby převáděla čísla řádků chyb z šablon je e-e. Místo toho bych před vyhodnocováním šablony nastavil error handler na interní funkci šablony (která může vědět, jak získat data o převodu řádků z keše; narozdíl od Laděnky), která by u chyby zaměnila čísla řádků a název souboru a vyhodila výjimku, jež by zachytila funkce volající vyhodnocení šablony (Template::render), ta by obnovila error handler a vyhodila výjimku dále. Takovou výjimku se změněnými čísly řádků a názvu souboru by již zachytila Laděnka a zobrazila by ji.

v6ak
Člen | 206
+
0
-

O nutnosti upravit LatteFilter a další jsem již psal. Ony obě možnosti by ale nemusely mít problémy se zpětnou kompatibilitou. Možná bych se i tak přiklonil spíše k vrácenému objektu, kdyby tu nebyl problém se více po sobě jdoucími filtry.

Pro starší filtry bych se nepokloušel o heuristiku, zdá se mi to jako:

  • zbytečné
  • věštění, které se nemusí povést

Asi máme trošku jinou představu o určení této tabulky. Já ji nechci omezovat jen na šablony, ačkoli u nich bude zřejmě nejvetší využití, ale chtěl bych tuto možnost dát všem souborům. Z toho zřejmě pramení také rozdílný názor na to, jestli tuto zodpovědnost nechat Laděnce. V případě, že by to bylo pro libovolný soubor, pak to Laděnce IMHO celkem dost patří. Možná by akorát mohla tuto zodpovědnost přenechat jiné třídě, takže tyto informace by byly k dispozici i dalším třídám, ale to už je detail. Prostě jsem to nechtěl omezovat na šablony.

Získání čísel řádků by šlo i přidáním nějakého suffixu (třeba .lines.php) na konec názvu souboru.