mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-22 06:42:41 +01:00
Allow AAST to extract string literal values from HEREDOCs
Summary: Ref T13577. I'd like to `arc lint --everything` to find other bad calls to `pht()` and similar functions, but `n_HEREDOC` nodes currently can not generate a response to "getStringLiteralValue()". Support literal extraction from heredocs. Test Plan: Added a test, made it pass. Will lint everything. Maniphest Tasks: T13577 Differential Revision: https://secure.phabricator.com/D21455
This commit is contained in:
parent
1c327208d7
commit
83e63aeb07
2 changed files with 49 additions and 16 deletions
|
@ -14,6 +14,16 @@ foobar(null, null, '%s');
|
||||||
|
|
||||||
pht('x %s y');
|
pht('x %s y');
|
||||||
pht('x %s y'.'z');
|
pht('x %s y'.'z');
|
||||||
|
|
||||||
|
pht(<<<HEREDOC
|
||||||
|
a b c
|
||||||
|
HEREDOC
|
||||||
|
);
|
||||||
|
|
||||||
|
pht(<<<HEREDOC
|
||||||
|
a %s c
|
||||||
|
HEREDOC
|
||||||
|
);
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
error:3:1:XHP54:Formatted String
|
error:3:1:XHP54:Formatted String
|
||||||
error:7:1:XHP54:Formatted String
|
error:7:1:XHP54:Formatted String
|
||||||
|
@ -22,6 +32,7 @@ error:11:1:XHP54:Formatted String
|
||||||
error:13:1:XHP54:Formatted String
|
error:13:1:XHP54:Formatted String
|
||||||
error:15:1:XHP54:Formatted String
|
error:15:1:XHP54:Formatted String
|
||||||
error:16:1:XHP54:Formatted String
|
error:16:1:XHP54:Formatted String
|
||||||
|
error:23:1:XHP54:Formatted String
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,7 +33,9 @@ final class XHPASTNode extends AASTNode {
|
||||||
return $this->getChildByIndex(0)->evalStatic();
|
return $this->getChildByIndex(0)->evalStatic();
|
||||||
break;
|
break;
|
||||||
case 'n_STRING_SCALAR':
|
case 'n_STRING_SCALAR':
|
||||||
return (string)$this->getStringLiteralValue();
|
return phutil_string_cast($this->getStringLiteralValue());
|
||||||
|
case 'n_HEREDOC':
|
||||||
|
return phutil_string_cast($this->getStringLiteralValue());
|
||||||
case 'n_NUMERIC_SCALAR':
|
case 'n_NUMERIC_SCALAR':
|
||||||
$value = $this->getSemanticString();
|
$value = $this->getSemanticString();
|
||||||
if (preg_match('/^0x/i', $value)) {
|
if (preg_match('/^0x/i', $value)) {
|
||||||
|
@ -186,31 +188,51 @@ final class XHPASTNode extends AASTNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStringLiteralValue() {
|
public function getStringLiteralValue() {
|
||||||
if ($this->getTypeName() != 'n_STRING_SCALAR') {
|
$type_name = $this->getTypeName();
|
||||||
return null;
|
|
||||||
|
if ($type_name === 'n_HEREDOC') {
|
||||||
|
$value = $this->getSemanticString();
|
||||||
|
$value = phutil_split_lines($value);
|
||||||
|
$value = array_slice($value, 1, -1);
|
||||||
|
$value = implode('', $value);
|
||||||
|
|
||||||
|
// Strip the final newline from value, this isn't part of the string
|
||||||
|
// literal.
|
||||||
|
$value = preg_replace('/(\r|\n|\r\n)\z/', '', $value);
|
||||||
|
|
||||||
|
return $this->newStringLiteralFromSemanticString($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
$value = $this->getSemanticString();
|
if ($type_name === 'n_STRING_SCALAR') {
|
||||||
$type = $value[0];
|
$value = $this->getSemanticString();
|
||||||
$value = preg_replace('/^b?[\'"]|[\'"]$/i', '', $value);
|
$type = $value[0];
|
||||||
$esc = false;
|
$value = preg_replace('/^b?[\'"]|[\'"]$/i', '', $value);
|
||||||
$len = strlen($value);
|
|
||||||
$out = '';
|
|
||||||
|
|
||||||
if ($type == "'") {
|
if ($type == "'") {
|
||||||
// Single quoted strings treat everything as a literal except "\\" and
|
// Single quoted strings treat everything as a literal except "\\" and
|
||||||
// "\'".
|
// "\'".
|
||||||
return str_replace(
|
return str_replace(
|
||||||
array('\\\\', '\\\''),
|
array('\\\\', '\\\''),
|
||||||
array('\\', "'"),
|
array('\\', "'"),
|
||||||
$value);
|
$value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->newStringLiteralFromSemanticString($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function newStringLiteralFromSemanticString($value) {
|
||||||
// Double quoted strings treat "\X" as a literal if X isn't specifically
|
// Double quoted strings treat "\X" as a literal if X isn't specifically
|
||||||
// a character which needs to be escaped -- e.g., "\q" and "\'" are
|
// a character which needs to be escaped -- e.g., "\q" and "\'" are
|
||||||
// literally "\q" and "\'". stripcslashes() is too aggressive, so find
|
// literally "\q" and "\'". stripcslashes() is too aggressive, so find
|
||||||
// all these under-escaped backslashes and escape them.
|
// all these under-escaped backslashes and escape them.
|
||||||
|
|
||||||
|
$len = strlen($value);
|
||||||
|
$esc = false;
|
||||||
|
$out = '';
|
||||||
|
|
||||||
for ($ii = 0; $ii < $len; $ii++) {
|
for ($ii = 0; $ii < $len; $ii++) {
|
||||||
$c = $value[$ii];
|
$c = $value[$ii];
|
||||||
if ($esc) {
|
if ($esc) {
|
||||||
|
|
Loading…
Reference in a new issue