Completed
Push — master ( 9971b9...3d6cb8 )
by Richard
06:14
created

Relation::compile()   B

Complexity

Conditions 4
Paths 3

Size

Total Lines 81
Code Lines 63

Duplication

Lines 73
Ratio 90.12 %

Code Coverage

Tests 65
CRAP Score 4.0484

Importance

Changes 5
Bugs 0 Features 0
Metric Value
c 5
b 0
f 0
dl 73
loc 81
ccs 65
cts 76
cp 0.8553
rs 8.5264
nc 3
cc 4
eloc 63
nop 2
crap 4.0484

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/******************************************************************************
3
 * An implementation of dicto (scg.unibe.ch/dicto) in and for PHP.
4
 *
5
 * Copyright (c) 2016 Richard Klees <[email protected]>
6
 *
7
 * This software is licensed under The MIT License. You should have received
8
 * a copy of the license along with the code.
9
 */
10
11
namespace Lechimp\Dicto\Rules;
12
13
use Lechimp\Dicto\Analysis\Query;
14
use Lechimp\Dicto\Definition\ArgumentParser;
15
use Lechimp\Dicto\Indexer\Insert;
16
use Lechimp\Dicto\Indexer\Location;
17
use Lechimp\Dicto\Variables\Variable;
18
19
/**
20
 * This is a rule that checks a relation between two entities
21
 * in the code.
22
 *
23
 * TODO: Test if relation can be used for files.
24
 */
25
abstract class Relation extends Schema {
26
    /**
27
     * @inheritdoc
28
     */
29 6
    public function fetch_arguments(ArgumentParser $parser) {
30 6
        $var = $parser->fetch_variable();
31 6
        return array($var);
32
    }
33
34
    /**
35
     * @inheritdoc
36
     */
37 59
    public function arguments_are_valid(array &$arguments) {
38 59
         if (count($arguments) != 1) {
39
            return false;
40
        }
41 59
        if (!($arguments[0] instanceof Variable)) {
42
            return false;
43
        }
44 59
        return true;
45
    }
46
47
    /**
48
     * @inheritdoc
49
     */
50 14
    public function pprint(Rule $rule) {
51 14
        return $this->name()." ".$rule->argument(0)->name();
52
    }
53
54
    /**
55
     * @inheritdoc
56
     */
57 37
    public function compile(Query $query, Rule $rule) {
58 37
        $builder = $query->builder();
59 37
        $b = $builder->expr();
60 37
        $mode = $rule->mode();
61 37
        $name_left = $rule->checked_on();
62 37
        $name_right = $rule->argument(0);
63 37 View Code Duplication
        if ($mode == Rule::MODE_CANNOT || $mode == Rule::MODE_ONLY_CAN) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
64
            return $builder
0 ignored issues
show
Bug Compatibility introduced by
The expression $builder->select('rel.na...($b, 'nr'))->execute(); of type Doctrine\DBAL\Driver\Statement|integer adds the type integer to the return on line 64 which is incompatible with the return type declared by the abstract method Lechimp\Dicto\Rules\Schema::compile of type Doctrine\DBAL\Driver\Statement.
Loading history...
65 29
                ->select
66 29
                    ( "rel.name_left"
67 29
                    , "rel.name_right"
68 29
                    , "f.path as file"
69 29
                    , "rel.line as line"
70 29
                    , "src.source as source"
71 29
                    )
72 29
                ->from($query->relation_table(), "rel")
73
                ->join
74 29
                    ( "rel", $query->file_table(), "f"
75 29
                    , $b->eq("rel.file", "f.id")
76 29
                    )
77
                ->join
78 29
                    ( "rel", $query->name_table(), "nl"
79 29
                    , $b->eq("rel.name_left", "nl.id")
80 29
                    )
81
                ->join
82 29
                    ( "rel", $query->name_table(), "nr"
83 29
                    , $b->eq("rel.name_right", "nr.id")
84 29
                    )
85
                ->join
86 29
                    ( "rel", $query->source_table(), "src"
87 29
                    , $b->andX
88 29
                        ( $b->eq("src.line", "rel.line")
89 29
                        , $b->eq("src.file", "rel.file")
90 29
                        )
91 29
                    )
92
                ->where
93 29
                    ( $b->eq("rel.which", $b->literal($this->name()))
94 29
                    , $name_left->compile($b, "nl")
95 29
                    , $name_right->compile($b, "nr")
96 29
                    )
97 29
                ->execute();
98
        }
99 8 View Code Duplication
        if ($mode == Rule::MODE_MUST) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
100
            return $builder
101 8
                ->select
102 8
                    ( "d.name"
103 8
                    , "f.path as file"
104 8
                    , "d.start_line as line"
105 8
                    , "src.source as source"
106 8
                    )
107 8
                ->from($query->definition_table(), "d")
108
                ->join
109 8
                    ( "d", $query->file_table(), "f"
110 8
                    , $b->eq("d.file", "f.id")
111 8
                    )
112
                ->join
113 8
                    ( "d", $query->name_table(), "n"
114 8
                    , $b->eq("d.name", "n.id")
115 8
                    )
116
                ->leftJoin
117 8
                    ("d", $query->relation_table(), "rel"
118 8
                    , $b->andX
119 8
                        ( $b->eq("rel.which", $b->literal($this->name()))
120 8
                        , $b->eq("rel.name_left", "d.name")
121 8
                        )
122 8
                    )
123
                ->innerJoin
124 8
                    ( "d", $query->source_table(), "src"
125 8
                    , $b->andX
126 8
                        ( $b->eq("src.line", "d.start_line")
127 8
                        , $b->eq("src.file", "d.file")
128 8
                        )
129 8
                    )
130
                ->where
131 8
                    ( $name_left->compile($b, "n")
132 8
                    , $b->isNull("rel.name_right")
133 8
                    )
134 8
                ->execute();
135
        }
136
        throw new \LogicException("Unknown rule mode: '$mode'");
137
    }
138
139
    /**
140
     * Insert this relation somewhere, where it is recorded for all
141
     * entities that the current location is in.
142
     *
143
     * @param   Insert      $insert
144
     * @param   Location    $location
145
     * @param   int         $name_id
146
     * @return  null
147
     */
148 6
    protected function insert_relation_into(Insert $insert, Location $location, $name_id, $line) {
149 6
        assert('is_int($name_id)');
150 6
        assert('is_int($line)');
151 6
        foreach ($location->in_entities() as $entity) {
152 6
            $insert->relation
153 6
                ( $entity[1]
154 6
                , $name_id
155 6
                , $this->name()
156 6
                , $location->file_path()
157 6
                , $line
158 6
                );
159 6
        }
160 6
    }
161
}
162