mirror of
https://github.com/danog/PHP-Parser.git
synced 2024-11-30 04:19:30 +01:00
Support mixed group use declarations
This commit is contained in:
parent
9620f79cdc
commit
1a1bd1448d
@ -162,10 +162,10 @@ use_type:
|
||||
|
||||
/* Using namespace_name_parts here to avoid s/r conflict on T_NS_SEPARATOR */
|
||||
group_use_declaration:
|
||||
T_USE namespace_name_parts T_NS_SEPARATOR '{' use_declarations '}'
|
||||
{ $$ = Stmt\GroupUse[Name[$2], $5, Stmt\Use_::TYPE_NORMAL]; }
|
||||
| T_USE use_type namespace_name_parts T_NS_SEPARATOR '{' use_declarations '}'
|
||||
T_USE use_type namespace_name_parts T_NS_SEPARATOR '{' use_declarations '}'
|
||||
{ $$ = Stmt\GroupUse[Name[$3], $6, $2]; }
|
||||
| T_USE namespace_name_parts T_NS_SEPARATOR '{' inline_use_declarations '}'
|
||||
{ $$ = Stmt\GroupUse[Name[$2], $5, Stmt\Use_::TYPE_UNKNOWN]; }
|
||||
;
|
||||
|
||||
use_declarations:
|
||||
@ -174,10 +174,20 @@ use_declarations:
|
||||
;
|
||||
|
||||
use_declaration:
|
||||
namespace_name { $$ = Stmt\UseUse[$1, null]; }
|
||||
| namespace_name T_AS T_STRING { $$ = Stmt\UseUse[$1, $3]; }
|
||||
| T_NS_SEPARATOR namespace_name { $$ = Stmt\UseUse[$2, null]; }
|
||||
| T_NS_SEPARATOR namespace_name T_AS T_STRING { $$ = Stmt\UseUse[$2, $4]; }
|
||||
namespace_name { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; }
|
||||
| namespace_name T_AS T_STRING { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; }
|
||||
| T_NS_SEPARATOR namespace_name { $$ = Stmt\UseUse[$2, null, Stmt\Use_::TYPE_UNKNOWN]; }
|
||||
| T_NS_SEPARATOR namespace_name T_AS T_STRING { $$ = Stmt\UseUse[$2, $4, Stmt\Use_::TYPE_UNKNOWN]; }
|
||||
;
|
||||
|
||||
inline_use_declarations:
|
||||
inline_use_declarations ',' inline_use_declaration { push($1, $3); }
|
||||
| inline_use_declaration { init($1); }
|
||||
;
|
||||
|
||||
inline_use_declaration:
|
||||
use_declaration { $$ = $1; $$->type = Stmt\Use_::TYPE_NORMAL; }
|
||||
| use_type use_declaration { $$ = $2; $$->type = $1; }
|
||||
;
|
||||
|
||||
constant_declaration_list:
|
||||
|
@ -192,5 +192,9 @@ function magicSplit($regex, $string) {
|
||||
$piece = trim($piece);
|
||||
}
|
||||
|
||||
return array_filter($pieces);
|
||||
if ($pieces === ['']) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $pieces;
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ use PhpParser\Error;
|
||||
|
||||
class UseUse extends Node\Stmt
|
||||
{
|
||||
/** @var int One of the Stmt\Use_::TYPE_* constants. Will only differ from TYPE_UNKNOWN for mixed group uses */
|
||||
public $type;
|
||||
/** @var Node\Name Namespace, class, function or constant to alias */
|
||||
public $name;
|
||||
/** @var string Alias */
|
||||
@ -17,9 +19,10 @@ class UseUse extends Node\Stmt
|
||||
*
|
||||
* @param Node\Name $name Namespace/Class to alias
|
||||
* @param null|string $alias Alias
|
||||
* @param int $type Type of the use element (for mixed group use declarations only)
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Node\Name $name, $alias = null, array $attributes = array()) {
|
||||
public function __construct(Node\Name $name, $alias = null, $type = Use_::TYPE_UNKNOWN, array $attributes = array()) {
|
||||
if (null === $alias) {
|
||||
$alias = $name->getLast();
|
||||
}
|
||||
@ -32,11 +35,12 @@ class UseUse extends Node\Stmt
|
||||
}
|
||||
|
||||
parent::__construct($attributes);
|
||||
$this->type = $type;
|
||||
$this->name = $name;
|
||||
$this->alias = $alias;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() {
|
||||
return array('name', 'alias');
|
||||
return array('type', 'name', 'alias');
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,17 @@ use PhpParser\Node\Stmt;
|
||||
|
||||
class Use_ extends Stmt
|
||||
{
|
||||
const TYPE_NORMAL = 1;
|
||||
/**
|
||||
* Unknown type. Both Stmt\Use_ / Stmt\GroupUse and Stmt\UseUse have a $type property, one of them will always be
|
||||
* TYPE_UNKNOWN while the other has one of the three other possible types. For normal use statements the type on the
|
||||
* Stmt\UseUse is unknown. It's only the other way around for mixed group use declarations.
|
||||
*/
|
||||
const TYPE_UNKNOWN = 0;
|
||||
/** Class or namespace import */
|
||||
const TYPE_NORMAL = 1;
|
||||
/** Function import */
|
||||
const TYPE_FUNCTION = 2;
|
||||
/** Constant import */
|
||||
const TYPE_CONSTANT = 3;
|
||||
|
||||
/** @var int Type of alias */
|
||||
|
@ -110,6 +110,11 @@ class NameResolver extends NodeVisitorAbstract
|
||||
}
|
||||
|
||||
protected function addAlias(Stmt\UseUse $use, $type, Name $prefix = null) {
|
||||
// Add prefix for group uses
|
||||
$name = $prefix ? Name::concat($prefix, $use->name) : $use->name;
|
||||
// Type is determined either by individual element or whole use declaration
|
||||
$type |= $use->type;
|
||||
|
||||
// Constant names are case sensitive, everything else case insensitive
|
||||
if ($type === Stmt\Use_::TYPE_CONSTANT) {
|
||||
$aliasName = $use->alias;
|
||||
@ -117,9 +122,6 @@ class NameResolver extends NodeVisitorAbstract
|
||||
$aliasName = strtolower($use->alias);
|
||||
}
|
||||
|
||||
// Add prefix for group uses
|
||||
$name = $prefix ? Name::concat($prefix, $use->name) : $use->name;
|
||||
|
||||
if (isset($this->aliases[$type][$aliasName])) {
|
||||
$typeStringMap = array(
|
||||
Stmt\Use_::TYPE_NORMAL => '',
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -526,13 +526,13 @@ class Standard extends PrettyPrinterAbstract
|
||||
}
|
||||
|
||||
public function pStmt_UseUse(Stmt\UseUse $node) {
|
||||
return $this->p($node->name)
|
||||
return $this->pUseType($node->type) . $this->p($node->name)
|
||||
. ($node->name->getLast() !== $node->alias ? ' as ' . $node->alias : '');
|
||||
}
|
||||
|
||||
private function pUseType($type) {
|
||||
return ($type === Stmt\Use_::TYPE_FUNCTION ? 'function ' : '')
|
||||
. ($type === Stmt\Use_::TYPE_CONSTANT ? 'const ' : '');
|
||||
return $type === Stmt\Use_::TYPE_FUNCTION ? 'function '
|
||||
: ($type === Stmt\Use_::TYPE_CONSTANT ? 'const ' : '');
|
||||
}
|
||||
|
||||
public function pStmt_Interface(Stmt\Interface_ $node) {
|
||||
|
@ -80,15 +80,20 @@ namespace Baz {
|
||||
use A\T\{B\C, D\E};
|
||||
use function X\T\{b\c, d\e};
|
||||
use const Y\T\{B\C, D\E};
|
||||
use Z\T\{G, function f, const K};
|
||||
|
||||
new C;
|
||||
new E;
|
||||
new C\D;
|
||||
new E\F;
|
||||
new G;
|
||||
|
||||
c();
|
||||
e();
|
||||
f();
|
||||
C;
|
||||
E;
|
||||
K;
|
||||
}
|
||||
EOC;
|
||||
$expectedCode = <<<'EOC'
|
||||
@ -145,14 +150,18 @@ namespace Baz {
|
||||
use A\T\{B\C, D\E};
|
||||
use function X\T\{b\c, d\e};
|
||||
use const Y\T\{B\C, D\E};
|
||||
use Z\T\{G, function f, const K};
|
||||
new \A\T\B\C();
|
||||
new \A\T\D\E();
|
||||
new \A\T\B\C\D();
|
||||
new \A\T\D\E\F();
|
||||
new \Z\T\G();
|
||||
\X\T\b\c();
|
||||
\X\T\d\e();
|
||||
\Z\T\f();
|
||||
\Y\T\B\C;
|
||||
\Y\T\D\E;
|
||||
\Z\T\K;
|
||||
}
|
||||
EOC;
|
||||
|
||||
@ -272,7 +281,7 @@ EOC;
|
||||
protected function createNamespacedAndNonNamespaced(array $stmts) {
|
||||
return array(
|
||||
new Stmt\Namespace_(new Name('NS'), $stmts),
|
||||
new Stmt\Namespace_(null, $stmts),
|
||||
new Stmt\Namespace_(null, $stmts),
|
||||
);
|
||||
}
|
||||
|
||||
@ -333,22 +342,22 @@ EOC;
|
||||
return array(
|
||||
array(
|
||||
new Stmt\Use_(array(
|
||||
new Stmt\UseUse(new Name('A\B'), 'B', array('startLine' => 1)),
|
||||
new Stmt\UseUse(new Name('C\D'), 'B', array('startLine' => 2)),
|
||||
new Stmt\UseUse(new Name('A\B'), 'B', 0, array('startLine' => 1)),
|
||||
new Stmt\UseUse(new Name('C\D'), 'B', 0, array('startLine' => 2)),
|
||||
), Stmt\Use_::TYPE_NORMAL),
|
||||
'Cannot use C\D as B because the name is already in use on line 2'
|
||||
),
|
||||
array(
|
||||
new Stmt\Use_(array(
|
||||
new Stmt\UseUse(new Name('a\b'), 'b', array('startLine' => 1)),
|
||||
new Stmt\UseUse(new Name('c\d'), 'B', array('startLine' => 2)),
|
||||
new Stmt\UseUse(new Name('a\b'), 'b', 0, array('startLine' => 1)),
|
||||
new Stmt\UseUse(new Name('c\d'), 'B', 0, array('startLine' => 2)),
|
||||
), Stmt\Use_::TYPE_FUNCTION),
|
||||
'Cannot use function c\d as B because the name is already in use on line 2'
|
||||
),
|
||||
array(
|
||||
new Stmt\Use_(array(
|
||||
new Stmt\UseUse(new Name('A\B'), 'B', array('startLine' => 1)),
|
||||
new Stmt\UseUse(new Name('C\D'), 'B', array('startLine' => 2)),
|
||||
new Stmt\UseUse(new Name('A\B'), 'B', 0, array('startLine' => 1)),
|
||||
new Stmt\UseUse(new Name('C\D'), 'B', 0, array('startLine' => 2)),
|
||||
), Stmt\Use_::TYPE_CONSTANT),
|
||||
'Cannot use const C\D as B because the name is already in use on line 2'
|
||||
),
|
||||
|
@ -21,6 +21,7 @@ array(
|
||||
type: 1
|
||||
uses: array(
|
||||
0: Stmt_UseUse(
|
||||
type: 0
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: A
|
||||
@ -35,6 +36,7 @@ array(
|
||||
type: 1
|
||||
uses: array(
|
||||
0: Stmt_UseUse(
|
||||
type: 0
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: C
|
||||
@ -49,6 +51,7 @@ array(
|
||||
type: 1
|
||||
uses: array(
|
||||
0: Stmt_UseUse(
|
||||
type: 0
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: F
|
||||
@ -58,6 +61,7 @@ array(
|
||||
alias: H
|
||||
)
|
||||
1: Stmt_UseUse(
|
||||
type: 0
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: J
|
||||
@ -71,6 +75,7 @@ array(
|
||||
type: 1
|
||||
uses: array(
|
||||
0: Stmt_UseUse(
|
||||
type: 0
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: A
|
||||
@ -84,6 +89,7 @@ array(
|
||||
type: 1
|
||||
uses: array(
|
||||
0: Stmt_UseUse(
|
||||
type: 0
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: A
|
||||
@ -97,6 +103,7 @@ array(
|
||||
type: 2
|
||||
uses: array(
|
||||
0: Stmt_UseUse(
|
||||
type: 0
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: foo
|
||||
@ -111,6 +118,7 @@ array(
|
||||
type: 2
|
||||
uses: array(
|
||||
0: Stmt_UseUse(
|
||||
type: 0
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: foo
|
||||
@ -125,6 +133,7 @@ array(
|
||||
type: 3
|
||||
uses: array(
|
||||
0: Stmt_UseUse(
|
||||
type: 0
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: foo
|
||||
@ -139,6 +148,7 @@ array(
|
||||
type: 3
|
||||
uses: array(
|
||||
0: Stmt_UseUse(
|
||||
type: 0
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: foo
|
||||
@ -149,4 +159,4 @@ array(
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -6,10 +6,11 @@ use A\{B\C, D};
|
||||
use A\B\{C\D, E};
|
||||
use function A\{b\c, d};
|
||||
use const A\{B\C, D};
|
||||
use A\B\{C\D, function b\c, const D};
|
||||
-----
|
||||
array(
|
||||
0: Stmt_GroupUse(
|
||||
type: 1
|
||||
type: 0
|
||||
prefix: Name(
|
||||
parts: array(
|
||||
0: A
|
||||
@ -17,6 +18,7 @@ array(
|
||||
)
|
||||
uses: array(
|
||||
0: Stmt_UseUse(
|
||||
type: 1
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: B
|
||||
@ -27,7 +29,7 @@ array(
|
||||
)
|
||||
)
|
||||
1: Stmt_GroupUse(
|
||||
type: 1
|
||||
type: 0
|
||||
prefix: Name(
|
||||
parts: array(
|
||||
0: A
|
||||
@ -35,6 +37,7 @@ array(
|
||||
)
|
||||
uses: array(
|
||||
0: Stmt_UseUse(
|
||||
type: 1
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: B
|
||||
@ -44,6 +47,7 @@ array(
|
||||
alias: C
|
||||
)
|
||||
1: Stmt_UseUse(
|
||||
type: 1
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: D
|
||||
@ -54,7 +58,7 @@ array(
|
||||
)
|
||||
)
|
||||
2: Stmt_GroupUse(
|
||||
type: 1
|
||||
type: 0
|
||||
prefix: Name(
|
||||
parts: array(
|
||||
0: A
|
||||
@ -63,6 +67,7 @@ array(
|
||||
)
|
||||
uses: array(
|
||||
0: Stmt_UseUse(
|
||||
type: 1
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: C
|
||||
@ -72,6 +77,7 @@ array(
|
||||
alias: D
|
||||
)
|
||||
1: Stmt_UseUse(
|
||||
type: 1
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: E
|
||||
@ -90,6 +96,7 @@ array(
|
||||
)
|
||||
uses: array(
|
||||
0: Stmt_UseUse(
|
||||
type: 0
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: b
|
||||
@ -99,6 +106,7 @@ array(
|
||||
alias: c
|
||||
)
|
||||
1: Stmt_UseUse(
|
||||
type: 0
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: d
|
||||
@ -117,6 +125,7 @@ array(
|
||||
)
|
||||
uses: array(
|
||||
0: Stmt_UseUse(
|
||||
type: 0
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: B
|
||||
@ -126,6 +135,47 @@ array(
|
||||
alias: C
|
||||
)
|
||||
1: Stmt_UseUse(
|
||||
type: 0
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: D
|
||||
)
|
||||
)
|
||||
alias: D
|
||||
)
|
||||
)
|
||||
)
|
||||
5: Stmt_GroupUse(
|
||||
type: 0
|
||||
prefix: Name(
|
||||
parts: array(
|
||||
0: A
|
||||
1: B
|
||||
)
|
||||
)
|
||||
uses: array(
|
||||
0: Stmt_UseUse(
|
||||
type: 1
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: C
|
||||
1: D
|
||||
)
|
||||
)
|
||||
alias: D
|
||||
)
|
||||
1: Stmt_UseUse(
|
||||
type: 2
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: b
|
||||
1: c
|
||||
)
|
||||
)
|
||||
alias: c
|
||||
)
|
||||
2: Stmt_UseUse(
|
||||
type: 3
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: D
|
||||
|
@ -6,9 +6,11 @@ use A\{B\C, D};
|
||||
use A\B\{C\D, E};
|
||||
use function A\{b\c, d};
|
||||
use const A\{B\C, D};
|
||||
use A\B\{C\D, function b\c, const D};
|
||||
-----
|
||||
use A\{B};
|
||||
use A\{B\C, D};
|
||||
use A\B\{C\D, E};
|
||||
use function A\{b\c, d};
|
||||
use const A\{B\C, D};
|
||||
use A\B\{C\D, function b\c, const D};
|
||||
|
Loading…
Reference in New Issue
Block a user