Add source maps to templates

master
Vitaliy Filippov 2017-02-24 14:07:33 +03:00
parent 86d7f58e00
commit 912141f7c8
3 changed files with 48 additions and 6 deletions

View File

@ -89,7 +89,7 @@ chunks = {
$$ = ''; $$ = '';
} }
| chunks chunk { | chunks chunk {
$$ = $1 . $2; $$ = $1 . "# line ".$this->template->lexer->lineno."\n" . $2;
} }
. .
chunk = literal { chunk = literal {

View File

@ -4,7 +4,7 @@
* Homepage: http://yourcmc.ru/wiki/VMX::Template * Homepage: http://yourcmc.ru/wiki/VMX::Template
* License: GNU GPLv3 or later * License: GNU GPLv3 or later
* Author: Vitaliy Filippov, 2006-2016 * Author: Vitaliy Filippov, 2006-2016
* Version: V3 (LALR), 2016-10-31 * Version: V3 (LALR), 2017-02-24
* *
* This file contains the implementation of VMX::Template compiler. * This file contains the implementation of VMX::Template compiler.
* It is only used when a template is compiled in runtime. * It is only used when a template is compiled in runtime.
@ -190,26 +190,38 @@ class VMXTemplateCompiler
// Generate code for functions // Generate code for functions
$code = ''; $code = '';
$functions = array(); $functions = [];
$smap = [];
$l = 9;
foreach ($this->st->functions as $n => $f) foreach ($this->st->functions as $n => $f)
{ {
$ms = [];
preg_match_all('/(?:^|\n)# line (\d+)|\n/', $f['body'], $ms, PREG_SET_ORDER);
foreach ($ms as $m)
{
$l++;
if (!empty($m[1]))
$smap[] = [ $l, $m[1] ];
}
$code .= $f['body']; $code .= $f['body'];
$functions[$n] = $f['args']; $functions[$n] = $f['args'];
} }
// Assemble the class code // Assemble the class code
$functions = var_export($functions, true); $functions = var_export($functions, true);
$smap = var_export($smap, true);
$rfn = addcslashes($this->options->input_filename, '\\\''); $rfn = addcslashes($this->options->input_filename, '\\\'');
$code = "<?php // {$this->options->input_filename} $code = "<?php // {$this->options->input_filename}
class Template_$func_ns extends VMXTemplate { class Template_$func_ns extends VMXTemplate {
static \$template_filename = '$rfn'; static \$template_filename = '$rfn';
static \$version = ".VMXTemplate::CODE_VERSION."; static \$version = ".VMXTemplate::CODE_VERSION.";
static \$functions = $functions;
function __construct(\$t) { function __construct(\$t) {
\$this->tpldata = &\$t->tpldata; \$this->tpldata = &\$t->tpldata;
\$this->parent = &\$t; \$this->parent = &\$t;
} }
$code $code
static \$functions = $functions;
static \$smap = $smap;
} }
"; ";
@ -3466,7 +3478,7 @@ class VMXTemplateParser extends lime_parser {
// (2) chunks := chunks chunk // (2) chunks := chunks chunk
$result = reset($tokens); $result = reset($tokens);
$result = $tokens[0] . $tokens[1]; $result = $tokens[0] . "# line ".$this->template->lexer->lineno."\n" . $tokens[1];
} }
function reduce_3_chunk_1($tokens, &$result) { function reduce_3_chunk_1($tokens, &$result) {

View File

@ -8,7 +8,7 @@
* Homepage: http://yourcmc.ru/wiki/VMX::Template * Homepage: http://yourcmc.ru/wiki/VMX::Template
* License: GNU GPLv3 or later * License: GNU GPLv3 or later
* Author: Vitaliy Filippov, 2006-2016 * Author: Vitaliy Filippov, 2006-2016
* Version: V3 (LALR), 2016-10-31 * Version: V3 (LALR), 2017-02-24
* *
* The template engine is split into two parts: * The template engine is split into two parts:
* (1) This file - always used when running templates * (1) This file - always used when running templates
@ -349,6 +349,36 @@ class VMXTemplate
return $t; return $t;
} }
/**
* Translate template file line number from stack frame $frame (taken from debug_backtrace())
*/
public static function translateLine(&$frame)
{
if (!empty($frame['class']) && substr($frame['class'], 0, 9) == 'Template_')
{
$class = $frame['class'];
if (isset($class::$smap))
{
$l = $frame['line'];
$s = 0;
$e = count($class::$smap);
while ($e > $s+1)
{
if ($l < $class::$smap[($e+$s)>>1][0])
$e = ($e+$s)>>1;
else
$s = ($e+$s)>>1;
}
$frame['class'] = '';
$frame['type'] = '';
if (substr($frame['function'], 0, 3) == 'fn_')
$frame['function'] = substr($frame['function'], 3);
$frame['file'] = $class::$template_filename;
$frame['line'] = $s;
}
}
}
/** /**
* Load file (with caching) * Load file (with caching)
* *