Skip to content

Commit 05457e3

Browse files
Implement sourcecode rendering.
1 parent 5941d2f commit 05457e3

File tree

1 file changed

+304
-0
lines changed
  • PHP/CodeCoverage/Report/HTML/Renderer

1 file changed

+304
-0
lines changed

PHP/CodeCoverage/Report/HTML/Renderer/File.php

Lines changed: 304 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@
4343
* @since File available since Release 1.1.0
4444
*/
4545

46+
if (!defined('T_NAMESPACE')) {
47+
define('T_NAMESPACE', 1000);
48+
}
49+
50+
if (!defined('T_TRAIT')) {
51+
define('T_TRAIT', 1001);
52+
}
53+
4654
/**
4755
* Renders a PHP_CodeCoverage_Report_Node_File node.
4856
*
@@ -107,14 +115,310 @@ public function render(PHP_CodeCoverage_Report_Node_File $node, $file, $title =
107115

108116
if ($this->yui) {
109117
$template = new Text_Template($this->templatePath . 'file.html');
118+
119+
$yuiTemplate = new Text_Template(
120+
$this->templatePath . 'yui_item.js'
121+
);
110122
} else {
111123
$template = new Text_Template(
112124
$this->templatePath . 'file_no_yui.html'
113125
);
114126
}
115127

128+
$coverageData = $node->getCoverageData();
129+
$ignoredLines = $node->getIgnoredLines();
130+
$testData = $node->getTestData();
131+
list($codeLines, $fillup) = $this->loadFile($node->getPath());
132+
$lines = '';
133+
$i = 1;
134+
135+
foreach ($codeLines as $line) {
136+
$css = '';
137+
138+
if (!isset($ignoredLines[$i]) && isset($coverageData[$i])) {
139+
$count = '';
140+
$numTests = count($coverageData[$i]);
141+
142+
if ($coverageData[$i] === NULL) {
143+
$color = 'lineDeadCode';
144+
$count = ' ';
145+
}
146+
147+
else if ($numTests == 0) {
148+
$color = 'lineNoCov';
149+
$count = sprintf('%8d', 0);
150+
}
151+
152+
else {
153+
$color = 'lineCov';
154+
$count = sprintf('%8d', $numTests);
155+
156+
if ($this->yui) {
157+
$buffer = '';
158+
$testCSS = '';
159+
160+
foreach ($coverageData[$i] as $test) {
161+
switch ($testData[$test]) {
162+
case 0: {
163+
$testCSS = ' class=\"testPassed\"';
164+
}
165+
break;
166+
167+
case 1:
168+
case 2: {
169+
$testCSS = ' class=\"testIncomplete\"';
170+
}
171+
break;
172+
173+
case 3: {
174+
$testCSS = ' class=\"testFailure\"';
175+
}
176+
break;
177+
178+
case 4: {
179+
$testCSS = ' class=\"testError\"';
180+
}
181+
break;
182+
183+
default: {
184+
$testCSS = '';
185+
}
186+
}
187+
188+
$buffer .= sprintf(
189+
'<li%s>%s</li>',
190+
191+
$testCSS,
192+
addslashes(htmlspecialchars($test))
193+
);
194+
}
195+
196+
if ($numTests > 1) {
197+
$header = $numTests . ' tests cover';
198+
} else {
199+
$header = '1 test covers';
200+
}
201+
202+
$header .= ' line ' . $i;
203+
204+
$yuiTemplate->setVar(
205+
array(
206+
'line' => $i,
207+
'header' => $header,
208+
'tests' => $buffer
209+
),
210+
FALSE
211+
);
212+
213+
$this->yuiPanelJS .= $yuiTemplate->render();
214+
}
215+
}
216+
217+
$css = sprintf(
218+
'<span class="%s"> %s : ',
219+
220+
$color,
221+
$count
222+
);
223+
}
224+
225+
$_fillup = array_shift($fillup);
226+
227+
if ($_fillup > 0) {
228+
$line .= str_repeat(' ', $_fillup);
229+
}
230+
231+
$lines .= sprintf(
232+
'<span class="lineNum" id="container%d"><a name="%d"></a>'.
233+
'<a href="#%d" id="line%d">%8d</a> </span>%s%s%s' . "\n",
234+
235+
$i,
236+
$i,
237+
$i,
238+
$i,
239+
$i,
240+
!empty($css) ? $css : ' : ',
241+
!$this->highlight ? htmlspecialchars($line) : $line,
242+
!empty($css) ? '</span>' : ''
243+
);
244+
245+
$i++;
246+
}
247+
248+
$template->setVar(
249+
array(
250+
'lines' => $lines
251+
)
252+
);
253+
116254
$this->setCommonTemplateVariables($template, $title, $node);
117255

118256
$template->renderTo($file);
119257
}
258+
259+
/**
260+
* @param string $file
261+
* @return array
262+
*/
263+
protected function loadFile($file)
264+
{
265+
$buffer = file_get_contents($file);
266+
$lines = explode("\n", str_replace("\t", ' ', $buffer));
267+
$fillup = array();
268+
$result = array();
269+
270+
if (count($lines) == 0) {
271+
return $result;
272+
}
273+
274+
$lines = array_map('rtrim', $lines);
275+
$linesLength = array_map('strlen', $lines);
276+
$width = max($linesLength);
277+
278+
foreach ($linesLength as $line => $length) {
279+
$fillup[$line] = $width - $length;
280+
}
281+
282+
if (!$this->highlight) {
283+
unset($lines[count($lines)-1]);
284+
return $lines;
285+
}
286+
287+
$tokens = token_get_all($buffer);
288+
$stringFlag = FALSE;
289+
$i = 0;
290+
$result[$i] = '';
291+
292+
foreach ($tokens as $j => $token) {
293+
if (is_string($token)) {
294+
if ($token === '"' && $tokens[$j - 1] !== '\\') {
295+
$result[$i] .= sprintf(
296+
'<span class="string">%s</span>',
297+
298+
htmlspecialchars($token)
299+
);
300+
301+
$stringFlag = !$stringFlag;
302+
} else {
303+
$result[$i] .= sprintf(
304+
'<span class="keyword">%s</span>',
305+
306+
htmlspecialchars($token)
307+
);
308+
}
309+
310+
continue;
311+
}
312+
313+
list ($token, $value) = $token;
314+
315+
$value = str_replace(
316+
array("\t", ' '),
317+
array('&nbsp;&nbsp;&nbsp;&nbsp;', '&nbsp;'),
318+
htmlspecialchars($value)
319+
);
320+
321+
if ($value === "\n") {
322+
$result[++$i] = '';
323+
} else {
324+
$lines = explode("\n", $value);
325+
326+
foreach ($lines as $jj => $line) {
327+
$line = trim($line);
328+
329+
if ($line !== '') {
330+
if ($stringFlag) {
331+
$colour = 'string';
332+
} else {
333+
switch ($token) {
334+
case T_INLINE_HTML: {
335+
$colour = 'html';
336+
}
337+
break;
338+
339+
case T_COMMENT:
340+
case T_DOC_COMMENT: {
341+
$colour = 'comment';
342+
}
343+
break;
344+
345+
case T_ABSTRACT:
346+
case T_ARRAY:
347+
case T_AS:
348+
case T_BREAK:
349+
case T_CASE:
350+
case T_CATCH:
351+
case T_CLASS:
352+
case T_CLONE:
353+
case T_CONTINUE:
354+
case T_DEFAULT:
355+
case T_ECHO:
356+
case T_ELSE:
357+
case T_ELSEIF:
358+
case T_EMPTY:
359+
case T_ENDDECLARE:
360+
case T_ENDFOR:
361+
case T_ENDFOREACH:
362+
case T_ENDIF:
363+
case T_ENDSWITCH:
364+
case T_ENDWHILE:
365+
case T_EXIT:
366+
case T_EXTENDS:
367+
case T_FINAL:
368+
case T_FOREACH:
369+
case T_FUNCTION:
370+
case T_GLOBAL:
371+
case T_IF:
372+
case T_INCLUDE:
373+
case T_INCLUDE_ONCE:
374+
case T_INSTANCEOF:
375+
case T_ISSET:
376+
case T_LOGICAL_AND:
377+
case T_LOGICAL_OR:
378+
case T_LOGICAL_XOR:
379+
case T_NAMESPACE:
380+
case T_NEW:
381+
case T_PRIVATE:
382+
case T_PROTECTED:
383+
case T_PUBLIC:
384+
case T_REQUIRE:
385+
case T_REQUIRE_ONCE:
386+
case T_RETURN:
387+
case T_STATIC:
388+
case T_THROW:
389+
case T_TRAIT:
390+
case T_TRY:
391+
case T_UNSET:
392+
case T_USE:
393+
case T_VAR:
394+
case T_WHILE: {
395+
$colour = 'keyword';
396+
}
397+
break;
398+
399+
default: {
400+
$colour = 'default';
401+
}
402+
}
403+
}
404+
405+
$result[$i] .= sprintf(
406+
'<span class="%s">%s</span>',
407+
408+
$colour,
409+
$line
410+
);
411+
}
412+
413+
if (isset($lines[$jj + 1])) {
414+
$result[++$i] = '';
415+
}
416+
}
417+
}
418+
}
419+
420+
unset($result[count($result)-1]);
421+
422+
return array($result, $fillup);
423+
}
120424
}

0 commit comments

Comments
 (0)