in src/markup/syntax/highlighter/xhpast/PhutilXHPASTSyntaxHighlighterFuture.php [31:162]
private function applyXHPHighlight($result) {
// We perform two passes here: one using the AST to find symbols we care
// about -- particularly, class names and function names. These are used
// in the crossreference stuff to link into Diffusion. After we've done our
// AST pass, we do a followup pass on the token stream to catch all the
// simple stuff like strings and comments.
$tree = XHPASTTree::newFromDataAndResolvedExecFuture(
$this->source,
$result);
$root = $tree->getRootNode();
$tokens = $root->getTokens();
$interesting_symbols = $this->findInterestingSymbols($root);
if ($this->scrub) {
// If we're scrubbing, we prepended "<?php\n" to the text to force the
// highlighter to treat it as PHP source. Now, we need to remove that.
$ok = false;
if (count($tokens) >= 2) {
if ($tokens[0]->getTypeName() === 'T_OPEN_TAG') {
if ($tokens[1]->getTypeName() === 'T_WHITESPACE') {
$ok = true;
}
}
}
if (!$ok) {
throw new Exception(
pht(
'Expected T_OPEN_TAG, T_WHITESPACE tokens at head of results '.
'for highlighting parse of PHP snippet.'));
}
// Remove the "<?php".
unset($tokens[0]);
$value = $tokens[1]->getValue();
if ((strlen($value) < 1) || ($value[0] != "\n")) {
throw new Exception(
pht(
'Expected "\\n" at beginning of T_WHITESPACE token at head of '.
'tokens for highlighting parse of PHP snippet.'));
}
$value = substr($value, 1);
$tokens[1]->overwriteValue($value);
}
$out = array();
foreach ($tokens as $key => $token) {
$value = $token->getValue();
$class = null;
$multi = false;
$attrs = array();
if (isset($interesting_symbols[$key])) {
$sym = $interesting_symbols[$key];
$class = $sym[0];
$attrs['data-symbol-context'] = idx($sym, 'context');
$attrs['data-symbol-name'] = idx($sym, 'symbol');
} else {
switch ($token->getTypeName()) {
case 'T_WHITESPACE':
break;
case 'T_DOC_COMMENT':
$class = 'dc';
$multi = true;
break;
case 'T_COMMENT':
$class = 'c';
$multi = true;
break;
case 'T_CONSTANT_ENCAPSED_STRING':
case 'T_ENCAPSED_AND_WHITESPACE':
case 'T_INLINE_HTML':
$class = 's';
$multi = true;
break;
case 'T_VARIABLE':
$class = 'nv';
break;
case 'T_OPEN_TAG':
case 'T_OPEN_TAG_WITH_ECHO':
case 'T_CLOSE_TAG':
$class = 'o';
break;
case 'T_LNUMBER':
case 'T_DNUMBER':
$class = 'm';
break;
case 'T_STRING':
static $magic = array(
'true' => true,
'false' => true,
'null' => true,
);
if (isset($magic[strtolower($value)])) {
$class = 'k';
break;
}
$class = 'nx';
break;
default:
$class = 'k';
break;
}
}
if ($class) {
$attrs['class'] = $class;
if ($multi) {
// If the token may have multiple lines in it, make sure each
// <span> crosses no more than one line so the lines can be put
// in a table, etc., later.
$value = phutil_split_lines($value, $retain_endings = true);
} else {
$value = array($value);
}
foreach ($value as $val) {
$out[] = phutil_tag('span', $attrs, $val);
}
} else {
$out[] = $value;
}
}
return phutil_implode_html('', $out);
}