Completed
Push — master ( a514ed...c80037 )
by Théo
44:56 queued 16:09
created

FullyQualifiedNameResolver::resolveStringName()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 1
dl 0
loc 17
ccs 0
cts 0
cp 0
crap 6
rs 9.7
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 521
    private $useStatements;
42
43 521
    public function __construct(NamespaceStmtCollection $namespaceStatements, UseStmtCollection $useStatements)
44 521
    {
45
        $this->namespaceStatements = $namespaceStatements;
46
        $this->useStatements = $useStatements;
47
    }
48
49
    /**
50 457
     * @param Name|Identifier
51
     */
52 457
    public function resolveName(Node $node): ResolvedValue
53 163
    {
54
        if ($node instanceof FullyQualified) {
55
            return new ResolvedValue($node, null, null);
56 414
        }
57 298
58
        if ($node instanceof String_) {
59
            return $this->resolveStringName($node);
60 414
        }
61
62 414
        if ($node instanceof Identifier) {
63
            $node = NamedIdentifier::create($node);
64 414
        }
65 414
66 414
        $namespaceName = $this->namespaceStatements->findNamespaceForNode($node);
67 414
68
        $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
        return new ResolvedValue(
71 414
            $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
            $namespaceName,
73 414
            $useName
74 125
        );
75
    }
76
77 380
    private function resolveNodeName(Name $name, ?Name $namespace, ?Name $use): Name
78 266
    {
79
        if (null !== $use) {
80
            return FullyQualified::concat($use, $name->slice(1), $name->getAttributes());
81 215
        }
82 1
83
        if (null === $namespace) {
84
            return new FullyQualified($name, $name->getAttributes());
85 215
        }
86
87
        if (in_array((string) $name, NameStmtPrefixer::PHP_FUNCTION_KEYWORDS, true)) {
88 215
            return $name;
89 215
        }
90
91
        $parentNode = ParentNodeAppender::getParent($name);
92 23
93
        if (
94
            ($parentNode instanceof ConstFetch || $parentNode instanceof FuncCall)
95 205
            && 1 === count($name->parts)
96
        ) {
97
            // Ambiguous name, cannot determine the FQ name
98
            return $name;
99
        }
100
101
        return FullyQualified::concat($namespace, $name, $name->getAttributes());
102
    }
103
104
    private function resolveStringName(String_ $node): ResolvedValue
105
    {
106
        $name = new FullyQualified(ltrim($node->value, '\\'));
107
108
        $deducedNamespaceName = $name->slice(0, -1);
109
        $namespaceName = null;
110
111
        if (null !== $deducedNamespaceName) {
112
            $namespaceName = $this->namespaceStatements->findNamespaceByName($deducedNamespaceName->toString());
113
        }
114
115
        return new ResolvedValue(
116
            $name,
117
            $namespaceName,
118
            null
119
        );
120
    }
121
}
122