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

Relation   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 137
Duplicated Lines 53.28 %

Coupling/Cohesion

Components 1
Dependencies 9

Test Coverage

Coverage 87%

Importance

Changes 11
Bugs 0 Features 0
Metric Value
c 11
b 0
f 0
dl 73
loc 137
wmc 11
lcom 1
cbo 9
ccs 87
cts 100
cp 0.87
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A fetch_arguments() 0 4 1
A arguments_are_valid() 0 9 3
A pprint() 0 3 1
B compile() 73 81 4
A insert_relation_into() 0 13 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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