Generované (překládané) zdrojáky a čísla řádků // typicky šablony
- v6ak
- Člen | 206
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:
- 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.
- Naučit Laděnku tyto informace smysluplně využívat. Nejsem proti možnosti přepnutí na generovaný kód.
- Umožnit v templatovacím engine tyto informace co nejjednodušeji generovat.
- 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
Nadšení je evidentně pramalé :-)
Implementovat by to znamenalo trochu poupravit chování vyhodnocování
šablon i filtrů šablon (tzn. i LatteFilter
u). 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
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.