Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F1432322
QualifiedName.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
QualifiedName.php
View Options
<?php
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
namespace
Microsoft\PhpParser\Node
;
use
Microsoft\PhpParser\NamespacedNameInterface
;
use
Microsoft\PhpParser\NamespacedNameTrait
;
use
Microsoft\PhpParser\Node
;
use
Microsoft\PhpParser\Node\Expression\AnonymousFunctionCreationExpression
;
use
Microsoft\PhpParser\Node\Expression\ArrowFunctionCreationExpression
;
use
Microsoft\PhpParser\Node\Expression\CallExpression
;
use
Microsoft\PhpParser\Node\Expression\ObjectCreationExpression
;
use
Microsoft\PhpParser\ResolvedName
;
use
Microsoft\PhpParser\Token
;
use
Microsoft\PhpParser\TokenKind
;
class
QualifiedName
extends
Node
implements
NamespacedNameInterface
{
use
NamespacedNameTrait
;
/** @var Token */
public
$globalSpecifier
;
// \_opt
/** @var RelativeSpecifier */
public
$relativeSpecifier
;
// namespace\
/** @var array */
public
$nameParts
;
const
CHILD_NAMES
=
[
'globalSpecifier'
,
'relativeSpecifier'
,
'nameParts'
];
/**
* Checks whether a QualifiedName is prefixed with a backslash global specifier.
* @return bool
*/
public
function
isFullyQualifiedName
()
:
bool
{
return
isset
(
$this
->
globalSpecifier
);
}
/**
* Checks whether a QualifiedName begins with a "namespace" keyword
* @return bool
*/
public
function
isRelativeName
()
:
bool
{
return
isset
(
$this
->
relativeSpecifier
);
}
/**
* Checks whether a Name includes at least one namespace separator (and is neither fully-qualified nor relative)
* @return bool
*/
public
function
isQualifiedName
()
:
bool
{
return
!
$this
->
isFullyQualifiedName
()
&&
!
$this
->
isRelativeName
()
&&
\count
(
$this
->
nameParts
)
>
1
;
// at least one namespace separator
}
/**
* Checks whether a name is does not include a namespace separator.
* @return bool
*/
public
function
isUnqualifiedName
()
:
bool
{
return
!(
$this
->
isFullyQualifiedName
()
||
$this
->
isRelativeName
()
||
$this
->
isQualifiedName
());
}
/**
* Gets resolved name based on name resolution rules defined in:
* http://php.net/manual/en/language.namespaces.rules.php
*
* Returns null if one of the following conditions is met:
* - name resolution is not valid for this element (e.g. part of the name in a namespace definition)
* - name cannot be resolved (unqualified namespaced function/constant names that are not explicitly imported.)
*
* @return null|string|ResolvedName
* @throws \Exception
*/
public
function
getResolvedName
(
$namespaceDefinition
=
null
)
{
// Name resolution not applicable to constructs that define symbol names or aliases.
if
((
$this
->
parent
instanceof
Node\Statement\NamespaceDefinition
&&
$this
->
parent
->
name
->
getStartPosition
()
===
$this
->
getStartPosition
())
||
$this
->
parent
instanceof
Node\Statement\NamespaceUseDeclaration
||
$this
->
parent
instanceof
Node\NamespaceUseClause
||
$this
->
parent
instanceof
Node\NamespaceUseGroupClause
||
$this
->
parent
->
parent
instanceof
Node\TraitUseClause
||
$this
->
parent
instanceof
Node\TraitSelectOrAliasClause
||
(
$this
->
parent
instanceof
TraitSelectOrAliasClause
&&
(
$this
->
parent
->
asOrInsteadOfKeyword
==
null
||
$this
->
parent
->
asOrInsteadOfKeyword
->
kind
===
TokenKind
::
AsKeyword
))
)
{
return
null
;
}
if
(
in_array
(
$lowerText
=
strtolower
(
$this
->
getText
()),
[
"self"
,
"static"
,
"parent"
]))
{
return
$lowerText
;
}
// FULLY QUALIFIED NAMES
// - resolve to the name without leading namespace separator.
if
(
$this
->
isFullyQualifiedName
())
{
return
ResolvedName
::
buildName
(
$this
->
nameParts
,
$this
->
getFileContents
());
}
// RELATIVE NAMES
// - resolve to the name with namespace replaced by the current namespace.
// - if current namespace is global, strip leading namespace\ prefix.
if
(
$this
->
isRelativeName
())
{
return
$this
->
getNamespacedName
();
}
[
$namespaceImportTable
,
$functionImportTable
,
$constImportTable
]
=
$this
->
getImportTablesForCurrentScope
();
// QUALIFIED NAMES
// - first segment of the name is translated according to the current class/namespace import table.
// - If no import rule applies, the current namespace is prepended to the name.
if
(
$this
->
isQualifiedName
())
{
return
$this
->
tryResolveFromImportTable
(
$namespaceImportTable
)
??
$this
->
getNamespacedName
();
}
// UNQUALIFIED NAMES
// - translated according to the current import table for the respective symbol type.
// (class-like => namespace import table, constant => const import table, function => function import table)
// - if no import rule applies:
// - all symbol types: if current namespace is global, resolve to global namespace.
// - class-like symbols: resolve from current namespace.
// - function or const: resolved at runtime (from current namespace, with fallback to global namespace).
if
(
$this
->
isConstantName
())
{
$resolvedName
=
$this
->
tryResolveFromImportTable
(
$constImportTable
,
/* case-sensitive */
true
);
$namespaceDefinition
=
$this
->
getNamespaceDefinition
();
if
(
$namespaceDefinition
!==
null
&&
$namespaceDefinition
->
name
===
null
)
{
$resolvedName
=
$resolvedName
??
ResolvedName
::
buildName
(
$this
->
nameParts
,
$this
->
getFileContents
());
}
return
$resolvedName
;
}
elseif
(
$this
->
parent
instanceof
CallExpression
)
{
$resolvedName
=
$this
->
tryResolveFromImportTable
(
$functionImportTable
);
if
((
$namespaceDefinition
=
$this
->
getNamespaceDefinition
())
===
null
||
$namespaceDefinition
->
name
===
null
)
{
$resolvedName
=
$resolvedName
??
ResolvedName
::
buildName
(
$this
->
nameParts
,
$this
->
getFileContents
());
}
return
$resolvedName
;
}
return
$this
->
tryResolveFromImportTable
(
$namespaceImportTable
)
??
$this
->
getNamespacedName
();
}
public
function
getLastNamePart
()
{
$parts
=
$this
->
nameParts
;
for
(
$i
=
\count
(
$parts
)
-
1
;
$i
>=
0
;
$i
--)
{
// TODO - also handle reserved word tokens
if
(
$parts
[
$i
]->
kind
===
TokenKind
::
Name
)
{
return
$parts
[
$i
];
}
}
return
null
;
}
/**
* @param ResolvedName[] $importTable
* @param bool $isCaseSensitive
* @return string|null
*/
private
function
tryResolveFromImportTable
(
$importTable
,
bool
$isCaseSensitive
=
false
)
{
$content
=
$this
->
getFileContents
();
$index
=
$this
->
nameParts
[
0
]->
getText
(
$content
);
// if (!$isCaseSensitive) {
// $index = strtolower($index);
// }
if
(
isset
(
$importTable
[
$index
]))
{
$resolvedName
=
$importTable
[
$index
];
$resolvedName
->
addNameParts
(
\array_slice
(
$this
->
nameParts
,
1
),
$content
);
return
$resolvedName
;
}
return
null
;
}
private
function
isConstantName
()
:
bool
{
return
(
$this
->
parent
instanceof
Node\Statement\ExpressionStatement
||
$this
->
parent
instanceof
Expression
)
&&
!(
$this
->
parent
instanceof
Node\Expression\MemberAccessExpression
||
$this
->
parent
instanceof
CallExpression
||
$this
->
parent
instanceof
ObjectCreationExpression
||
$this
->
parent
instanceof
Node\Expression\ScopedPropertyAccessExpression
||
$this
->
parent
instanceof
AnonymousFunctionCreationExpression
||
$this
->
parent
instanceof
ArrowFunctionCreationExpression
||
(
$this
->
parent
instanceof
Node\Expression\BinaryExpression
&&
$this
->
parent
->
operator
->
kind
===
TokenKind
::
InstanceOfKeyword
)
);
}
public
function
getNameParts
()
:
array
{
return
$this
->
nameParts
;
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Sat, May 16, 21:38 (1 d, 2 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
90/19/a847926dedfa50ae6f76b2e09d64
Default Alt Text
QualifiedName.php (8 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment