SymbolTableBuilderVisitor::enter()   B
last analyzed

Complexity

Conditions 8
Paths 8

Size

Total Lines 37
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 22
dl 0
loc 37
rs 8.4444
c 1
b 0
f 0
cc 8
nc 8
nop 1
1
<?php
2
3
/**
4
 * This file is part of Railt package.
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
declare(strict_types=1);
11
12
namespace Railt\SDL\Backend;
13
14
use Phplrt\Contracts\Ast\NodeInterface;
15
use Phplrt\Visitor\Visitor;
16
use Railt\SDL\Backend\Context\DirectiveDefinitionLocator;
0 ignored issues
show
Bug introduced by
The type Railt\SDL\Backend\Contex...ectiveDefinitionLocator 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...
17
use Railt\SDL\Backend\Context\EnumTypeDefinitionLocator;
18
use Railt\SDL\Backend\Context\InputObjectTypeDefinitionLocator;
19
use Railt\SDL\Backend\Context\InterfaceTypeDefinitionLocator;
20
use Railt\SDL\Backend\Context\ObjectTypeDefinitionLocator;
21
use Railt\SDL\Backend\Context\ScalarTypeDefinitionLocator;
22
use Railt\SDL\Backend\Context\TypeLocatorInterface;
23
use Railt\SDL\Backend\Context\UnionTypeDefinitionLocator;
24
use Railt\SDL\Exception\TypeErrorException;
25
use Railt\SDL\Frontend\Ast\Definition\DirectiveDefinitionNode;
26
use Railt\SDL\Frontend\Ast\Definition\Type\EnumTypeDefinitionNode;
27
use Railt\SDL\Frontend\Ast\Definition\Type\InputObjectTypeDefinitionNode;
28
use Railt\SDL\Frontend\Ast\Definition\Type\InterfaceTypeDefinitionNode;
29
use Railt\SDL\Frontend\Ast\Definition\Type\ObjectTypeDefinitionNode;
30
use Railt\SDL\Frontend\Ast\Definition\Type\ScalarTypeDefinitionNode;
31
use Railt\SDL\Frontend\Ast\Definition\Type\TypeDefinitionNode;
32
use Railt\SDL\Frontend\Ast\Definition\Type\UnionTypeDefinitionNode;
33
34
/**
35
 * Class TypeBuilderVisitor
36
 */
37
class SymbolTableBuilderVisitor extends Visitor
38
{
39
    /**
40
     * @var string
41
     */
42
    private const ERROR_TYPE_DUPLICATION = 'GraphQL %s type has already been defined';
43
44
    /**
45
     * @var string
46
     */
47
    private const ERROR_DIRECTIVE_DUPLICATION = 'GraphQL directive @%s has already been defined';
48
49
    /**
50
     * @var ContextInterface
51
     */
52
    private ContextInterface $context;
53
54
    /**
55
     * TypeBuilderVisitor constructor.
56
     *
57
     * @param ContextInterface $context
58
     */
59
    public function __construct(ContextInterface $context)
60
    {
61
        $this->context = $context;
62
    }
63
64
    /**
65
     * @param NodeInterface $node
66
     * @return void
67
     * @throws \Throwable
68
     */
69
    public function enter(NodeInterface $node): void
70
    {
71
        switch (true) {
72
            case $node instanceof DirectiveDefinitionNode:
73
                $this->registerDirectiveOrError(new DirectiveDefinitionLocator($node), $node);
74
75
                break;
76
77
            case $node instanceof EnumTypeDefinitionNode:
78
                $this->registerTypeOrError(new EnumTypeDefinitionLocator($node), $node);
79
80
                break;
81
82
            case $node instanceof InterfaceTypeDefinitionNode:
83
                $this->registerTypeOrError(new InterfaceTypeDefinitionLocator($node), $node);
84
85
                break;
86
87
            case $node instanceof InputObjectTypeDefinitionNode:
88
                $this->registerTypeOrError(new InputObjectTypeDefinitionLocator($node), $node);
89
90
                break;
91
92
            case $node instanceof ObjectTypeDefinitionNode:
93
                $this->registerTypeOrError(new ObjectTypeDefinitionLocator($node), $node);
94
95
                break;
96
97
            case $node instanceof ScalarTypeDefinitionNode:
98
                $this->registerTypeOrError(new ScalarTypeDefinitionLocator($node), $node);
99
100
                break;
101
102
            case $node instanceof UnionTypeDefinitionNode:
103
                $this->registerTypeOrError(new UnionTypeDefinitionLocator($node), $node);
104
105
                break;
106
        }
107
    }
108
109
    /**
110
     * @param TypeLocatorInterface $ctx
111
     * @param DirectiveDefinitionNode $node
112
     * @return void
113
     */
114
    private function registerDirectiveOrError(TypeLocatorInterface $ctx, DirectiveDefinitionNode $node): void
115
    {
116
        if ($this->context->hasDirective($ctx->getName())) {
117
            $message = \sprintf(self::ERROR_DIRECTIVE_DUPLICATION, $ctx->getName());
118
119
            throw TypeErrorException::fromAst($message, $node->name);
120
        }
121
122
        $this->context->addDirective($ctx);
123
    }
124
125
    /**
126
     * @param TypeLocatorInterface $context
127
     * @param TypeDefinitionNode $node
128
     * @return void
129
     */
130
    private function registerTypeOrError(TypeLocatorInterface $context, TypeDefinitionNode $node): void
131
    {
132
        if ($this->context->hasType($context->getName())) {
133
            $message = \sprintf(self::ERROR_TYPE_DUPLICATION, $context->getName());
134
135
            throw TypeErrorException::fromAst($message, $node->name);
136
        }
137
138
        $this->context->addType($context);
139
    }
140
}
141