PHPBuilder::buildAstFieldDeclaration()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
/**
3
 * This file is part of PDepend.
4
 *
5
 * PHP Version 5
6
 *
7
 * Copyright (c) 2008-2017 Manuel Pichler <[email protected]>.
8
 * All rights reserved.
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 *
14
 *   * Redistributions of source code must retain the above copyright
15
 *     notice, this list of conditions and the following disclaimer.
16
 *
17
 *   * Redistributions in binary form must reproduce the above copyright
18
 *     notice, this list of conditions and the following disclaimer in
19
 *     the documentation and/or other materials provided with the
20
 *     distribution.
21
 *
22
 *   * Neither the name of Manuel Pichler nor the names of his
23
 *     contributors may be used to endorse or promote products derived
24
 *     from this software without specific prior written permission.
25
 *
26
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
29
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
30
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
32
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
34
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
36
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37
 * POSSIBILITY OF SUCH DAMAGE.
38
 *
39
 * @copyright 2008-2017 Manuel Pichler. All rights reserved.
40
 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
41
 */
42
43
namespace PDepend\Source\Language\PHP;
44
45
use BadMethodCallException;
46
use PDepend\Source\AST\AbstractASTClassOrInterface;
47
use PDepend\Source\AST\AbstractASTNode;
48
use PDepend\Source\AST\AbstractASTType;
49
use PDepend\Source\AST\ASTAllocationExpression;
50
use PDepend\Source\AST\ASTAnonymousClass;
51
use PDepend\Source\AST\ASTArguments;
52
use PDepend\Source\AST\ASTArray;
53
use PDepend\Source\AST\ASTArrayElement;
54
use PDepend\Source\AST\ASTArrayIndexExpression;
55
use PDepend\Source\AST\ASTArtifactList;
56
use PDepend\Source\AST\ASTAssignmentExpression;
57
use PDepend\Source\AST\ASTBooleanAndExpression;
58
use PDepend\Source\AST\ASTBooleanOrExpression;
59
use PDepend\Source\AST\ASTBreakStatement;
60
use PDepend\Source\AST\ASTCastExpression;
61
use PDepend\Source\AST\ASTCatchStatement;
62
use PDepend\Source\AST\ASTClass;
63
use PDepend\Source\AST\ASTClassFqnPostfix;
64
use PDepend\Source\AST\ASTClassOrInterfaceReference;
65
use PDepend\Source\AST\ASTClassReference;
66
use PDepend\Source\AST\ASTCloneExpression;
67
use PDepend\Source\AST\ASTClosure;
68
use PDepend\Source\AST\ASTComment;
69
use PDepend\Source\AST\ASTCompilationUnit;
70
use PDepend\Source\AST\ASTCompoundExpression;
71
use PDepend\Source\AST\ASTCompoundVariable;
72
use PDepend\Source\AST\ASTConditionalExpression;
73
use PDepend\Source\AST\ASTConstant;
74
use PDepend\Source\AST\ASTConstantDeclarator;
75
use PDepend\Source\AST\ASTConstantDefinition;
76
use PDepend\Source\AST\ASTConstantPostfix;
77
use PDepend\Source\AST\ASTContinueStatement;
78
use PDepend\Source\AST\ASTDeclareStatement;
79
use PDepend\Source\AST\ASTDoWhileStatement;
80
use PDepend\Source\AST\ASTEchoStatement;
81
use PDepend\Source\AST\ASTElseIfStatement;
82
use PDepend\Source\AST\ASTEnum;
83
use PDepend\Source\AST\ASTEnumCase;
84
use PDepend\Source\AST\ASTEvalExpression;
85
use PDepend\Source\AST\ASTExitExpression;
86
use PDepend\Source\AST\ASTExpression;
87
use PDepend\Source\AST\ASTFieldDeclaration;
88
use PDepend\Source\AST\ASTFinallyStatement;
89
use PDepend\Source\AST\ASTForeachStatement;
90
use PDepend\Source\AST\ASTForInit;
91
use PDepend\Source\AST\ASTFormalParameter;
92
use PDepend\Source\AST\ASTFormalParameters;
93
use PDepend\Source\AST\ASTForStatement;
94
use PDepend\Source\AST\ASTForUpdate;
95
use PDepend\Source\AST\ASTFunction;
96
use PDepend\Source\AST\ASTFunctionPostfix;
97
use PDepend\Source\AST\ASTGlobalStatement;
98
use PDepend\Source\AST\ASTGotoStatement;
99
use PDepend\Source\AST\ASTHeredoc;
100
use PDepend\Source\AST\ASTIdentifier;
101
use PDepend\Source\AST\ASTIfStatement;
102
use PDepend\Source\AST\ASTIncludeExpression;
103
use PDepend\Source\AST\ASTInstanceOfExpression;
104
use PDepend\Source\AST\ASTInterface;
105
use PDepend\Source\AST\ASTIntersectionType;
106
use PDepend\Source\AST\ASTIssetExpression;
107
use PDepend\Source\AST\ASTLabelStatement;
108
use PDepend\Source\AST\ASTListExpression;
109
use PDepend\Source\AST\ASTLiteral;
110
use PDepend\Source\AST\ASTLogicalAndExpression;
111
use PDepend\Source\AST\ASTLogicalOrExpression;
112
use PDepend\Source\AST\ASTLogicalXorExpression;
113
use PDepend\Source\AST\ASTMatchArgument;
114
use PDepend\Source\AST\ASTMatchBlock;
115
use PDepend\Source\AST\ASTMatchEntry;
116
use PDepend\Source\AST\ASTMemberPrimaryPrefix;
117
use PDepend\Source\AST\ASTMethod;
118
use PDepend\Source\AST\ASTMethodPostfix;
119
use PDepend\Source\AST\ASTNamedArgument;
120
use PDepend\Source\AST\ASTNamespace;
121
use PDepend\Source\AST\ASTNode;
122
use PDepend\Source\AST\ASTParentReference;
123
use PDepend\Source\AST\ASTPostfixExpression;
124
use PDepend\Source\AST\ASTPreDecrementExpression;
125
use PDepend\Source\AST\ASTPreIncrementExpression;
126
use PDepend\Source\AST\ASTPrintExpression;
127
use PDepend\Source\AST\ASTPropertyPostfix;
128
use PDepend\Source\AST\ASTRequireExpression;
129
use PDepend\Source\AST\ASTReturnStatement;
130
use PDepend\Source\AST\ASTScalarType;
131
use PDepend\Source\AST\ASTScope;
132
use PDepend\Source\AST\ASTScopeStatement;
133
use PDepend\Source\AST\ASTSelfReference;
134
use PDepend\Source\AST\ASTShiftLeftExpression;
135
use PDepend\Source\AST\ASTShiftRightExpression;
136
use PDepend\Source\AST\ASTStatement;
137
use PDepend\Source\AST\ASTStaticReference;
138
use PDepend\Source\AST\ASTStaticVariableDeclaration;
139
use PDepend\Source\AST\ASTString;
140
use PDepend\Source\AST\ASTStringIndexExpression;
141
use PDepend\Source\AST\ASTSwitchLabel;
142
use PDepend\Source\AST\ASTSwitchStatement;
143
use PDepend\Source\AST\ASTThrowStatement;
144
use PDepend\Source\AST\ASTTrait;
145
use PDepend\Source\AST\ASTTraitAdaptation;
146
use PDepend\Source\AST\ASTTraitAdaptationAlias;
147
use PDepend\Source\AST\ASTTraitAdaptationPrecedence;
148
use PDepend\Source\AST\ASTTraitReference;
149
use PDepend\Source\AST\ASTTraitUseStatement;
150
use PDepend\Source\AST\ASTTryStatement;
151
use PDepend\Source\AST\ASTTypeArray;
152
use PDepend\Source\AST\ASTTypeCallable;
153
use PDepend\Source\AST\ASTTypeIterable;
154
use PDepend\Source\AST\ASTUnaryExpression;
155
use PDepend\Source\AST\ASTUnionType;
156
use PDepend\Source\AST\ASTUnsetStatement;
157
use PDepend\Source\AST\ASTVariable;
158
use PDepend\Source\AST\ASTVariableDeclarator;
159
use PDepend\Source\AST\ASTVariableVariable;
160
use PDepend\Source\AST\ASTWhileStatement;
161
use PDepend\Source\AST\ASTYieldStatement;
162
use PDepend\Source\Builder\Builder;
163
use PDepend\Source\Builder\BuilderContext;
164
use PDepend\Source\Builder\BuilderContext\GlobalBuilderContext;
165
use PDepend\Util\Cache\CacheDriver;
166
use PDepend\Util\Log;
167
use PDepend\Util\Type;
168
use ReturnTypeWillChange;
0 ignored issues
show
Bug introduced by
The type ReturnTypeWillChange was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
169
170
/**
171
 * Default code tree builder implementation.
172
 *
173
 * @copyright 2008-2017 Manuel Pichler. All rights reserved.
174
 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
175
 *
176
 * @implements Builder<ASTNamespace>
177
 */
178
class PHPBuilder implements Builder
179
{
180
    /**
181
     * The internal used cache instance.
182
     *
183
     * @var CacheDriver
184
     *
185
     * @since 0.10.0
186
     */
187
    protected $cache = null;
188
189
    /**
190
     * The ast builder context.
191
     *
192
     * @var BuilderContext
193
     *
194
     * @since 0.10.0
195
     */
196
    protected $context = null;
197
198
    /**
199
     * This property holds all packages found during the parsing phase.
200
     *
201
     * @var ASTNamespace[]
202
     *
203
     * @since 0.9.12
204
     */
205
    private $preparedNamespaces = null;
206
207
    /**
208
     * Default package which contains all functions and classes with an unknown
209
     * scope.
210
     *
211
     * @var ASTNamespace
212
     */
213
    protected $defaultPackage = null;
214
215
    /**
216
     * Default source file that acts as a dummy.
217
     *
218
     * @var ASTCompilationUnit
219
     */
220
    protected $defaultCompilationUnit = null;
221
222
    /**
223
     * All generated {@link ASTTrait} objects
224
     *
225
     * @var array<string, array<string, array<int, ASTTrait>>>
226
     */
227
    private $traits = array();
228
229
    /**
230
     * All generated {@link ASTClass} objects
231
     *
232
     * @var array<string, array<string, array<int, ASTClass>>>
233
     */
234
    private $classes = array();
235
236
    /**
237
     * All generated {@link ASTInterface} instances.
238
     *
239
     * @var array<string, array<string, array<int, ASTInterface>>>
240
     */
241
    private $interfaces = array();
242
243
    /**
244
     * All generated {@link ASTNamespace} objects
245
     *
246
     * @var ASTNamespace[]
247
     */
248
    private $namespaces = array();
249
250
    /**
251
     * Internal status flag used to check that a build request is internal.
252
     *
253
     * @var bool
254
     */
255
    private $internal = false;
256
257
    /**
258
     * Internal used flag that marks the parsing process as frozen.
259
     *
260
     * @var bool
261
     */
262
    private $frozen = false;
263
264
    /**
265
     * Cache of all traits created during the regular parsing process.
266
     *
267
     * @var array<string, array<string, array<int, ASTTrait>>>
268
     */
269
    private $frozenTraits = array();
270
271
    /**
272
     * Cache of all classes created during the regular parsing process.
273
     *
274
     * @var array<string, array<string, array<int, ASTClass>>>
275
     */
276
    private $frozenClasses = array();
277
278
    /**
279
     * Cache of all interfaces created during the regular parsing process.
280
     *
281
     * @var array<string, array<string, array<int, ASTInterface>>>
282
     */
283
    private $frozenInterfaces = array();
284
285
    /**
286
     * Constructs a new builder instance.
287
     */
288
    public function __construct()
289
    {
290
        $this->defaultPackage = new ASTNamespace(self::DEFAULT_NAMESPACE);
291
        $this->defaultCompilationUnit = new ASTCompilationUnit(null);
292
293
        $this->namespaces[self::DEFAULT_NAMESPACE] = $this->defaultPackage;
294
295
        $this->context = new GlobalBuilderContext($this);
296
    }
297
298
    /**
299
     * Setter method for the currently used token cache.
300
     *
301
     * @return $this
302
     *
303
     * @since  0.10.0
304
     */
305
    public function setCache(CacheDriver $cache)
306
    {
307
        $this->cache = $cache;
308
        return $this;
309
    }
310
311
    /**
312
     * Builds a new code type reference instance.
313
     *
314
     * @param string $qualifiedName The qualified name of the referenced type.
315
     *
316
     * @return ASTClassOrInterfaceReference
317
     *
318
     * @since  0.9.5
319
     */
320
    public function buildAstClassOrInterfaceReference($qualifiedName)
321
    {
322
        $this->checkBuilderState();
323
324
        // Debug method creation
325
        Log::debug(
326
            'Creating: \\PDepend\\Source\\AST\\ASTClassOrInterfaceReference(' .
327
            $qualifiedName .
328
            ')'
329
        );
330
331
        return new ASTClassOrInterfaceReference($this->context, $qualifiedName);
332
    }
333
334
    /**
335
     * Builds a new code type reference instance, either Class or ClassOrInterface.
336
     *
337
     * @param string $qualifiedName  The qualified name of the referenced type.
338
     * @param bool   $classReference true if class reference only.
339
     *
340
     * @return ASTClassOrInterfaceReference
341
     *
342
     * @since  0.9.5
343
     */
344
    public function buildAstNeededReference($qualifiedName, $classReference)
345
    {
346
        if ($classReference === true) {
347
            return $this->buildAstClassReference($qualifiedName);
348
        }
349
350
        return $this->buildAstClassOrInterfaceReference($qualifiedName);
351
    }
352
353
    /**
354
     * This method will try to find an already existing instance for the given
355
     * qualified name. It will create a new {@link ASTClass}
356
     * instance when no matching type exists.
357
     *
358
     * @param string $qualifiedName
359
     *
360
     * @return AbstractASTClassOrInterface
361
     *
362
     * @since  0.9.5
363
     */
364
    public function getClassOrInterface($qualifiedName)
365
    {
366
        $classOrInterface = $this->findClass($qualifiedName);
367
        if ($classOrInterface !== null) {
368
            return $classOrInterface;
369
        }
370
371
        $classOrInterface = $this->findInterface($qualifiedName);
372
        if ($classOrInterface !== null) {
373
            return $classOrInterface;
374
        }
375
        return $this->buildClassInternal($qualifiedName);
376
    }
377
378
    /**
379
     * Builds a new php trait instance.
380
     *
381
     * @param string $qualifiedName The full qualified trait name.
382
     *
383
     * @return ASTTrait
384
     *
385
     * @since 1.0.0
386
     */
387
    public function buildTrait($qualifiedName)
388
    {
389
        $this->checkBuilderState();
390
391
        $trait = new ASTTrait($this->extractTypeName($qualifiedName));
392
        $trait->setCache($this->cache)
393
            ->setContext($this->context)
394
            ->setCompilationUnit($this->defaultCompilationUnit);
395
396
        return $trait;
397
    }
398
399
    /**
400
     * This method will try to find an already existing instance for the given
401
     * qualified name. It will create a new {@link ASTTrait}
402
     * instance when no matching type exists.
403
     *
404
     * @param string $qualifiedName
405
     *
406
     * @return ASTTrait
407
     *
408
     * @since  1.0.0
409
     */
410
    public function getTrait($qualifiedName)
411
    {
412
        $trait = $this->findTrait($qualifiedName);
413
        if ($trait === null) {
414
            $trait = $this->buildTraitInternal($qualifiedName);
415
        }
416
        return $trait;
417
    }
418
419
    /**
420
     * Builds a new trait reference node.
421
     *
422
     * @param string $qualifiedName The full qualified trait name.
423
     *
424
     * @return ASTTraitReference
425
     *
426
     * @since  1.0.0
427
     */
428
    public function buildAstTraitReference($qualifiedName)
429
    {
430
        $this->checkBuilderState();
431
432
        Log::debug(
433
            'Creating: \\PDepend\\Source\\AST\\ASTTraitReference(' . $qualifiedName . ')'
434
        );
435
436
        return new ASTTraitReference($this->context, $qualifiedName);
437
    }
438
439
    /**
440
     * Builds a new class instance or reuses a previous created class.
441
     *
442
     * Where possible you should give a qualified class name, that is prefixed
443
     * with the package identifier.
444
     *
445
     * <code>
446
     *   $builder->buildClass('php::depend::Parser');
447
     * </code>
448
     *
449
     * To determine the correct class, this method implements the following
450
     * algorithm.
451
     *
452
     * <ol>
453
     *   <li>Check for an exactly matching instance and reuse it.</li>
454
     *   <li>Check for a class instance that belongs to the default package. If
455
     *   such an instance exists, reuse it and replace the default package with
456
     *   the newly given package information.</li>
457
     *   <li>Check that the requested class is in the default package, if this
458
     *   is true, reuse the first class instance and ignore the default package.
459
     *   </li>
460
     *   <li>Create a new instance for the specified package.</li>
461
     * </ol>
462
     *
463
     * @param string $name The class name.
464
     *
465
     * @return ASTClass The created class object.
466
     */
467
    public function buildClass($name)
468
    {
469
        $this->checkBuilderState();
470
471
        $class = new ASTClass($this->extractTypeName($name));
472
        $class->setCache($this->cache)
473
            ->setContext($this->context)
474
            ->setCompilationUnit($this->defaultCompilationUnit);
475
476
        return $class;
477
    }
478
479
    /**
480
     * This method will try to find an already existing instance for the given
481
     * qualified name. It will create a new {@link ASTClass}
482
     * instance when no matching type exists.
483
     *
484
     * @param string $qualifiedName The full qualified type identifier.
485
     *
486
     * @return ASTClass
487
     *
488
     * @since  0.9.5
489
     */
490
    public function getClass($qualifiedName)
491
    {
492
        return $this->findClass($qualifiedName)
493
            ?: $this->buildClassInternal($qualifiedName);
494
    }
495
496
    /**
497
     * Builds an anonymous class instance.
498
     *
499
     * @return ASTAnonymousClass
500
     */
501
    public function buildAnonymousClass()
502
    {
503
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTAnonymousClass')
504
            ->setCache($this->cache)
505
            ->setContext($this->context);
506
    }
507
508
    /**
509
     * Builds a new code type reference instance.
510
     *
511
     * @param string $qualifiedName The qualified name of the referenced type.
512
     *
513
     * @return ASTClassReference
514
     *
515
     * @since  0.9.5
516
     */
517
    public function buildAstClassReference($qualifiedName)
518
    {
519
        $this->checkBuilderState();
520
521
        // Debug method creation
522
        Log::debug(
523
            'Creating: \\PDepend\\Source\\AST\\ASTClassReference(' . $qualifiedName . ')'
524
        );
525
526
        return new ASTClassReference($this->context, $qualifiedName);
527
    }
528
529
    /**
530
     * Builds a new new interface instance.
531
     *
532
     * If there is an existing class instance for the given name, this method
533
     * checks if this class is part of the default namespace. If this is the
534
     * case this method will update all references to the new interface and it
535
     * removes the class instance. Otherwise it creates new interface instance.
536
     *
537
     * Where possible you should give a qualified interface name, that is
538
     * prefixed with the package identifier.
539
     *
540
     * <code>
541
     *   $builder->buildInterface('php::depend::Parser');
542
     * </code>
543
     *
544
     * To determine the correct interface, this method implements the following
545
     * algorithm.
546
     *
547
     * <ol>
548
     *   <li>Check for an exactly matching instance and reuse it.</li>
549
     *   <li>Check for a interface instance that belongs to the default package.
550
     *   If such an instance exists, reuse it and replace the default package
551
     *   with the newly given package information.</li>
552
     *   <li>Check that the requested interface is in the default package, if
553
     *   this is true, reuse the first interface instance and ignore the default
554
     *   package.
555
     *   </li>
556
     *   <li>Create a new instance for the specified package.</li>
557
     * </ol>
558
     *
559
     * @param string $name The interface name.
560
     *
561
     * @return ASTInterface
562
     */
563
    public function buildInterface($name)
564
    {
565
        $this->checkBuilderState();
566
567
        $interface = new ASTInterface($this->extractTypeName($name));
568
        $interface->setCache($this->cache)
569
            ->setContext($this->context)
570
            ->setCompilationUnit($this->defaultCompilationUnit);
571
572
        return $interface;
573
    }
574
575
    /**
576
     * This method will try to find an already existing instance for the given
577
     * qualified name. It will create a new {@link ASTInterface}
578
     * instance when no matching type exists.
579
     *
580
     * @param string $qualifiedName
581
     *
582
     * @return ASTInterface
583
     *
584
     * @since  0.9.5
585
     */
586
    public function getInterface($qualifiedName)
587
    {
588
        $interface = $this->findInterface($qualifiedName);
589
        if ($interface === null) {
590
            $interface = $this->buildInterfaceInternal($qualifiedName);
591
        }
592
        return $interface;
593
    }
594
595
    /**
596
     * Builds a new method instance.
597
     *
598
     * @param string $name
599
     *
600
     * @return ASTMethod
601
     */
602
    public function buildMethod($name)
603
    {
604
        $this->checkBuilderState();
605
606
        // Debug method creation
607
        Log::debug("Creating: \\PDepend\\Source\\AST\\ASTMethod({$name})");
608
609
        // Create a new method instance
610
        $method = new ASTMethod($name);
611
        $method->setCache($this->cache);
612
613
        return $method;
614
    }
615
616
    /**
617
     * Builds a new package instance.
618
     *
619
     * @param string $name The package name.
620
     *
621
     * @return ASTNamespace
622
     */
623
    public function buildNamespace($name)
624
    {
625
        if (!isset($this->namespaces[$name])) {
626
            // Debug package creation
627
            Log::debug(
628
                'Creating: \\PDepend\\Source\\AST\\ASTNamespace(' . $name . ')'
629
            );
630
631
            $this->namespaces[$name] = new ASTNamespace($name);
632
        }
633
        return $this->namespaces[$name];
634
    }
635
636
    /**
637
     * Builds a new function instance.
638
     *
639
     * @param string $name The function name.
640
     *
641
     * @return ASTFunction
642
     */
643
    public function buildFunction($name)
644
    {
645
        $this->checkBuilderState();
646
647
        // Debug function creation
648
        Log::debug("Creating: \\PDepend\\Source\\AST\\ASTFunction({$name})");
649
650
        // Create new function
651
        $function = new ASTFunction($name);
652
        $function->setCache($this->cache)
653
            ->setContext($this->context)
654
            ->setCompilationUnit($this->defaultCompilationUnit);
655
656
        return $function;
657
    }
658
659
    /**
660
     * Builds a new self reference instance.
661
     *
662
     * @return ASTSelfReference
663
     *
664
     * @since  0.9.6
665
     */
666
    public function buildAstSelfReference(AbstractASTClassOrInterface $type)
667
    {
668
        Log::debug(
669
            'Creating: \\PDepend\\Source\\AST\\ASTSelfReference(' . $type->getName() . ')'
670
        );
671
672
        return new ASTSelfReference($this->context, $type);
673
    }
674
675
    /**
676
     * Builds a new parent reference instance.
677
     *
678
     * @param ASTClassOrInterfaceReference $reference The type
679
     *                                                instance that reference the concrete target of parent.
680
     *
681
     * @return ASTParentReference
682
     *
683
     * @since  0.9.6
684
     */
685
    public function buildAstParentReference(ASTClassOrInterfaceReference $reference)
686
    {
687
        Log::debug('Creating: \\PDepend\\Source\\AST\\ASTParentReference()');
688
689
        return new ASTParentReference($reference);
690
    }
691
692
    /**
693
     * Builds a new static reference instance.
694
     *
695
     * @return ASTStaticReference
696
     *
697
     * @since  0.9.6
698
     */
699
    public function buildAstStaticReference(AbstractASTClassOrInterface $owner)
700
    {
701
        Log::debug('Creating: \\PDepend\\Source\\AST\\ASTStaticReference()');
702
703
        return new ASTStaticReference($this->context, $owner);
704
    }
705
706
    /**
707
     * Builds a new field declaration node.
708
     *
709
     * @return ASTFieldDeclaration
710
     *
711
     * @since  0.9.6
712
     */
713
    public function buildAstFieldDeclaration()
714
    {
715
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTFieldDeclaration');
716
    }
717
718
    /**
719
     * Builds a new variable declarator node.
720
     *
721
     * @param string $image The source image for the variable declarator.
722
     *
723
     * @return ASTVariableDeclarator
724
     *
725
     * @since  0.9.6
726
     */
727
    public function buildAstVariableDeclarator($image)
728
    {
729
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTVariableDeclarator', $image);
730
    }
731
732
    /**
733
     * Builds a new static variable declaration node.
734
     *
735
     * @param string $image The source image for the statuc declaration.
736
     *
737
     * @return ASTStaticVariableDeclaration
738
     *
739
     * @since  0.9.6
740
     */
741
    public function buildAstStaticVariableDeclaration($image)
742
    {
743
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTStaticVariableDeclaration', $image);
744
    }
745
746
    /**
747
     * Builds a new constant node.
748
     *
749
     * @param string $image The source image for the constant.
750
     *
751
     * @return ASTConstant
752
     *
753
     * @since  0.9.6
754
     */
755
    public function buildAstConstant($image)
756
    {
757
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTConstant', $image);
758
    }
759
760
    /**
761
     * Builds a new variable node.
762
     *
763
     * @param string $image The source image for the variable.
764
     *
765
     * @return ASTVariable
766
     *
767
     * @since  0.9.6
768
     */
769
    public function buildAstVariable($image)
770
    {
771
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTVariable', $image);
772
    }
773
774
    /**
775
     * Builds a new variable variable node.
776
     *
777
     * @param string $image The source image for the variable variable.
778
     *
779
     * @return ASTVariableVariable
780
     *
781
     * @since  0.9.6
782
     */
783
    public function buildAstVariableVariable($image)
784
    {
785
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTVariableVariable', $image);
786
    }
787
788
    /**
789
     * Builds a new compound variable node.
790
     *
791
     * @param string $image The source image for the compound variable.
792
     *
793
     * @return ASTCompoundVariable
794
     *
795
     * @since  0.9.6
796
     */
797
    public function buildAstCompoundVariable($image)
798
    {
799
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTCompoundVariable', $image);
800
    }
801
802
    /**
803
     * Builds a new compound expression node.
804
     *
805
     * @return ASTCompoundExpression
806
     *
807
     * @since  0.9.6
808
     */
809
    public function buildAstCompoundExpression()
810
    {
811
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTCompoundExpression');
812
    }
813
814
    /**
815
     * Builds a new closure node.
816
     *
817
     * @return ASTClosure
818
     *
819
     * @since  0.9.12
820
     */
821
    public function buildAstClosure()
822
    {
823
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTClosure');
824
    }
825
826
    /**
827
     * Builds a new formal parameters node.
828
     *
829
     * @return ASTFormalParameters
830
     *
831
     * @since  0.9.6
832
     */
833
    public function buildAstFormalParameters()
834
    {
835
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTFormalParameters');
836
    }
837
838
    /**
839
     * Builds a new formal parameter node.
840
     *
841
     * @return ASTFormalParameter
842
     *
843
     * @since  0.9.6
844
     */
845
    public function buildAstFormalParameter()
846
    {
847
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTFormalParameter');
848
    }
849
850
    /**
851
     * Builds a new expression node.
852
     *
853
     * @param string $image
854
     *
855
     * @return ASTExpression
856
     *
857
     * @since 0.9.8
858
     */
859
    public function buildAstExpression($image = null)
860
    {
861
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTExpression', $image);
862
    }
863
864
    /**
865
     * Builds a new assignment expression node.
866
     *
867
     * @param string $image The assignment operator.
868
     *
869
     * @return ASTAssignmentExpression
870
     *
871
     * @since  0.9.8
872
     */
873
    public function buildAstAssignmentExpression($image)
874
    {
875
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTAssignmentExpression', $image);
876
    }
877
878
    /**
879
     * Builds a new allocation expression node.
880
     *
881
     * @param string $image The source image of this expression.
882
     *
883
     * @return ASTAllocationExpression
884
     *
885
     * @since  0.9.6
886
     */
887
    public function buildAstAllocationExpression($image)
888
    {
889
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTAllocationExpression', $image);
890
    }
891
892
    /**
893
     * Builds a new eval-expression node.
894
     *
895
     * @param string $image The source image of this expression.
896
     *
897
     * @return ASTEvalExpression
898
     *
899
     * @since  0.9.12
900
     */
901
    public function buildAstEvalExpression($image)
902
    {
903
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTEvalExpression', $image);
904
    }
905
906
    /**
907
     * Builds a new exit-expression instance.
908
     *
909
     * @param string $image The source code image for this node.
910
     *
911
     * @return ASTExitExpression
912
     *
913
     * @since  0.9.12
914
     */
915
    public function buildAstExitExpression($image)
916
    {
917
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTExitExpression', $image);
918
    }
919
920
    /**
921
     * Builds a new clone-expression node.
922
     *
923
     * @param string $image The source image of this expression.
924
     *
925
     * @return ASTCloneExpression
926
     *
927
     * @since  0.9.12
928
     */
929
    public function buildAstCloneExpression($image)
930
    {
931
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTCloneExpression', $image);
932
    }
933
934
    /**
935
     * Builds a new list-expression node.
936
     *
937
     * @param string $image The source image of this expression.
938
     *
939
     * @return ASTListExpression
940
     *
941
     * @since  0.9.12
942
     */
943
    public function buildAstListExpression($image)
944
    {
945
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTListExpression', $image);
946
    }
947
948
    /**
949
     * Builds a new include- or include_once-expression.
950
     *
951
     * @return ASTIncludeExpression
952
     *
953
     * @since  0.9.12
954
     */
955
    public function buildAstIncludeExpression()
956
    {
957
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTIncludeExpression');
958
    }
959
960
    /**
961
     * Builds a new require- or require_once-expression.
962
     *
963
     * @return ASTRequireExpression
964
     *
965
     * @since  0.9.12
966
     */
967
    public function buildAstRequireExpression()
968
    {
969
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTRequireExpression');
970
    }
971
972
    /**
973
     * Builds a new array-expression node.
974
     *
975
     * @return ASTArrayIndexExpression
976
     *
977
     * @since  0.9.12
978
     */
979
    public function buildAstArrayIndexExpression()
980
    {
981
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTArrayIndexExpression');
982
    }
983
984
    /**
985
     * Builds a new string-expression node.
986
     *
987
     * <code>
988
     * //     --------
989
     * $string{$index}
990
     * //     --------
991
     * </code>
992
     *
993
     * @return ASTStringIndexExpression
994
     *
995
     * @since  0.9.12
996
     */
997
    public function buildAstStringIndexExpression()
998
    {
999
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTStringIndexExpression');
1000
    }
1001
1002
    /**
1003
     * Builds a new php array node.
1004
     *
1005
     * @return ASTArray
1006
     *
1007
     * @since  1.0.0
1008
     */
1009
    public function buildAstArray()
1010
    {
1011
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTArray');
1012
    }
1013
1014
    /**
1015
     * Builds a new array element node.
1016
     *
1017
     * @return ASTArrayElement
1018
     *
1019
     * @since  1.0.0
1020
     */
1021
    public function buildAstArrayElement()
1022
    {
1023
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTArrayElement');
1024
    }
1025
1026
1027
    /**
1028
     * Builds a new instanceof expression node.
1029
     *
1030
     * @param string $image The source image of this expression.
1031
     *
1032
     * @return ASTInstanceOfExpression
1033
     *
1034
     * @since  0.9.6
1035
     */
1036
    public function buildAstInstanceOfExpression($image)
1037
    {
1038
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTInstanceOfExpression', $image);
1039
    }
1040
1041
    /**
1042
     * Builds a new isset-expression node.
1043
     *
1044
     * <code>
1045
     * //  -----------
1046
     * if (isset($foo)) {
1047
     * //  -----------
1048
     * }
1049
     *
1050
     * //  -----------------------
1051
     * if (isset($foo, $bar, $baz)) {
1052
     * //  -----------------------
1053
     * }
1054
     * </code>
1055
     *
1056
     * @return ASTIssetExpression
1057
     *
1058
     * @since  0.9.12
1059
     */
1060
    public function buildAstIssetExpression()
1061
    {
1062
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTIssetExpression');
1063
    }
1064
1065
    /**
1066
     * Builds a new boolean conditional-expression.
1067
     *
1068
     * <code>
1069
     *         --------------
1070
     * $bar = ($foo ? 42 : 23);
1071
     *         --------------
1072
     * </code>
1073
     *
1074
     * @return ASTConditionalExpression
1075
     *
1076
     * @since  0.9.8
1077
     */
1078
    public function buildAstConditionalExpression()
1079
    {
1080
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTConditionalExpression', '?');
1081
    }
1082
1083
    /**
1084
     * Builds a new print-expression.
1085
     *
1086
     * <code>
1087
     * -------------
1088
     * print "qafoo";
1089
     * -------------
1090
     * </code>
1091
     *
1092
     * @return ASTPrintExpression
1093
     *
1094
     * @since 2.3
1095
     */
1096
    public function buildAstPrintExpression()
1097
    {
1098
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTPrintExpression', 'print');
1099
    }
1100
1101
    /**
1102
     * Build a new shift left expression.
1103
     *
1104
     * @return ASTShiftLeftExpression
1105
     *
1106
     * @since  1.0.1
1107
     */
1108
    public function buildAstShiftLeftExpression()
1109
    {
1110
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTShiftLeftExpression');
1111
    }
1112
1113
    /**
1114
     * Build a new shift right expression.
1115
     *
1116
     * @return ASTShiftRightExpression
1117
     *
1118
     * @since  1.0.1
1119
     */
1120
    public function buildAstShiftRightExpression()
1121
    {
1122
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTShiftRightExpression');
1123
    }
1124
1125
    /**
1126
     * Builds a new boolean and-expression.
1127
     *
1128
     * @return ASTBooleanAndExpression
1129
     *
1130
     * @since  0.9.8
1131
     */
1132
    public function buildAstBooleanAndExpression()
1133
    {
1134
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTBooleanAndExpression', '&&');
1135
    }
1136
1137
    /**
1138
     * Builds a new boolean or-expression.
1139
     *
1140
     * @return ASTBooleanOrExpression
1141
     *
1142
     * @since  0.9.8
1143
     */
1144
    public function buildAstBooleanOrExpression()
1145
    {
1146
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTBooleanOrExpression', '||');
1147
    }
1148
1149
    /**
1150
     * Builds a new logical <b>and</b>-expression.
1151
     *
1152
     * @return ASTLogicalAndExpression
1153
     *
1154
     * @since  0.9.8
1155
     */
1156
    public function buildAstLogicalAndExpression()
1157
    {
1158
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTLogicalAndExpression', 'and');
1159
    }
1160
1161
    /**
1162
     * Builds a new logical <b>or</b>-expression.
1163
     *
1164
     * @return ASTLogicalOrExpression
1165
     *
1166
     * @since  0.9.8
1167
     */
1168
    public function buildAstLogicalOrExpression()
1169
    {
1170
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTLogicalOrExpression', 'or');
1171
    }
1172
1173
    /**
1174
     * Builds a new logical <b>xor</b>-expression.
1175
     *
1176
     * @return ASTLogicalXorExpression
1177
     *
1178
     * @since  0.9.8
1179
     */
1180
    public function buildAstLogicalXorExpression()
1181
    {
1182
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTLogicalXorExpression', 'xor');
1183
    }
1184
1185
    /**
1186
     * Builds a new trait use-statement node.
1187
     *
1188
     * @return ASTTraitUseStatement
1189
     *
1190
     * @since  1.0.0
1191
     */
1192
    public function buildAstTraitUseStatement()
1193
    {
1194
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTTraitUseStatement');
1195
    }
1196
1197
    /**
1198
     * Builds a new trait adaptation scope
1199
     *
1200
     * @return ASTTraitAdaptation
1201
     *
1202
     * @since  1.0.0
1203
     */
1204
    public function buildAstTraitAdaptation()
1205
    {
1206
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTTraitAdaptation');
1207
    }
1208
1209
    /**
1210
     * Builds a new trait adaptation alias statement.
1211
     *
1212
     * @param string $image The trait method name.
1213
     *
1214
     * @return ASTTraitAdaptationAlias
1215
     *
1216
     * @since  1.0.0
1217
     */
1218
    public function buildAstTraitAdaptationAlias($image)
1219
    {
1220
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTTraitAdaptationAlias', $image);
1221
    }
1222
1223
    /**
1224
     * Builds a new trait adaptation precedence statement.
1225
     *
1226
     * @param string $image The trait method name.
1227
     *
1228
     * @return ASTTraitAdaptationPrecedence
1229
     *
1230
     * @since  1.0.0
1231
     */
1232
    public function buildAstTraitAdaptationPrecedence($image)
1233
    {
1234
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTTraitAdaptationPrecedence', $image);
1235
    }
1236
1237
    /**
1238
     * Builds a new switch-statement-node.
1239
     *
1240
     * @return ASTSwitchStatement
1241
     *
1242
     * @since  0.9.8
1243
     */
1244
    public function buildAstSwitchStatement()
1245
    {
1246
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTSwitchStatement');
1247
    }
1248
1249
    /**
1250
     * Builds a new switch-label node.
1251
     *
1252
     * @param string $image The source image of this label.
1253
     *
1254
     * @return ASTSwitchLabel
1255
     *
1256
     * @since  0.9.8
1257
     */
1258
    public function buildAstSwitchLabel($image)
1259
    {
1260
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTSwitchLabel', $image);
1261
    }
1262
1263
    /**
1264
     * Builds a new global-statement instance.
1265
     *
1266
     * @return ASTGlobalStatement
1267
     *
1268
     * @since  0.9.12
1269
     */
1270
    public function buildAstGlobalStatement()
1271
    {
1272
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTGlobalStatement');
1273
    }
1274
1275
    /**
1276
     * Builds a new unset-statement instance.
1277
     *
1278
     * @return ASTUnsetStatement
1279
     *
1280
     * @since  0.9.12
1281
     */
1282
    public function buildAstUnsetStatement()
1283
    {
1284
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTUnsetStatement');
1285
    }
1286
1287
    /**
1288
     * Builds a new catch-statement node.
1289
     *
1290
     * @param string $image
1291
     *
1292
     * @return ASTCatchStatement
1293
     *
1294
     * @since  0.9.8
1295
     */
1296
    public function buildAstCatchStatement($image)
1297
    {
1298
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTCatchStatement', $image);
1299
    }
1300
1301
    /**
1302
     * Builds a new finally-statement node.
1303
     *
1304
     * @return ASTFinallyStatement
1305
     *
1306
     * @since  2.0.0
1307
     */
1308
    public function buildAstFinallyStatement()
1309
    {
1310
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTFinallyStatement', 'finally');
1311
    }
1312
1313
    /**
1314
     * Builds a new if statement node.
1315
     *
1316
     * @param string $image The source image of this statement.
1317
     *
1318
     * @return ASTIfStatement
1319
     *
1320
     * @since  0.9.8
1321
     */
1322
    public function buildAstIfStatement($image)
1323
    {
1324
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTIfStatement', $image);
1325
    }
1326
1327
    /**
1328
     * Builds a new elseif statement node.
1329
     *
1330
     * @param string $image The source image of this statement.
1331
     *
1332
     * @return ASTElseIfStatement
1333
     *
1334
     * @since  0.9.8
1335
     */
1336
    public function buildAstElseIfStatement($image)
1337
    {
1338
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTElseIfStatement', $image);
1339
    }
1340
1341
    /**
1342
     * Builds a new for statement node.
1343
     *
1344
     * @param string $image The source image of this statement.
1345
     *
1346
     * @return ASTForStatement
1347
     *
1348
     * @since  0.9.8
1349
     */
1350
    public function buildAstForStatement($image)
1351
    {
1352
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTForStatement', $image);
1353
    }
1354
1355
    /**
1356
     * Builds a new for-init node.
1357
     *
1358
     * <code>
1359
     *      ------------------------
1360
     * for ($x = 0, $y = 23, $z = 42; $x < $y; ++$x) {}
1361
     *      ------------------------
1362
     * </code>
1363
     *
1364
     * @return ASTForInit
1365
     *
1366
     * @since  0.9.8
1367
     */
1368
    public function buildAstForInit()
1369
    {
1370
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTForInit');
1371
    }
1372
1373
    /**
1374
     * Builds a new for-update node.
1375
     *
1376
     * <code>
1377
     *                                        -------------------------------
1378
     * for ($x = 0, $y = 23, $z = 42; $x < $y; ++$x, $y = $x + 1, $z = $x + 2) {}
1379
     *                                        -------------------------------
1380
     * </code>
1381
     *
1382
     * @return ASTForUpdate
1383
     *
1384
     * @since  0.9.12
1385
     */
1386
    public function buildAstForUpdate()
1387
    {
1388
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTForUpdate');
1389
    }
1390
1391
    /**
1392
     * Builds a new foreach-statement node.
1393
     *
1394
     * @param string $image The source image of this statement.
1395
     *
1396
     * @return ASTForeachStatement
1397
     *
1398
     * @since  0.9.8
1399
     */
1400
    public function buildAstForeachStatement($image)
1401
    {
1402
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTForeachStatement', $image);
1403
    }
1404
1405
    /**
1406
     * Builds a new while-statement node.
1407
     *
1408
     * @param string $image The source image of this statement.
1409
     *
1410
     * @return ASTWhileStatement
1411
     *
1412
     * @since  0.9.8
1413
     */
1414
    public function buildAstWhileStatement($image)
1415
    {
1416
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTWhileStatement', $image);
1417
    }
1418
1419
    /**
1420
     * Builds a new do/while-statement node.
1421
     *
1422
     * @param string $image The source image of this statement.
1423
     *
1424
     * @return ASTDoWhileStatement
1425
     *
1426
     * @since  0.9.12
1427
     */
1428
    public function buildAstDoWhileStatement($image)
1429
    {
1430
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTDoWhileStatement', $image);
1431
    }
1432
1433
    /**
1434
     * Builds a new declare-statement node.
1435
     *
1436
     * <code>
1437
     * -------------------------------
1438
     * declare(encoding='ISO-8859-1');
1439
     * -------------------------------
1440
     *
1441
     * -------------------
1442
     * declare(ticks=42) {
1443
     *     // ...
1444
     * }
1445
     * -
1446
     *
1447
     * ------------------
1448
     * declare(ticks=42):
1449
     *     // ...
1450
     * enddeclare;
1451
     * -----------
1452
     * </code>
1453
     *
1454
     * @return ASTDeclareStatement
1455
     *
1456
     * @since  0.10.0
1457
     */
1458
    public function buildAstDeclareStatement()
1459
    {
1460
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTDeclareStatement');
1461
    }
1462
1463
    /**
1464
     * Builds a new member primary expression node.
1465
     *
1466
     * <code>
1467
     * //--------
1468
     * Foo::bar();
1469
     * //--------
1470
     *
1471
     * //---------
1472
     * Foo::$bar();
1473
     * //---------
1474
     *
1475
     * //---------
1476
     * $obj->bar();
1477
     * //---------
1478
     *
1479
     * //----------
1480
     * $obj->$bar();
1481
     * //----------
1482
     * </code>
1483
     *
1484
     * @param string $image The source image of this expression.
1485
     *
1486
     * @return ASTMemberPrimaryPrefix
1487
     *
1488
     * @since  0.9.6
1489
     */
1490
    public function buildAstMemberPrimaryPrefix($image)
1491
    {
1492
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTMemberPrimaryPrefix', $image);
1493
    }
1494
1495
    /**
1496
     * Builds a new identifier node.
1497
     *
1498
     * @param string $image The image of this identifier.
1499
     *
1500
     * @return ASTIdentifier
1501
     *
1502
     * @since  0.9.6
1503
     */
1504
    public function buildAstIdentifier($image)
1505
    {
1506
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTIdentifier', $image);
1507
    }
1508
1509
    /**
1510
     * Builds a new function postfix expression.
1511
     *
1512
     * <code>
1513
     * //-------
1514
     * foo($bar);
1515
     * //-------
1516
     *
1517
     * //--------
1518
     * $foo($bar);
1519
     * //--------
1520
     * </code>
1521
     *
1522
     * @param string $image The image of this node.
1523
     *
1524
     * @return ASTFunctionPostfix
1525
     *
1526
     * @since  0.9.6
1527
     */
1528
    public function buildAstFunctionPostfix($image)
1529
    {
1530
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTFunctionPostfix', $image);
1531
    }
1532
1533
    /**
1534
     * Builds a new method postfix expression.
1535
     *
1536
     * <code>
1537
     * //   ---------
1538
     * Foo::bar($baz);
1539
     * //   ---------
1540
     *
1541
     * //   ----------
1542
     * Foo::$bar($baz);
1543
     * //   ----------
1544
     * </code>
1545
     *
1546
     * @param string $image The image of this node.
1547
     *
1548
     * @return ASTMethodPostfix
1549
     *
1550
     * @since  0.9.6
1551
     */
1552
    public function buildAstMethodPostfix($image)
1553
    {
1554
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTMethodPostfix', $image);
1555
    }
1556
1557
    /**
1558
     * Builds a new constant postfix expression.
1559
     *
1560
     * <code>
1561
     * //   ---
1562
     * Foo::BAR;
1563
     * //   ---
1564
     * </code>
1565
     *
1566
     * @param string $image The image of this node.
1567
     *
1568
     * @return ASTConstantPostfix
1569
     *
1570
     * @since  0.9.6
1571
     */
1572
    public function buildAstConstantPostfix($image)
1573
    {
1574
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTConstantPostfix', $image);
1575
    }
1576
1577
    /**
1578
     * Builds a new property postfix expression.
1579
     *
1580
     * <code>
1581
     * //   ----
1582
     * Foo::$bar;
1583
     * //   ----
1584
     *
1585
     * //       ---
1586
     * $object->bar;
1587
     * //       ---
1588
     * </code>
1589
     *
1590
     * @param string $image The image of this node.
1591
     *
1592
     * @return ASTPropertyPostfix
1593
     *
1594
     * @since  0.9.6
1595
     */
1596
    public function buildAstPropertyPostfix($image)
1597
    {
1598
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTPropertyPostfix', $image);
1599
    }
1600
1601
    /**
1602
     * Builds a new full qualified class name postfix expression.
1603
     *
1604
     * <code>
1605
     * //   -----
1606
     * Foo::class;
1607
     * //   -----
1608
     *
1609
     * //       -----
1610
     * $object::class;
1611
     * //       -----
1612
     * </code>
1613
     *
1614
     * @return ASTClassFqnPostfix
1615
     *
1616
     * @since  2.0.0
1617
     */
1618
    public function buildAstClassFqnPostfix()
1619
    {
1620
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTClassFqnPostfix', 'class');
1621
    }
1622
1623
    /**
1624
     * Builds a new arguments list.
1625
     *
1626
     * <code>
1627
     * //      ------------
1628
     * Foo::bar($x, $y, $z);
1629
     * //      ------------
1630
     *
1631
     * //       ------------
1632
     * $foo->bar($x, $y, $z);
1633
     * //       ------------
1634
     * </code>
1635
     *
1636
     * @return ASTArguments
1637
     *
1638
     * @since  0.9.6
1639
     */
1640
    public function buildAstArguments()
1641
    {
1642
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTArguments');
1643
    }
1644
1645
    /**
1646
     * Builds a new argument match expression single-item slot.
1647
     *
1648
     * <code>
1649
     * match($x)
1650
     * </code>
1651
     *
1652
     * @return ASTMatchArgument
1653
     *
1654
     * @since  0.9.6
1655
     */
1656
    public function buildAstMatchArgument()
1657
    {
1658
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTMatchArgument');
1659
    }
1660
1661
    /**
1662
     * Builds a new match block.
1663
     *
1664
     * <code>
1665
     * match($x) {
1666
     *   "foo" => "bar",
1667
     * }
1668
     * </code>
1669
     *
1670
     * @return ASTMatchBlock
1671
     *
1672
     * @since  2.9.0
1673
     */
1674
    public function buildAstMatchBlock()
1675
    {
1676
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTMatchBlock');
1677
    }
1678
1679
    /**
1680
     * Builds a new match item.
1681
     *
1682
     * <code>
1683
     * "foo" => "bar",
1684
     * </code>
1685
     *
1686
     * @return ASTMatchEntry
1687
     *
1688
     * @since  2.9.0
1689
     */
1690
    public function buildAstMatchEntry()
1691
    {
1692
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTMatchEntry');
1693
    }
1694
1695
    /**
1696
     * Builds a new named argument node.
1697
     *
1698
     * <code>
1699
     * number_format(5623, thousands_separator: ' ')
1700
     * </code>
1701
     *
1702
     * @param string $name
1703
     *
1704
     * @return ASTNamedArgument
1705
     *
1706
     * @since  2.9.0
1707
     */
1708
    public function buildAstNamedArgument($name, ASTNode $value)
1709
    {
1710
        Log::debug("Creating: \\PDepend\\Source\\AST\\ASTNamedArgument($name)");
1711
1712
        return new ASTNamedArgument($name, $value);
1713
    }
1714
1715
    /**
1716
     * Builds a new array type node.
1717
     *
1718
     * @return ASTTypeArray
1719
     *
1720
     * @since  0.9.6
1721
     */
1722
    public function buildAstTypeArray()
1723
    {
1724
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTTypeArray');
1725
    }
1726
1727
    /**
1728
     * Builds a new node for the callable type.
1729
     *
1730
     * @return ASTTypeCallable
1731
     *
1732
     * @since  1.0.0
1733
     */
1734
    public function buildAstTypeCallable()
1735
    {
1736
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTTypeCallable');
1737
    }
1738
1739
    /**
1740
     * Builds a new node for the iterable type.
1741
     *
1742
     * @return ASTTypeIterable
1743
     *
1744
     * @since  2.5.1
1745
     */
1746
    public function buildAstTypeIterable()
1747
    {
1748
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTTypeIterable');
1749
    }
1750
1751
    /**
1752
     * Builds a new primitive type node.
1753
     *
1754
     * @param string $image The source image for the primitive type.
1755
     *
1756
     * @return ASTScalarType
1757
     *
1758
     * @since  0.9.6
1759
     */
1760
    public function buildAstScalarType($image)
1761
    {
1762
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTScalarType', $image);
1763
    }
1764
1765
    /**
1766
     * Builds a new node for the union type.
1767
     *
1768
     * @return ASTUnionType
1769
     *
1770
     * @since  1.0.0
1771
     */
1772
    public function buildAstUnionType()
1773
    {
1774
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTUnionType');
1775
    }
1776
1777
    /**
1778
     * Builds a new node for the union type.
1779
     *
1780
     * @return ASTIntersectionType
1781
     */
1782
    public function buildAstIntersectionType()
1783
    {
1784
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTIntersectionType');
1785
    }
1786
1787
    /**
1788
     * Builds a new literal node.
1789
     *
1790
     * @param string $image The source image for the literal node.
1791
     *
1792
     * @return ASTLiteral
1793
     *
1794
     * @since  0.9.6
1795
     */
1796
    public function buildAstLiteral($image)
1797
    {
1798
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTLiteral', $image);
1799
    }
1800
1801
    /**
1802
     * Builds a new php string node.
1803
     *
1804
     * <code>
1805
     * $string = "Manuel $Pichler <{$email}>";
1806
     *
1807
     * // ASTString
1808
     * // |-- ASTLiteral             -  "Manuel ")
1809
     * // |-- ASTVariable            -  $Pichler
1810
     * // |-- ASTLiteral             -  " <"
1811
     * // |-- ASTCompoundExpression  -  {...}
1812
     * // |   |-- ASTVariable        -  $email
1813
     * // |-- ASTLiteral             -  ">"
1814
     * </code>
1815
     *
1816
     * @return ASTString
1817
     *
1818
     * @since  0.9.10
1819
     */
1820
    public function buildAstString()
1821
    {
1822
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTString');
1823
    }
1824
1825
    /**
1826
     * Builds a new heredoc node.
1827
     *
1828
     * @return ASTHeredoc
1829
     *
1830
     * @since  0.9.12
1831
     */
1832
    public function buildAstHeredoc()
1833
    {
1834
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTHeredoc');
1835
    }
1836
1837
    /**
1838
     * Builds a new constant definition node.
1839
     *
1840
     * <code>
1841
     * class Foo
1842
     * {
1843
     * //  ------------------------
1844
     *     const FOO = 42, BAR = 23;
1845
     * //  ------------------------
1846
     * }
1847
     * </code>
1848
     *
1849
     * @param string $image The source code image for this node.
1850
     *
1851
     * @return ASTConstantDefinition
1852
     *
1853
     * @since  0.9.6
1854
     */
1855
    public function buildAstConstantDefinition($image)
1856
    {
1857
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTConstantDefinition', $image);
1858
    }
1859
1860
    /**
1861
     * Builds a new constant declarator node.
1862
     *
1863
     * <code>
1864
     * class Foo
1865
     * {
1866
     *     //    --------
1867
     *     const BAR = 42;
1868
     *     //    --------
1869
     * }
1870
     * </code>
1871
     *
1872
     * Or in a comma separated constant defintion:
1873
     *
1874
     * <code>
1875
     * class Foo
1876
     * {
1877
     *     //    --------
1878
     *     const BAR = 42,
1879
     *     //    --------
1880
     *
1881
     *     //    --------------
1882
     *     const BAZ = 'Foobar',
1883
     *     //    --------------
1884
     *
1885
     *     //    ----------
1886
     *     const FOO = 3.14;
1887
     *     //    ----------
1888
     * }
1889
     * </code>
1890
     *
1891
     * @param string $image The source code image for this node.
1892
     *
1893
     * @return ASTConstantDeclarator
1894
     *
1895
     * @since  0.9.6
1896
     */
1897
    public function buildAstConstantDeclarator($image)
1898
    {
1899
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTConstantDeclarator', $image);
1900
    }
1901
1902
    /**
1903
     * Builds a new comment node instance.
1904
     *
1905
     * @param string $cdata The comment text.
1906
     *
1907
     * @return ASTComment
1908
     *
1909
     * @since  0.9.8
1910
     */
1911
    public function buildAstComment($cdata)
1912
    {
1913
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTComment', $cdata);
1914
    }
1915
1916
    /**
1917
     * Builds a new unary expression node instance.
1918
     *
1919
     * @param string $image The unary expression image/character.
1920
     *
1921
     * @return ASTUnaryExpression
1922
     *
1923
     * @since  0.9.11
1924
     */
1925
    public function buildAstUnaryExpression($image)
1926
    {
1927
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTUnaryExpression', $image);
1928
    }
1929
1930
    /**
1931
     * Builds a new cast-expression node instance.
1932
     *
1933
     * @param string $image The cast-expression image/character.
1934
     *
1935
     * @return ASTCastExpression
1936
     *
1937
     * @since  0.10.0
1938
     */
1939
    public function buildAstCastExpression($image)
1940
    {
1941
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTCastExpression', $image);
1942
    }
1943
1944
    /**
1945
     * Builds a new postfix-expression node instance.
1946
     *
1947
     * @param string $image The postfix-expression image/character.
1948
     *
1949
     * @return ASTPostfixExpression
1950
     *
1951
     * @since  0.10.0
1952
     */
1953
    public function buildAstPostfixExpression($image)
1954
    {
1955
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTPostfixExpression', $image);
1956
    }
1957
1958
    /**
1959
     * Builds a new pre-increment-expression node instance.
1960
     *
1961
     * @return ASTPreIncrementExpression
1962
     *
1963
     * @since  0.10.0
1964
     */
1965
    public function buildAstPreIncrementExpression()
1966
    {
1967
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTPreIncrementExpression');
1968
    }
1969
1970
    /**
1971
     * Builds a new pre-decrement-expression node instance.
1972
     *
1973
     * @return ASTPreDecrementExpression
1974
     *
1975
     * @since  0.10.0
1976
     */
1977
    public function buildAstPreDecrementExpression()
1978
    {
1979
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTPreDecrementExpression');
1980
    }
1981
1982
    /**
1983
     * Builds a new function/method scope instance.
1984
     *
1985
     * @return ASTScope
1986
     *
1987
     * @since  0.9.12
1988
     */
1989
    public function buildAstScope()
1990
    {
1991
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTScope');
1992
    }
1993
1994
    /**
1995
     * Builds a new statement instance.
1996
     *
1997
     * @return ASTStatement
1998
     *
1999
     * @since  0.9.12
2000
     */
2001
    public function buildAstStatement()
2002
    {
2003
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTStatement');
2004
    }
2005
2006
    /**
2007
     * Builds a new return statement node instance.
2008
     *
2009
     * @param string $image The source code image for this node.
2010
     *
2011
     * @return ASTReturnStatement
2012
     *
2013
     * @since  0.9.12
2014
     */
2015
    public function buildAstReturnStatement($image)
2016
    {
2017
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTReturnStatement', $image);
2018
    }
2019
2020
    /**
2021
     * Builds a new break-statement node instance.
2022
     *
2023
     * @param string $image The source code image for this node.
2024
     *
2025
     * @return ASTBreakStatement
2026
     *
2027
     * @since  0.9.12
2028
     */
2029
    public function buildAstBreakStatement($image)
2030
    {
2031
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTBreakStatement', $image);
2032
    }
2033
2034
    /**
2035
     * Builds a new continue-statement node instance.
2036
     *
2037
     * @param string $image The source code image for this node.
2038
     *
2039
     * @return ASTContinueStatement
2040
     *
2041
     * @since  0.9.12
2042
     */
2043
    public function buildAstContinueStatement($image)
2044
    {
2045
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTContinueStatement', $image);
2046
    }
2047
2048
    /**
2049
     * Builds a new scope-statement instance.
2050
     *
2051
     * @return ASTScopeStatement
2052
     *
2053
     * @since  0.9.12
2054
     */
2055
    public function buildAstScopeStatement()
2056
    {
2057
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTScopeStatement');
2058
    }
2059
2060
    /**
2061
     * Builds a new try-statement instance.
2062
     *
2063
     * @param string $image The source code image for this node.
2064
     *
2065
     * @return ASTTryStatement
2066
     *
2067
     * @since  0.9.12
2068
     */
2069
    public function buildAstTryStatement($image)
2070
    {
2071
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTTryStatement', $image);
2072
    }
2073
2074
    /**
2075
     * Builds a new throw-statement instance.
2076
     *
2077
     * @param string $image The source code image for this node.
2078
     *
2079
     * @return ASTThrowStatement
2080
     *
2081
     * @since  0.9.12
2082
     */
2083
    public function buildAstThrowStatement($image)
2084
    {
2085
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTThrowStatement', $image);
2086
    }
2087
2088
    /**
2089
     * Builds a new goto-statement instance.
2090
     *
2091
     * @param string $image The source code image for this node.
2092
     *
2093
     * @return ASTGotoStatement
2094
     *
2095
     * @since  0.9.12
2096
     */
2097
    public function buildAstGotoStatement($image)
2098
    {
2099
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTGotoStatement', $image);
2100
    }
2101
2102
    /**
2103
     * Builds a new label-statement instance.
2104
     *
2105
     * @param string $image The source code image for this node.
2106
     *
2107
     * @return ASTLabelStatement
2108
     *
2109
     * @since  0.9.12
2110
     */
2111
    public function buildAstLabelStatement($image)
2112
    {
2113
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTLabelStatement', $image);
2114
    }
2115
2116
    /**
2117
     * Builds a new exit-statement instance.
2118
     *
2119
     * @param string $image The source code image for this node.
2120
     *
2121
     * @return ASTEchoStatement
2122
     *
2123
     * @since  0.9.12
2124
     */
2125
    public function buildAstEchoStatement($image)
2126
    {
2127
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTEchoStatement', $image);
2128
    }
2129
2130
    /**
2131
     * Builds a new yield-statement instance.
2132
     *
2133
     * @param string $image The source code image for this node.
2134
     *
2135
     * @return ASTYieldStatement
2136
     *
2137
     * @since  $version$
2138
     */
2139
    public function buildAstYieldStatement($image)
2140
    {
2141
        return $this->buildAstNodeInstance('\\PDepend\\Source\\AST\\ASTYieldStatement', $image);
2142
    }
2143
2144
    /**
2145
     * Returns an iterator with all generated {@link ASTNamespace}
2146
     * objects.
2147
     *
2148
     * @return ASTArtifactList<ASTNamespace>
2149
     */
2150
    #[ReturnTypeWillChange]
2151
    public function getIterator()
2152
    {
2153
        return $this->getNamespaces();
2154
    }
2155
2156
    /**
2157
     * Returns an iterator with all generated {@link ASTNamespace}
2158
     * objects.
2159
     *
2160
     * @return ASTArtifactList<ASTNamespace>
2161
     */
2162
    public function getNamespaces()
2163
    {
2164
        if ($this->preparedNamespaces === null) {
2165
            $this->preparedNamespaces = $this->getPreparedNamespaces();
2166
        }
2167
        return new ASTArtifactList($this->preparedNamespaces);
2168
    }
2169
2170
    /**
2171
     * Returns an iterator with all generated {@link ASTNamespace}
2172
     * objects.
2173
     *
2174
     * @return ASTNamespace[]
2175
     *
2176
     * @since  0.9.12
2177
     */
2178
    private function getPreparedNamespaces()
2179
    {
2180
        // Create a package array copy
2181
        $namespaces = $this->namespaces;
2182
2183
        // Remove default package if empty
2184
        if (count($this->defaultPackage->getTypes()) === 0
2185
            && count($this->defaultPackage->getFunctions()) === 0
2186
        ) {
2187
            unset($namespaces[self::DEFAULT_NAMESPACE]);
2188
        }
2189
        return $namespaces;
2190
    }
2191
2192
    /**
2193
     * Builds a new trait instance or reuses a previous created trait.
2194
     *
2195
     * Where possible you should give a qualified trait name, that is prefixed
2196
     * with the package identifier.
2197
     *
2198
     * <code>
2199
     *   $builder->buildTrait('php::depend::Parser');
2200
     * </code>
2201
     *
2202
     * To determine the correct trait, this method implements the following
2203
     * algorithm.
2204
     *
2205
     * <ol>
2206
     *   <li>Check for an exactly matching instance and reuse it.</li>
2207
     *   <li>Check for a class instance that belongs to the default package. If
2208
     *   such an instance exists, reuse it and replace the default package with
2209
     *   the newly given package information.</li>
2210
     *   <li>Check that the requested trait is in the default package, if this
2211
     *   is true, reuse the first trait instance and ignore the default package.
2212
     *   </li>
2213
     *   <li>Create a new instance for the specified package.</li>
2214
     * </ol>
2215
     *
2216
     * @param string $qualifiedName
2217
     *
2218
     * @return ASTTrait
2219
     *
2220
     * @since  0.9.5
2221
     */
2222
    protected function buildTraitInternal($qualifiedName)
2223
    {
2224
        $this->internal = true;
2225
2226
        $trait = $this->buildTrait($qualifiedName);
2227
        $trait->setNamespace(
2228
            $this->buildNamespace($this->extractNamespaceName($qualifiedName))
2229
        );
2230
2231
        $this->restoreTrait($trait);
2232
2233
        return $trait;
2234
    }
2235
2236
    /**
2237
     * This method tries to find a trait instance matching for the given
2238
     * qualified name in all scopes already processed. It will return the best
2239
     * matching instance or <b>null</b> if no match exists.
2240
     *
2241
     * @param string $qualifiedName
2242
     *
2243
     * @return ASTTrait|null
2244
     *
2245
     * @since  0.9.5
2246
     */
2247
    protected function findTrait($qualifiedName)
2248
    {
2249
        $this->freeze();
2250
2251
        /** @var ASTTrait|null $trait */
2252
        $trait = $this->findType(
2253
            $this->frozenTraits,
2254
            $qualifiedName
2255
        );
2256
2257
        if ($trait === null) {
2258
            $trait = $this->findType($this->traits, $qualifiedName);
2259
        }
2260
        return $trait;
2261
    }
2262
2263
    /**
2264
     * Builds a new new interface instance.
2265
     *
2266
     * If there is an existing interface instance for the given name, this method
2267
     * checks if this interface is part of the default namespace. If this is the
2268
     * case this method will update all references to the new interface and it
2269
     * removes the class instance. Otherwise it creates new interface instance.
2270
     *
2271
     * Where possible you should give a qualified interface name, that is
2272
     * prefixed with the package identifier.
2273
     *
2274
     * <code>
2275
     *   $builder->buildInterface('php::depend::Parser');
2276
     * </code>
2277
     *
2278
     * To determine the correct interface, this method implements the following
2279
     * algorithm.
2280
     *
2281
     * <ol>
2282
     *   <li>Check for an exactly matching instance and reuse it.</li>
2283
     *   <li>Check for a interface instance that belongs to the default package.
2284
     *   If such an instance exists, reuse it and replace the default package
2285
     *   with the newly given package information.</li>
2286
     *   <li>Check that the requested interface is in the default package, if
2287
     *   this is true, reuse the first interface instance and ignore the default
2288
     *   package.
2289
     *   </li>
2290
     *   <li>Create a new instance for the specified package.</li>
2291
     * </ol>
2292
     *
2293
     * @param string $qualifiedName
2294
     *
2295
     * @return ASTInterface
2296
     *
2297
     * @since  0.9.5
2298
     */
2299
    protected function buildInterfaceInternal($qualifiedName)
2300
    {
2301
        $this->internal = true;
2302
2303
        $interface = $this->buildInterface($qualifiedName);
2304
        $interface->setNamespace(
2305
            $this->buildNamespace($this->extractNamespaceName($qualifiedName))
2306
        );
2307
2308
        $this->restoreInterface($interface);
2309
2310
        return $interface;
2311
    }
2312
2313
    /**
2314
     * This method tries to find an interface instance matching for the given
2315
     * qualified name in all scopes already processed. It will return the best
2316
     * matching instance or <b>null</b> if no match exists.
2317
     *
2318
     * @param string $qualifiedName
2319
     *
2320
     * @return ASTInterface|null
2321
     *
2322
     * @since  0.9.5
2323
     */
2324
    protected function findInterface($qualifiedName)
2325
    {
2326
        $this->freeze();
2327
2328
        /** @var ASTInterface|null $interface */
2329
        $interface = $this->findType(
2330
            $this->frozenInterfaces,
2331
            $qualifiedName
2332
        );
2333
2334
        if ($interface === null) {
2335
            $interface = $this->findType(
2336
                $this->interfaces,
2337
                $qualifiedName
2338
            );
2339
        }
2340
        return $interface;
2341
    }
2342
2343
    /**
2344
     * Builds a new class instance or reuses a previous created class.
2345
     *
2346
     * Where possible you should give a qualified class name, that is prefixed
2347
     * with the package identifier.
2348
     *
2349
     * <code>
2350
     *   $builder->buildClass('php::depend::Parser');
2351
     * </code>
2352
     *
2353
     * To determine the correct class, this method implements the following
2354
     * algorithm.
2355
     *
2356
     * <ol>
2357
     *   <li>Check for an exactly matching instance and reuse it.</li>
2358
     *   <li>Check for a class instance that belongs to the default package. If
2359
     *   such an instance exists, reuse it and replace the default package with
2360
     *   the newly given package information.</li>
2361
     *   <li>Check that the requested class is in the default package, if this
2362
     *   is true, reuse the first class instance and ignore the default package.
2363
     *   </li>
2364
     *   <li>Create a new instance for the specified package.</li>
2365
     * </ol>
2366
     *
2367
     * @param string $qualifiedName
2368
     *
2369
     * @return ASTClass
2370
     *
2371
     * @since  0.9.5
2372
     */
2373
    protected function buildClassInternal($qualifiedName)
2374
    {
2375
        $this->internal = true;
2376
2377
        $class = $this->buildClass($qualifiedName);
2378
        $class->setNamespace(
2379
            $this->buildNamespace($this->extractNamespaceName($qualifiedName))
2380
        );
2381
2382
        $this->restoreClass($class);
2383
2384
        return $class;
2385
    }
2386
2387
    /**
2388
     * This method tries to find a class instance matching for the given
2389
     * qualified name in all scopes already processed. It will return the best
2390
     * matching instance or <b>null</b> if no match exists.
2391
     *
2392
     * @param string $qualifiedName
2393
     *
2394
     * @return ASTClass|null
2395
     *
2396
     * @since  0.9.5
2397
     */
2398
    protected function findClass($qualifiedName)
2399
    {
2400
        $this->freeze();
2401
2402
        /** @var ASTClass|null $class */
2403
        $class = $this->findType(
2404
            $this->frozenClasses,
2405
            $qualifiedName
2406
        );
2407
2408
        if ($class === null) {
2409
            $class = $this->findType($this->classes, $qualifiedName);
2410
        }
2411
        return $class;
2412
    }
2413
2414
    /**
2415
     * This method tries to find an interface or class instance matching for the
2416
     * given qualified name in all scopes already processed. It will return the
2417
     * best matching instance or <b>null</b> if no match exists.
2418
     *
2419
     * @template T of AbstractASTType
2420
     *
2421
     * @param array<string, array<string, array<int, T>>> $instances
2422
     * @param string                                         $qualifiedName
2423
     *
2424
     * @return T|null
0 ignored issues
show
Bug introduced by
The type PDepend\Source\Language\PHP\T was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
2425
     *
2426
     * @since  0.9.5
2427
     */
2428
    protected function findType(array $instances, $qualifiedName)
2429
    {
2430
        $classOrInterfaceName = $this->extractTypeName($qualifiedName);
2431
        $caseInsensitiveName = strtolower($classOrInterfaceName);
2432
        if (!isset($instances[$caseInsensitiveName])) {
2433
            return null;
2434
        }
2435
2436
        $namespaceName = $this->extractNamespaceName($qualifiedName);
2437
        if ($namespaceName === null) {
2438
            return null;
2439
        }
2440
2441
        // Check for exact match and return first matching instance
2442
        if (isset($instances[$caseInsensitiveName][$namespaceName])) {
2443
            return reset($instances[$caseInsensitiveName][$namespaceName]) ?: null;
2444
        }
2445
2446
        if (!$this->isDefault($namespaceName)) {
2447
            return null;
2448
        }
2449
2450
        $classesOrInterfaces = reset($instances[$caseInsensitiveName]);
2451
        if (!$classesOrInterfaces) {
2452
            return null;
2453
        }
2454
2455
        return reset($classesOrInterfaces);
2456
    }
2457
2458
    /**
2459
     * This method will freeze the actual builder state and create a second
2460
     * runtime scope.
2461
     *
2462
     * @return void
2463
     *
2464
     * @since  0.9.5
2465
     */
2466
    protected function freeze()
2467
    {
2468
        if ($this->frozen === true) {
2469
            return;
2470
        }
2471
2472
        $this->frozen = true;
2473
2474
        $this->frozenTraits     = $this->copyTypesWithPackage($this->traits);
2475
        $this->frozenClasses    = $this->copyTypesWithPackage($this->classes);
2476
        $this->frozenInterfaces = $this->copyTypesWithPackage($this->interfaces);
2477
2478
        $this->traits     = array();
2479
        $this->classes    = array();
2480
        $this->interfaces = array();
2481
    }
2482
2483
    /**
2484
     * Creates a copy of the given input array, but skips all types that do not
2485
     * contain a parent package.
2486
     *
2487
     * @template T of AbstractASTType
2488
     *
2489
     * @param array<string, array<string, array<int, T>>> $originalTypes The original types created during the parsing
2490
     *                                                                   process.
2491
     *
2492
     * @return array<string, array<string, array<int, T>>>
2493
     */
2494
    private function copyTypesWithPackage(array $originalTypes)
2495
    {
2496
        $copiedTypes = array();
2497
        foreach ($originalTypes as $typeName => $namespaces) {
2498
            foreach ($namespaces as $namespaceName => $types) {
2499
                foreach ($types as $index => $type) {
2500
                    $copiedTypes[$typeName][$namespaceName][$index] = $type;
2501
                }
2502
            }
2503
        }
2504
        return $copiedTypes;
2505
    }
2506
2507
    /**
2508
     * Restores a function within the internal type scope.
2509
     *
2510
     * @return void
2511
     *
2512
     * @since  0.10.0
2513
     */
2514
    public function restoreFunction(ASTFunction $function)
2515
    {
2516
        $this->buildNamespace($function->getNamespaceName())
2517
            ->addFunction($function);
2518
    }
2519
2520
    /**
2521
     * Restores a trait within the internal type scope.
2522
     *
2523
     * @return void
2524
     *
2525
     * @since  0.10.0
2526
     */
2527
    public function restoreTrait(ASTTrait $trait)
2528
    {
2529
        $this->storeTrait(
2530
            $trait->getName(),
2531
            $trait->getNamespaceName(),
2532
            $trait
2533
        );
2534
    }
2535
2536
    /**
2537
     * Restores a class within the internal type scope.
2538
     *
2539
     * @return void
2540
     *
2541
     * @since  0.10.0
2542
     */
2543
    public function restoreClass(ASTClass $class)
2544
    {
2545
        $this->storeClass(
2546
            $class->getName(),
2547
            $class->getNamespaceName(),
2548
            $class
2549
        );
2550
    }
2551
2552
    /**
2553
     * Restores an enum within the internal type scope.
2554
     *
2555
     * @return void
2556
     *
2557
     * @since  2.11.0
2558
     */
2559
    public function restoreEnum(ASTEnum $enum)
2560
    {
2561
        $this->storeEnum(
2562
            $enum->getName(),
2563
            $enum->getNamespaceName(),
2564
            $enum
2565
        );
2566
    }
2567
2568
    /**
2569
     * Restores an interface within the internal type scope.
2570
     *
2571
     * @return void
2572
     *
2573
     * @since  0.10.0
2574
     */
2575
    public function restoreInterface(ASTInterface $interface)
2576
    {
2577
        $this->storeInterface(
2578
            $interface->getName(),
2579
            $interface->getNamespaceName(),
2580
            $interface
2581
        );
2582
    }
2583
2584
    /**
2585
     * Builds an enum definition.
2586
     *
2587
     * @param string        $name The enum name.
2588
     * @param ASTScalarType $type The enum type ('string', 'int', or null if not backed).
2589
     *
2590
     * @return ASTEnum The created class object.
2591
     */
2592
    public function buildEnum($name, ASTScalarType $type = null)
2593
    {
2594
        $this->checkBuilderState();
2595
2596
        $enum = new ASTEnum($name, $type);
2597
        $enum->setCache($this->cache)
2598
            ->setContext($this->context)
2599
            ->setCompilationUnit($this->defaultCompilationUnit);
2600
2601
        return $enum;
2602
    }
2603
2604
    /**
2605
     * Builds an enum definition.
2606
     *
2607
     * @param string          $name  The enum case name.
2608
     * @param AbstractASTNode $value The enum case value if backed.
2609
     *
2610
     * @return ASTEnumCase The created class object.
2611
     */
2612
    public function buildEnumCase($name, AbstractASTNode $value = null)
2613
    {
2614
        $this->checkBuilderState();
2615
2616
        $enumCase = new ASTEnumCase($name);
2617
2618
        if ($value !== null) {
2619
            $enumCase->addChild($value);
2620
        }
2621
2622
        return $enumCase;
2623
    }
2624
2625
    /**
2626
     * This method will persist a trait instance for later reuse.
2627
     *
2628
     * @param string $traitName
2629
     * @param string $namespaceName
2630
     *
2631
     * @return void
2632
     *
2633
     * @since 1.0.0
2634
     */
2635
    protected function storeTrait($traitName, $namespaceName, ASTTrait $trait)
2636
    {
2637
        $traitName = strtolower($traitName);
2638
        if (!isset($this->traits[$traitName][$namespaceName])) {
2639
            $this->traits[$traitName][$namespaceName] = array();
2640
        }
2641
        $this->traits[$traitName][$namespaceName][$trait->getId()] = $trait;
2642
2643
        $namespace = $this->buildNamespace($namespaceName);
2644
        $namespace->addType($trait);
2645
    }
2646
2647
    /**
2648
     * This method will persist a class instance for later reuse.
2649
     *
2650
     * @param string $className
2651
     * @param string $namespaceName
2652
     *
2653
     * @return void
2654
     *
2655
     * @since 0.9.5
2656
     */
2657
    protected function storeClass($className, $namespaceName, ASTClass $class)
2658
    {
2659
        $className = strtolower($className);
2660
        if (!isset($this->classes[$className][$namespaceName])) {
2661
            $this->classes[$className][$namespaceName] = array();
2662
        }
2663
        $this->classes[$className][$namespaceName][$class->getId()] = $class;
2664
2665
        $namespace = $this->buildNamespace($namespaceName);
2666
        $namespace->addType($class);
2667
    }
2668
2669
    /**
2670
     * This method will persist a class instance for later reuse.
2671
     *
2672
     * @param string $enumName
2673
     * @param string $namespaceName
2674
     *
2675
     * @return void
2676
     *
2677
     * @since 2.11.0
2678
     */
2679
    protected function storeEnum($enumName, $namespaceName, ASTEnum $enum)
2680
    {
2681
        $enumName = strtolower($enumName);
2682
        if (!isset($this->classes[$enumName][$namespaceName])) {
2683
            $this->classes[$enumName][$namespaceName] = array();
2684
        }
2685
        $this->classes[$enumName][$namespaceName][$enum->getId()] = $enum;
2686
2687
        $namespace = $this->buildNamespace($namespaceName);
2688
        $namespace->addType($enum);
2689
    }
2690
2691
    /**
2692
     * This method will persist an interface instance for later reuse.
2693
     *
2694
     * @param string $interfaceName
2695
     * @param string $namespaceName
2696
     *
2697
     * @return void
2698
     *
2699
     * @since 0.9.5
2700
     */
2701
    protected function storeInterface($interfaceName, $namespaceName, ASTInterface $interface)
2702
    {
2703
        $interfaceName = strtolower($interfaceName);
2704
        if (!isset($this->interfaces[$interfaceName][$namespaceName])) {
2705
            $this->interfaces[$interfaceName][$namespaceName] = array();
2706
        }
2707
        $this->interfaces[$interfaceName][$namespaceName][$interface->getId()]
2708
            = $interface;
2709
2710
        $namespace = $this->buildNamespace($namespaceName);
2711
        $namespace->addType($interface);
2712
    }
2713
2714
    /**
2715
     * Checks that the parser is not frozen or a request is flagged as internal.
2716
     *
2717
     * @param bool $internal The new internal flag value.
2718
     *
2719
     * @throws BadMethodCallException
2720
     *
2721
     * @return void
2722
     *
2723
     * @since  0.9.5
2724
     */
2725
    protected function checkBuilderState($internal = false)
2726
    {
2727
        if ($this->frozen === true && $this->internal === false) {
2728
            throw new BadMethodCallException(
2729
                'Cannot create new nodes, when internal state is frozen.'
2730
            );
2731
        }
2732
        $this->internal = $internal;
2733
    }
2734
2735
2736
    /**
2737
     * Returns <b>true</b> if the given package is the default package.
2738
     *
2739
     * @param string $namespaceName The package name.
2740
     *
2741
     * @return bool
2742
     */
2743
    protected function isDefault($namespaceName)
2744
    {
2745
        return ($namespaceName === self::DEFAULT_NAMESPACE);
2746
    }
2747
2748
    /**
2749
     * Extracts the type name of a qualified PHP 5.3 type identifier.
2750
     *
2751
     * <code>
2752
     *   $typeName = $this->extractTypeName('foo\bar\foobar');
2753
     *   var_dump($typeName);
2754
     *   // Results in:
2755
     *   // string(6) "foobar"
2756
     * </code>
2757
     *
2758
     * @param string $qualifiedName The qualified PHP 5.3 type identifier.
2759
     *
2760
     * @return string
2761
     */
2762
    protected function extractTypeName($qualifiedName)
2763
    {
2764
        if (($pos = strrpos($qualifiedName, '\\')) !== false) {
2765
            return substr($qualifiedName, $pos + 1);
2766
        }
2767
        return $qualifiedName;
2768
    }
2769
2770
    /**
2771
     * Extracts the package name of a qualified PHP 5.3 class identifier.
2772
     *
2773
     * If the class name doesn't contain a package identifier this method will
2774
     * return the default identifier.
2775
     *
2776
     * <code>
2777
     *   $namespaceName = $this->extractPackageName('foo\bar\foobar');
2778
     *   var_dump($namespaceName);
2779
     *   // Results in:
2780
     *   // string(8) "foo\bar"
2781
     *
2782
     *   $namespaceName = $this->extractPackageName('foobar');
2783
     *   var_dump($namespaceName);
2784
     *   // Results in:
2785
     *   // string(6) "+global"
2786
     * </code>
2787
     *
2788
     * @param string $qualifiedName The qualified PHP 5.3 class identifier.
2789
     *
2790
     * @return string|null
2791
     */
2792
    protected function extractNamespaceName($qualifiedName)
2793
    {
2794
        if (($pos = strrpos($qualifiedName, '\\')) !== false) {
2795
            return ltrim(substr($qualifiedName, 0, $pos), '\\');
2796
        } elseif (Type::isInternalType($qualifiedName)) {
2797
            return Type::getTypePackage($qualifiedName);
2798
        }
2799
        return self::DEFAULT_NAMESPACE;
2800
    }
2801
2802
    /**
2803
     * Creates a {@link ASTNode} instance.
2804
     *
2805
     * @template T of ASTNode
2806
     *
2807
     * @param class-string<T> $className
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<T> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<T>.
Loading history...
2808
     * @param string          $image
2809
     *
2810
     * @return T
2811
     *
2812
     * @since 0.9.12
2813
     */
2814
    private function buildAstNodeInstance($className, $image = null)
2815
    {
2816
        Log::debug("Creating: {$className}({$image})");
2817
2818
        return new $className($image);
2819
    }
2820
}
2821