1
0
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:
Nikita Popov 2015-06-13 11:27:38 +02:00
parent 9620f79cdc
commit 1a1bd1448d
11 changed files with 1927 additions and 1813 deletions

View File

@ -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:

View File

@ -192,5 +192,9 @@ function magicSplit($regex, $string) {
$piece = trim($piece);
}
return array_filter($pieces);
if ($pieces === ['']) {
return [];
}
return $pieces;
}

View File

@ -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');
}
}

View File

@ -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 */

View File

@ -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

View File

@ -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) {

View File

@ -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'
),

View File

@ -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(
)
)
)
)
)

View File

@ -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

View File

@ -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};