Completed
Push — master ( 0647fd...b9e92e )
by Théo
27:07 queued 08:01
created

FullyQualifiedNameResolver::resolveName()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
nc 4
nop 1
dl 0
loc 24
ccs 13
cts 13
cp 1
crap 4
rs 9.536
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the humbug/php-scoper package.
7
 *
8
 * Copyright (c) 2017 Théo FIDRY <[email protected]>,
9
 *                    Pádraic Brady <[email protected]>
10
 *
11
 * For the full copyright and license information, please view the LICENSE
12
 * file that was distributed with this source code.
13
 */
14
15
namespace Humbug\PhpScoper\PhpParser\NodeVisitor\Resolver;
16
17
use Humbug\PhpScoper\PhpParser\Node\NamedIdentifier;
18
use Humbug\PhpScoper\PhpParser\NodeVisitor\Collection\NamespaceStmtCollection;
19
use Humbug\PhpScoper\PhpParser\NodeVisitor\Collection\UseStmtCollection;
20
use Humbug\PhpScoper\PhpParser\NodeVisitor\NameStmtPrefixer;
21
use Humbug\PhpScoper\PhpParser\NodeVisitor\ParentNodeAppender;
22
use PhpParser\Node;
23
use PhpParser\Node\Expr\ConstFetch;
24
use PhpParser\Node\Expr\FuncCall;
25
use PhpParser\Node\Identifier;
26
use PhpParser\Node\Name;
27
use PhpParser\Node\Name\FullyQualified;
28
use PhpParser\Node\Scalar\String_;
29
use function in_array;
30
use function ltrim;
31
32
/**
33
 * Attempts to resolve the node name into a fully qualified node. Returns a valid (non fully-qualified) name node on
34
 * failure.
35
 *
36
 * @private
37
 */
38
final class FullyQualifiedNameResolver
39
{
40
    private $namespaceStatements;
41
    private $useStatements;
42
43 548
    public function __construct(NamespaceStmtCollection $namespaceStatements, UseStmtCollection $useStatements)
44
    {
45 548
        $this->namespaceStatements = $namespaceStatements;
46 548
        $this->useStatements = $useStatements;
47
    }
48
49
    /**
50
     * @param Name|String_|Identifier $node
51
     */
52 472
    public function resolveName(Node $node): ResolvedValue
53
    {
54 472
        if ($node instanceof FullyQualified) {
55 165
            return new ResolvedValue($node, null, null);
56
        }
57
58 427
        if ($node instanceof String_) {
59 8
            return $this->resolveStringName($node);
60
        }
61
62 427
        if ($node instanceof Identifier) {
63 299
            $node = NamedIdentifier::create($node);
64
        }
65
66 427
        $namespaceName = $this->namespaceStatements->findNamespaceForNode($node);
67
68 427
        $useName = $this->useStatements->findStatementForNode($namespaceName, $node);
1 ignored issue
show
Bug introduced by
It seems like $node defined by parameter $node on line 52 can also be of type object<PhpParser\Node>; however, Humbug\PhpScoper\PhpPars...:findStatementForNode() does only seem to accept object<PhpParser\Node\Name>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
69
70 427
        return new ResolvedValue(
71 427
            $this->resolveNodeName($node, $namespaceName, $useName),
1 ignored issue
show
Bug introduced by
It seems like $node defined by parameter $node on line 52 can also be of type object<PhpParser\Node>; however, Humbug\PhpScoper\PhpPars...lver::resolveNodeName() does only seem to accept object<PhpParser\Node\Name>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
72 427
            $namespaceName,
73 427
            $useName
74
        );
75
    }
76
77 427
    private function resolveNodeName(Name $name, ?Name $namespace, ?Name $use): Name
78
    {
79 427
        if (null !== $use) {
80 127
            return FullyQualified::concat($use, $name->slice(1), $name->getAttributes());
81
        }
82
83 391
        if (null === $namespace) {
84 274
            return new FullyQualified($name, $name->getAttributes());
85
        }
86
87 218
        if (in_array((string) $name, NameStmtPrefixer::PHP_FUNCTION_KEYWORDS, true)) {
88 1
            return $name;
89
        }
90
91 218
        $parentNode = ParentNodeAppender::getParent($name);
92
93
        if (
94 218
            ($parentNode instanceof ConstFetch || $parentNode instanceof FuncCall)
95 218
            && 1 === count($name->parts)
96
        ) {
97
            // Ambiguous name, cannot determine the FQ name
98 25
            return $name;
99
        }
100
101 206
        return FullyQualified::concat($namespace, $name, $name->getAttributes());
102
    }
103
104 8
    private function resolveStringName(String_ $node): ResolvedValue
105
    {
106 8
        $name = new FullyQualified(ltrim($node->value, '\\'));
107
108 8
        $deducedNamespaceName = $name->slice(0, -1);
109 8
        $namespaceName = null;
110
111 8
        if (null !== $deducedNamespaceName) {
112 4
            $namespaceName = $this->namespaceStatements->findNamespaceByName($deducedNamespaceName->toString());
113
        }
114
115 8
        return new ResolvedValue(
116 8
            $name,
117 8
            $namespaceName,
118 8
            null
119
        );
120
    }
121
}
122