Skip to content

Commit f6eb341

Browse files
committed
Fix GroupUse prefix attribute assignment
1 parent b2fe43c commit f6eb341

File tree

7 files changed

+41
-18
lines changed

7 files changed

+41
-18
lines changed

grammar/php5.y

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,13 @@ use_type:
7272
/* Using namespace_name_parts here to avoid s/r conflict on T_NS_SEPARATOR */
7373
group_use_declaration:
7474
T_USE use_type namespace_name_parts T_NS_SEPARATOR '{' unprefixed_use_declarations '}'
75-
{ $$ = Stmt\GroupUse[Name[$3], $6, $2]; }
75+
{ $$ = Stmt\GroupUse[new Name($3, stackAttributes(#3)), $6, $2]; }
7676
| T_USE use_type T_NS_SEPARATOR namespace_name_parts T_NS_SEPARATOR '{' unprefixed_use_declarations '}'
77-
{ $$ = Stmt\GroupUse[Name[$4], $7, $2]; }
77+
{ $$ = Stmt\GroupUse[new Name($4, stackAttributes(#4)), $7, $2]; }
7878
| T_USE namespace_name_parts T_NS_SEPARATOR '{' inline_use_declarations '}'
79-
{ $$ = Stmt\GroupUse[Name[$2], $5, Stmt\Use_::TYPE_UNKNOWN]; }
79+
{ $$ = Stmt\GroupUse[new Name($2, stackAttributes(#2)), $5, Stmt\Use_::TYPE_UNKNOWN]; }
8080
| T_USE T_NS_SEPARATOR namespace_name_parts T_NS_SEPARATOR '{' inline_use_declarations '}'
81-
{ $$ = Stmt\GroupUse[Name[$3], $6, Stmt\Use_::TYPE_UNKNOWN]; }
81+
{ $$ = Stmt\GroupUse[new Name($3, stackAttributes(#3)), $6, Stmt\Use_::TYPE_UNKNOWN]; }
8282
;
8383

8484
unprefixed_use_declarations:

grammar/php7.y

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,13 @@ use_type:
7272
/* Using namespace_name_parts here to avoid s/r conflict on T_NS_SEPARATOR */
7373
group_use_declaration:
7474
T_USE use_type namespace_name_parts T_NS_SEPARATOR '{' unprefixed_use_declarations '}'
75-
{ $$ = Stmt\GroupUse[Name[$3], $6, $2]; }
75+
{ $$ = Stmt\GroupUse[new Name($3, stackAttributes(#3)), $6, $2]; }
7676
| T_USE use_type T_NS_SEPARATOR namespace_name_parts T_NS_SEPARATOR '{' unprefixed_use_declarations '}'
77-
{ $$ = Stmt\GroupUse[Name[$4], $7, $2]; }
77+
{ $$ = Stmt\GroupUse[new Name($4, stackAttributes(#4)), $7, $2]; }
7878
| T_USE namespace_name_parts T_NS_SEPARATOR '{' inline_use_declarations '}'
79-
{ $$ = Stmt\GroupUse[Name[$2], $5, Stmt\Use_::TYPE_UNKNOWN]; }
79+
{ $$ = Stmt\GroupUse[new Name($2, stackAttributes(#2)), $5, Stmt\Use_::TYPE_UNKNOWN]; }
8080
| T_USE T_NS_SEPARATOR namespace_name_parts T_NS_SEPARATOR '{' inline_use_declarations '}'
81-
{ $$ = Stmt\GroupUse[Name[$3], $6, Stmt\Use_::TYPE_UNKNOWN]; }
81+
{ $$ = Stmt\GroupUse[new Name($3, stackAttributes(#3)), $6, Stmt\Use_::TYPE_UNKNOWN]; }
8282
;
8383

8484
unprefixed_use_declarations:

grammar/rebuildParsers.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,12 @@ function($matches) {
124124
return '$this->startAttributeStack[#1] + $this->endAttributes';
125125
}
126126

127+
if ('stackAttributes' == $name) {
128+
assertArgs(1, $args, $name);
129+
return '$this->startAttributeStack[' . $args[0] . ']'
130+
. ' + $this->endAttributeStack[' . $args[0] . ']';
131+
}
132+
127133
if ('init' == $name) {
128134
return '$$ = array(' . implode(', ', $args) . ')';
129135
}

lib/PhpParser/Parser/Php5.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1303,19 +1303,19 @@ protected function reduceRule97() {
13031303
}
13041304

13051305
protected function reduceRule98() {
1306-
$this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(7-3)], $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes), $this->semStack[$this->stackPos-(7-6)], $this->semStack[$this->stackPos-(7-2)], $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes);
1306+
$this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(7-3)], $this->startAttributeStack[$this->stackPos-(7-3)] + $this->endAttributeStack[$this->stackPos-(7-3)]), $this->semStack[$this->stackPos-(7-6)], $this->semStack[$this->stackPos-(7-2)], $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes);
13071307
}
13081308

13091309
protected function reduceRule99() {
1310-
$this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(8-4)], $this->startAttributeStack[$this->stackPos-(8-1)] + $this->endAttributes), $this->semStack[$this->stackPos-(8-7)], $this->semStack[$this->stackPos-(8-2)], $this->startAttributeStack[$this->stackPos-(8-1)] + $this->endAttributes);
1310+
$this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(8-4)], $this->startAttributeStack[$this->stackPos-(8-4)] + $this->endAttributeStack[$this->stackPos-(8-4)]), $this->semStack[$this->stackPos-(8-7)], $this->semStack[$this->stackPos-(8-2)], $this->startAttributeStack[$this->stackPos-(8-1)] + $this->endAttributes);
13111311
}
13121312

13131313
protected function reduceRule100() {
1314-
$this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(6-2)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes), $this->semStack[$this->stackPos-(6-5)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes);
1314+
$this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(6-2)], $this->startAttributeStack[$this->stackPos-(6-2)] + $this->endAttributeStack[$this->stackPos-(6-2)]), $this->semStack[$this->stackPos-(6-5)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes);
13151315
}
13161316

13171317
protected function reduceRule101() {
1318-
$this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(7-3)], $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes), $this->semStack[$this->stackPos-(7-6)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes);
1318+
$this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(7-3)], $this->startAttributeStack[$this->stackPos-(7-3)] + $this->endAttributeStack[$this->stackPos-(7-3)]), $this->semStack[$this->stackPos-(7-6)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes);
13191319
}
13201320

13211321
protected function reduceRule102() {

lib/PhpParser/Parser/Php7.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,19 +1188,19 @@ protected function reduceRule97() {
11881188
}
11891189

11901190
protected function reduceRule98() {
1191-
$this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(7-3)], $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes), $this->semStack[$this->stackPos-(7-6)], $this->semStack[$this->stackPos-(7-2)], $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes);
1191+
$this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(7-3)], $this->startAttributeStack[$this->stackPos-(7-3)] + $this->endAttributeStack[$this->stackPos-(7-3)]), $this->semStack[$this->stackPos-(7-6)], $this->semStack[$this->stackPos-(7-2)], $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes);
11921192
}
11931193

11941194
protected function reduceRule99() {
1195-
$this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(8-4)], $this->startAttributeStack[$this->stackPos-(8-1)] + $this->endAttributes), $this->semStack[$this->stackPos-(8-7)], $this->semStack[$this->stackPos-(8-2)], $this->startAttributeStack[$this->stackPos-(8-1)] + $this->endAttributes);
1195+
$this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(8-4)], $this->startAttributeStack[$this->stackPos-(8-4)] + $this->endAttributeStack[$this->stackPos-(8-4)]), $this->semStack[$this->stackPos-(8-7)], $this->semStack[$this->stackPos-(8-2)], $this->startAttributeStack[$this->stackPos-(8-1)] + $this->endAttributes);
11961196
}
11971197

11981198
protected function reduceRule100() {
1199-
$this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(6-2)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes), $this->semStack[$this->stackPos-(6-5)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes);
1199+
$this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(6-2)], $this->startAttributeStack[$this->stackPos-(6-2)] + $this->endAttributeStack[$this->stackPos-(6-2)]), $this->semStack[$this->stackPos-(6-5)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes);
12001200
}
12011201

12021202
protected function reduceRule101() {
1203-
$this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(7-3)], $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes), $this->semStack[$this->stackPos-(7-6)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes);
1203+
$this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(7-3)], $this->startAttributeStack[$this->stackPos-(7-3)] + $this->endAttributeStack[$this->stackPos-(7-3)]), $this->semStack[$this->stackPos-(7-6)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes);
12041204
}
12051205

12061206
protected function reduceRule102() {

lib/PhpParser/ParserAbstract.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ abstract class ParserAbstract implements Parser
8686
protected $semStack;
8787
/** @var array[] Start attribute stack */
8888
protected $startAttributeStack;
89+
/** @var array[] End attribute stack */
90+
protected $endAttributeStack;
8991
/** @var array End attributes of last *shifted* token */
9092
protected $endAttributes;
9193
/** @var array Start attributes of last *read* token */
@@ -149,9 +151,9 @@ public function parse($code) {
149151
$endAttributes = '*POISON';
150152
$this->endAttributes = $endAttributes;
151153

152-
// In order to figure out the attributes for the starting token, we have to keep
153-
// them in a stack
154+
// Keep stack of start and end attributes
154155
$this->startAttributeStack = array();
156+
$this->endAttributeStack = array($endAttributes);
155157

156158
// Start off in the initial state and keep a stack of previous states
157159
$state = 0;
@@ -193,6 +195,7 @@ public function parse($code) {
193195
// This is necessary to assign some meaningful attributes to /* empty */ productions. They'll get
194196
// the attributes of the next token, even though they don't contain it themselves.
195197
$this->startAttributeStack[$this->stackPos+1] = $startAttributes;
198+
$this->endAttributeStack[$this->stackPos+1] = $endAttributes;
196199
$this->lookaheadStartAttributes = $startAttributes;
197200

198201
//$this->traceRead($symbol);
@@ -219,6 +222,7 @@ public function parse($code) {
219222
$stateStack[$this->stackPos] = $state = $action;
220223
$this->semStack[$this->stackPos] = $tokenValue;
221224
$this->startAttributeStack[$this->stackPos] = $startAttributes;
225+
$this->endAttributeStack[$this->stackPos] = $endAttributes;
222226
$this->endAttributes = $endAttributes;
223227
$symbol = self::SYMBOL_NONE;
224228

@@ -266,6 +270,7 @@ public function parse($code) {
266270
}
267271

268272
/* Goto - shift nonterminal */
273+
$lastEndAttributes = $this->endAttributeStack[$this->stackPos];
269274
$this->stackPos -= $this->ruleToLength[$rule];
270275
$nonTerminal = $this->ruleToNonTerminal[$rule];
271276
$idx = $this->gotoBase[$nonTerminal] + $stateStack[$this->stackPos];
@@ -278,6 +283,7 @@ public function parse($code) {
278283
++$this->stackPos;
279284
$stateStack[$this->stackPos] = $state;
280285
$this->semStack[$this->stackPos] = $this->semValue;
286+
$this->endAttributeStack[$this->stackPos] = $lastEndAttributes;
281287
} else {
282288
/* error */
283289
switch ($this->errorState) {

test/PhpParser/ParserTest.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,17 @@ public function provideTestExtraAttributes() {
171171
array("?>\nFoo", ['hasLeadingNewline' => true]),
172172
);
173173
}
174+
175+
public function testGroupUsePrefixFileOffsets() {
176+
$parser = $this->getParser(new Lexer(
177+
['usedAttributes' => ['startFilePos', 'endFilePos']]
178+
));
179+
$stmts = $parser->parse('<?php use Foo\Bar\{Baz};');
180+
/** @var Node\Stmt\GroupUse $groupUse */
181+
$groupUse = $stmts[0];
182+
$this->assertSame(10, $groupUse->prefix->getAttribute('startFilePos'));
183+
$this->assertSame(16, $groupUse->prefix->getAttribute('endFilePos'));
184+
}
174185
}
175186

176187
class InvalidTokenLexer extends Lexer {

0 commit comments

Comments
 (0)