Completed
Push — master ( f7852e...e666ea )
by Richard
06:08
created

Relation::compile()   B

Complexity

Conditions 7
Paths 3

Size

Total Lines 59
Code Lines 46

Duplication

Lines 9
Ratio 15.25 %

Code Coverage

Tests 48
CRAP Score 7.0031

Importance

Changes 0
Metric Value
dl 9
loc 59
ccs 48
cts 50
cp 0.96
rs 7.5346
c 0
b 0
f 0
cc 7
eloc 46
nc 3
nop 2
crap 7.0031

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\Index;
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
use Lechimp\Dicto\Graph\Node;
19
20
/**
21
 * This is a rule that checks a relation between two entities
22
 * in the code.
23
 *
24
 * TODO: Test if relation can be used for files.
25
 */
26
abstract class Relation extends Schema {
27
    /**
28
     * @inheritdoc
29
     */
30 4
    public function fetch_arguments(ArgumentParser $parser) {
31 4
        $var = $parser->fetch_variable();
32 4
        return array($var);
33
    }
34
35
    /**
36
     * @inheritdoc
37
     */
38 33
    public function arguments_are_valid(array &$arguments) {
39 33
         if (count($arguments) != 1) {
40
            return false;
41
        }
42 33
        if (!($arguments[0] instanceof Variable)) {
43
            return false;
44
        }
45 33
        return true;
46
    }
47
48
    /**
49
     * @inheritdoc
50
     */
51 25
    public function pprint(Rule $rule) {
52 25
        return $this->name()." ".$rule->argument(0)->name();
53
    }
54
55
    /**
56
     * @inheritdoc
57
     */
58 13
    public function compile(Index $index, Rule $rule) {
59 13
        $mode = $rule->mode();
60 13
        $var_left = $rule->checked_on();
61 13
        $var_right = $rule->argument(0);
62 13
        if ($mode == Rule::MODE_CANNOT || $mode == Rule::MODE_ONLY_CAN) {
63 7
            $filter_left = $var_left->compile();
64 7
            $filter_right = $var_right->compile();
65 7
            return $index->query()
0 ignored issues
show
Bug introduced by
The method expand_relation() does not exist on Lechimp\Dicto\Graph\Query. Did you maybe mean expand()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
66 7
                ->filter($filter_left)
67 7
                ->expand_relation([$this->name()])
68 View Code Duplication
                ->extract(function($e,&$r) use ($rule) {
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...
69 2
                    $file = $e->property("file");
70 2
                    assert('$file->type() == "file"');
71 2
                    $r["rule"] = $rule;
72 2
                    $r["file"] = $file->property("path");
73 2
                    $line = $e->property("line");
74 2
                    $r["line"] = $line;
75 2
                    $r["source"] = $file->property("source")[$line - 1];
76 7
                })
77 7
                ->expand_target()
78 7
                ->filter($filter_right)
79 7
                ;
80
        }
81 6
        if ($mode == Rule::MODE_MUST) {
82 6
            $filter_left = $var_left->compile();
83 6
            $filter_right = $var_right->compile();
84 6
            return $index->query()
85 6
                ->filter($filter_left)
86
                ->filter(function(Node $n) use ($filter_right) {
87
                    $rels = $n->relations(function($r) {
88 6
                        return $r->type() == $this->name();
89 6
                    });
90 6
                    if (count($rels) == 0) {
91
                        return true;
92
                    }
93 6
                    foreach ($rels as $rel) {
94 6
                        if ($filter_right($rel->target())) {
95 3
                            return false;
96
                        }
97 4
                    }
98 3
                    return true;
99 6
                })
100
                ->extract(function($e,&$r) use ($index, $rule) {
101 3
                    $rels = $e->relations(function($r) {
102 3
                        return $r->type() == "defined in";
103 3
                    });
104 3
                    assert('count($rels) == 1');
105 3
                    $file = $rels[0]->target();
106 3
                    assert('$file->type() == "file"');
107 3
                    $r["rule"] = $rule;
108 3
                    $r["file"] = $file->property("path");
109 3
                    $line = $rels[0]->property("start_line");
110 3
                    $r["line"] = $line;
111 3
                    $r["source"] = $file->property("source")[$line - 1];
112 6
                })
113 6
                ;
114
        }
115
        throw new \LogicException("Unknown rule mode: '$mode'");
116
    }
117
118
    /**
119
     * Insert this relation somewhere, where it is recorded for all
120
     * entities that the current location is in.
121
     *
122
     * @param   Insert      $insert
123
     * @param   Location    $location
124
     * @param   mixed       $other
125
     * @return  null
126
     */
127 17
    protected function insert_relation_into(Insert $insert, Location $location, $other, $line) {
128 17
        assert('is_int($line)');
129 17
        foreach ($location->in_entities() as $entity) {
130 17
            if ($entity[0] == Variable::FILE_TYPE) {
131 17
                continue;
132
            }
133 17
            $insert->_relation
134 17
                ( $entity[1]
135 17
                , $this->name()
136 17
                , $other
137 17
                , $location->file()
138 17
                , $line
139 17
                );
140 17
        }
141 17
    }
142
}
143