Changeset View
Changeset View
Standalone View
Standalone View
src/applications/differential/parser/DifferentialChangesetParser.php
Show First 20 Lines • Show All 1,450 Lines • ▼ Show 20 Lines | private function adjustRenderedLineForDisplay($line) { | ||||
$is_html = false; | $is_html = false; | ||||
if ($line instanceof PhutilSafeHTML) { | if ($line instanceof PhutilSafeHTML) { | ||||
$is_html = true; | $is_html = true; | ||||
$line = hsprintf('%s', $line); | $line = hsprintf('%s', $line); | ||||
} | } | ||||
$line = phutil_string_cast($line); | $line = phutil_string_cast($line); | ||||
if (strpos($line, "\t") !== false) { | // TODO: This should be flexible, eventually. | ||||
Lint: TODO Comment: This comment has a TODO. | |||||
$line = $this->replaceTabsWithSpaces($line); | $tab_width = 2; | ||||
} | |||||
$line = self::replaceTabsWithSpaces($line, $tab_width); | |||||
$line = str_replace($search, $replace, $line); | $line = str_replace($search, $replace, $line); | ||||
if ($is_html) { | if ($is_html) { | ||||
$line = phutil_safe_html($line); | $line = phutil_safe_html($line); | ||||
} | } | ||||
return $line; | return $line; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | foreach ($control as $idx => $label) { | ||||
'class' => 'suspicious-character', | 'class' => 'suspicious-character', | ||||
'replacement' => "\xE2\x90".chr(0x80 + $idx), | 'replacement' => "\xE2\x90".chr(0x80 + $idx), | ||||
); | ); | ||||
} | } | ||||
return $rules; | return $rules; | ||||
} | } | ||||
private function replaceTabsWithSpaces($line) { | public static function replaceTabsWithSpaces($line, $tab_width) { | ||||
// TODO: This should be flexible, eventually. | static $tags = array(); | ||||
$tab_width = 2; | if (empty($tags[$tab_width])) { | ||||
static $tags; | |||||
if ($tags === null) { | |||||
$tags = array(); | |||||
for ($ii = 1; $ii <= $tab_width; $ii++) { | for ($ii = 1; $ii <= $tab_width; $ii++) { | ||||
$tag = phutil_tag( | $tag = phutil_tag( | ||||
'span', | 'span', | ||||
array( | array( | ||||
'data-copy-text' => "\t", | 'data-copy-text' => "\t", | ||||
), | ), | ||||
str_repeat(' ', $ii)); | str_repeat(' ', $ii)); | ||||
$tag = phutil_string_cast($tag); | $tag = phutil_string_cast($tag); | ||||
$tags[$ii] = $tag; | $tags[$ii] = $tag; | ||||
} | } | ||||
} | } | ||||
// If the line is particularly long, don't try to vectorize it. Use a | // Expand all prefix tabs until we encounter any non-tab character. This | ||||
// faster approximation of the correct tabstop expansion instead. This | // is cheap and often immediately produces the correct result with no | ||||
// usually still arrives at the right result. | // further work (and, particularly, no need to handle any unicode cases). | ||||
if (strlen($line) > 256) { | |||||
return str_replace("\t", $tags[$tab_width], $line); | $len = strlen($line); | ||||
$head = 0; | |||||
for ($head = 0; $head < $len; $head++) { | |||||
$char = $line[$head]; | |||||
if ($char !== "\t") { | |||||
break; | |||||
} | |||||
} | |||||
if ($head) { | |||||
if (empty($tags[$tab_width * $head])) { | |||||
$tags[$tab_width * $head] = str_repeat($tags[$tab_width], $head); | |||||
} | |||||
$prefix = $tags[$tab_width * $head]; | |||||
$line = substr($line, $head); | |||||
} else { | |||||
$prefix = ''; | |||||
} | |||||
// If we have no remaining tabs elsewhere in the string after taking care | |||||
// of all the prefix tabs, we're done. | |||||
if (strpos($line, "\t") === false) { | |||||
return $prefix.$line; | |||||
} | |||||
$len = strlen($line); | |||||
// If the line is particularly long, don't try to do anything special with | |||||
// it. Use a faster approximation of the correct tabstop expansion instead. | |||||
// This usually still arrives at the right result. | |||||
if ($len > 256) { | |||||
return $prefix.str_replace("\t", $tags[$tab_width], $line); | |||||
} | } | ||||
$line = phutil_utf8v_combined($line); | |||||
$in_tag = false; | $in_tag = false; | ||||
$pos = 0; | $pos = 0; | ||||
foreach ($line as $key => $char) { | |||||
// See PHI1210. If the line only has single-byte characters, we don't need | |||||
// to vectorize it and can avoid an expensive UTF8 call. | |||||
$fast_path = preg_match('/^[\x01-\x7F]*\z/', $line); | |||||
if ($fast_path) { | |||||
$replace = array(); | |||||
for ($ii = 0; $ii < $len; $ii++) { | |||||
$char = $line[$ii]; | |||||
if ($char === '>') { | |||||
$in_tag = false; | |||||
continue; | |||||
} | |||||
if ($in_tag) { | |||||
continue; | |||||
} | |||||
if ($char === '<') { | if ($char === '<') { | ||||
$in_tag = true; | $in_tag = true; | ||||
continue; | continue; | ||||
} | } | ||||
if ($char === "\t") { | |||||
$count = $tab_width - ($pos % $tab_width); | |||||
$pos += $count; | |||||
$replace[$ii] = $tags[$count]; | |||||
continue; | |||||
} | |||||
$pos++; | |||||
} | |||||
if ($replace) { | |||||
// Apply replacements starting at the end of the string so they | |||||
// don't mess up the offsets for following replacements. | |||||
$replace = array_reverse($replace, true); | |||||
foreach ($replace as $replace_pos => $replacement) { | |||||
$line = substr_replace($line, $replacement, $replace_pos, 1); | |||||
} | |||||
} | |||||
} else { | |||||
$line = phutil_utf8v_combined($line); | |||||
foreach ($line as $key => $char) { | |||||
if ($char === '>') { | if ($char === '>') { | ||||
$in_tag = false; | $in_tag = false; | ||||
continue; | continue; | ||||
} | } | ||||
if ($in_tag) { | if ($in_tag) { | ||||
continue; | continue; | ||||
} | } | ||||
if ($char === '<') { | |||||
$in_tag = true; | |||||
continue; | |||||
} | |||||
if ($char === "\t") { | if ($char === "\t") { | ||||
$count = $tab_width - ($pos % $tab_width); | $count = $tab_width - ($pos % $tab_width); | ||||
$pos += $count; | $pos += $count; | ||||
$line[$key] = $tags[$count]; | $line[$key] = $tags[$count]; | ||||
continue; | continue; | ||||
} | } | ||||
$pos++; | $pos++; | ||||
} | } | ||||
return implode('', $line); | $line = implode('', $line); | ||||
} | |||||
return $prefix.$line; | |||||
} | } | ||||
} | } |
This comment has a TODO.