Skip to content

Commit

Permalink
[String_] Add rawValue attribute (#831)
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasVotruba committed May 15, 2022
1 parent 3bf0082 commit 5d83adc
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 25 deletions.
8 changes: 2 additions & 6 deletions grammar/php5.y
Expand Up @@ -689,9 +689,7 @@ array_expr:

scalar_dereference:
array_expr '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; }
| T_CONSTANT_ENCAPSED_STRING '[' dim_offset ']'
{ $attrs = attributes(); $attrs['kind'] = strKind($1);
$$ = Expr\ArrayDimFetch[new Scalar\String_(Scalar\String_::parse($1), $attrs), $3]; }
| T_CONSTANT_ENCAPSED_STRING '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[Scalar\String_::fromString($1, attributes()), $3]; }
| constant '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; }
| scalar_dereference '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; }
/* alternative array syntax missing intentionally */
Expand Down Expand Up @@ -794,9 +792,7 @@ ctor_arguments:
common_scalar:
T_LNUMBER { $$ = $this->parseLNumber($1, attributes(), true); }
| T_DNUMBER { $$ = Scalar\DNumber::fromString($1, attributes()); }
| T_CONSTANT_ENCAPSED_STRING
{ $attrs = attributes(); $attrs['kind'] = strKind($1);
$$ = new Scalar\String_(Scalar\String_::parse($1, false), $attrs); }
| T_CONSTANT_ENCAPSED_STRING { $$ = Scalar\String_::fromString($1, attributes(), false); }
| T_LINE { $$ = Scalar\MagicConst\Line[]; }
| T_FILE { $$ = Scalar\MagicConst\File[]; }
| T_DIR { $$ = Scalar\MagicConst\Dir[]; }
Expand Down
4 changes: 1 addition & 3 deletions grammar/php7.y
Expand Up @@ -1014,9 +1014,7 @@ dereferencable_scalar:
{ $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_LONG;
$$ = new Expr\Array_($3, $attrs); }
| array_short_syntax { $$ = $1; }
| T_CONSTANT_ENCAPSED_STRING
{ $attrs = attributes(); $attrs['kind'] = strKind($1);
$$ = new Scalar\String_(Scalar\String_::parse($1), $attrs); }
| T_CONSTANT_ENCAPSED_STRING { $$ = Scalar\String_::fromString($1, attributes()); }
| '"' encaps_list '"'
{ $attrs = attributes(); $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED;
parseEncapsed($2, '"', true); $$ = new Scalar\Encapsed($2, $attrs); }
Expand Down
8 changes: 0 additions & 8 deletions grammar/phpyLang.php
Expand Up @@ -128,14 +128,6 @@ function($matches) {
. ' else { ' . $args[0] . ' = null; }';
}

if ('strKind' === $name) {
assertArgs(1, $args, $name);

return '(' . $args[0] . '[0] === "\'" || (' . $args[0] . '[1] === "\'" && '
. '(' . $args[0] . '[0] === \'b\' || ' . $args[0] . '[0] === \'B\')) '
. '? Scalar\String_::KIND_SINGLE_QUOTED : Scalar\String_::KIND_DOUBLE_QUOTED)';
}

if ('prependLeadingComments' === $name) {
assertArgs(1, $args, $name);

Expand Down
16 changes: 16 additions & 0 deletions lib/PhpParser/Node/Scalar/String_.php
Expand Up @@ -42,6 +42,22 @@ public function getSubNodeNames() : array {
return ['value'];
}

/**
* @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes
*/
public static function fromString(string $str, array $attributes = [], bool $parseUnicodeEscape = true): self
{
$attributes['kind'] = ($str[0] === "'" || ($str[1] === "'" && ($str[0] === 'b' || $str[0] === 'B')))
? Scalar\String_::KIND_SINGLE_QUOTED
: Scalar\String_::KIND_DOUBLE_QUOTED;

$attributes['rawValue'] = $str;

$string = self::parse($str, $parseUnicodeEscape);

return new self($string, $attributes);
}

/**
* @internal
*
Expand Down
6 changes: 2 additions & 4 deletions lib/PhpParser/Parser/Php5.php
Expand Up @@ -2147,8 +2147,7 @@ protected function initReduceCallbacks() {
$this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
},
392 => function ($stackPos) {
$attrs = $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes; $attrs['kind'] = ($this->semStack[$stackPos-(4-1)][0] === "'" || ($this->semStack[$stackPos-(4-1)][1] === "'" && ($this->semStack[$stackPos-(4-1)][0] === 'b' || $this->semStack[$stackPos-(4-1)][0] === 'B')) ? Scalar\String_::KIND_SINGLE_QUOTED : Scalar\String_::KIND_DOUBLE_QUOTED);
$this->semValue = new Expr\ArrayDimFetch(new Scalar\String_(Scalar\String_::parse($this->semStack[$stackPos-(4-1)]), $attrs), $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
$this->semValue = new Expr\ArrayDimFetch(Scalar\String_::fromString($this->semStack[$stackPos-(4-1)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes), $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
},
393 => function ($stackPos) {
$this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
Expand Down Expand Up @@ -2278,8 +2277,7 @@ protected function initReduceCallbacks() {
$this->semValue = Scalar\DNumber::fromString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
},
435 => function ($stackPos) {
$attrs = $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes; $attrs['kind'] = ($this->semStack[$stackPos-(1-1)][0] === "'" || ($this->semStack[$stackPos-(1-1)][1] === "'" && ($this->semStack[$stackPos-(1-1)][0] === 'b' || $this->semStack[$stackPos-(1-1)][0] === 'B')) ? Scalar\String_::KIND_SINGLE_QUOTED : Scalar\String_::KIND_DOUBLE_QUOTED);
$this->semValue = new Scalar\String_(Scalar\String_::parse($this->semStack[$stackPos-(1-1)], false), $attrs);
$this->semValue = Scalar\String_::fromString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes, false);
},
436 => function ($stackPos) {
$this->semValue = new Scalar\MagicConst\Line($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
Expand Down
3 changes: 1 addition & 2 deletions lib/PhpParser/Parser/Php7.php
Expand Up @@ -2543,8 +2543,7 @@ protected function initReduceCallbacks() {
$this->semValue = $this->semStack[$stackPos-(1-1)];
},
512 => function ($stackPos) {
$attrs = $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes; $attrs['kind'] = ($this->semStack[$stackPos-(1-1)][0] === "'" || ($this->semStack[$stackPos-(1-1)][1] === "'" && ($this->semStack[$stackPos-(1-1)][0] === 'b' || $this->semStack[$stackPos-(1-1)][0] === 'B')) ? Scalar\String_::KIND_SINGLE_QUOTED : Scalar\String_::KIND_DOUBLE_QUOTED);
$this->semValue = new Scalar\String_(Scalar\String_::parse($this->semStack[$stackPos-(1-1)]), $attrs);
$this->semValue = Scalar\String_::fromString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
},
513 => function ($stackPos) {
$attrs = $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED;
Expand Down
20 changes: 20 additions & 0 deletions test/PhpParser/Node/Scalar/StringTest.php
Expand Up @@ -2,8 +2,28 @@

namespace PhpParser\Node\Scalar;

use PhpParser\Node\Stmt\Echo_;
use PhpParser\ParserFactory;

class StringTest extends \PHPUnit\Framework\TestCase
{
public function testRawValue()
{
$parser = (new ParserFactory())->create(ParserFactory::PREFER_PHP7);
$nodes = $parser->parse('<?php echo "sequence \x41";');

$echo = $nodes[0];
$this->assertInstanceOf(Echo_::class, $echo);

/** @var Echo_ $echo */
$string = $echo->exprs[0];
$this->assertInstanceOf(String_::class, $string);

/** @var String_ $string */
$this->assertSame('sequence A', $string->value);
$this->assertSame('"sequence \\x41"', $string->getAttribute('rawValue'));
}

/**
* @dataProvider provideTestParseEscapeSequences
*/
Expand Down
6 changes: 4 additions & 2 deletions test/PhpParser/NodeAbstractTest.php
Expand Up @@ -297,7 +297,8 @@ function functionName(&$a = 0, $b = 1.0) {
"attributes": {
"startLine": 5,
"endLine": 5,
"kind": 1
"kind": 1,
"rawValue": "'Foo'"
}
}
],
Expand Down Expand Up @@ -452,7 +453,8 @@ function functionName(&$a = 0, $b = 1.0) {
"attributes": {
"startLine": 5,
"endLine": 5,
"kind": 1
"kind": 1,
"rawValue": "'Foo'"
},
"value": "Foo"
}
Expand Down

0 comments on commit 5d83adc

Please sign in to comment.