Completed
Push — master ( da54d7...33d164 )
by Colin
25s queued 10s
created

AdjacentTextMerger::mergeTextNodesInclusive()   A

Complexity

Conditions 5
Paths 7

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 25
c 0
b 0
f 0
ccs 17
cts 17
cp 1
rs 9.2088
cc 5
nc 7
nop 2
crap 5
1
<?php
2
3
/*
4
 * This file is part of the league/commonmark package.
5
 *
6
 * (c) Colin O'Dell <[email protected]>
7
 *
8
 * Additional emphasis processing code based on commonmark-java (https://github.com/atlassian/commonmark-java)
9
 *  - (c) Atlassian Pty Ltd
10
 *
11
 * For the full copyright and license information, please view the LICENSE
12
 * file that was distributed with this source code.
13
 */
14
15
namespace League\CommonMark\Inline;
16
17
use League\CommonMark\Inline\Element\Text;
18
use League\CommonMark\Node\Node;
19
20
/**
21
 * @internal
22
 */
23
final class AdjacentTextMerger
24
{
25 1746
    public static function mergeChildNodes(Node $node)
26
    {
27
        // No children or just one child node, no need for merging
28 1746
        if ($node->firstChild() === $node->lastChild()) {
29 1125
            return;
30
        }
31
32 801
        self::mergeTextNodesInclusive($node->firstChild(), $node->lastChild());
0 ignored issues
show
Bug introduced by Colin O'Dell
It seems like $node->firstChild() can be null; however, mergeTextNodesInclusive() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
Bug introduced by Colin O'Dell
It seems like $node->lastChild() can be null; however, mergeTextNodesInclusive() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
33 801
    }
34
35 354
    public static function mergeTextNodesBetweenExclusive(Node $fromNode, Node $toNode)
36
    {
37
        // No nodes between them
38 354
        if ($fromNode === $toNode || $fromNode->next() === $toNode) {
39
            return;
40
        }
41
42 354
        self::mergeTextNodesInclusive($fromNode->next(), $toNode->previous());
0 ignored issues
show
Bug introduced by Colin O'Dell
It seems like $fromNode->next() can be null; however, mergeTextNodesInclusive() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
Bug introduced by Colin O'Dell
It seems like $toNode->previous() can be null; however, mergeTextNodesInclusive() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
43 354
    }
44
45 981
    private static function mergeTextNodesInclusive(Node $fromNode, Node $toNode)
46
    {
47 981
        $first = null;
48 981
        $last = null;
49
50 981
        $node = $fromNode;
51 981
        while ($node !== null) {
52 981
            if ($node instanceof Text) {
53 960
                if ($first === null) {
54 960
                    $first = $node;
55
                }
56 960
                $last = $node;
57
            } else {
58 678
                self::mergeIfNeeded($first, $last);
59 678
                $first = null;
60 678
                $last = null;
61
            }
62 981
            if ($node === $toNode) {
63 981
                break;
64
            }
65 924
            $node = $node->next();
66
        }
67
68 981
        self::mergeIfNeeded($first, $last);
69 981
    }
70
71 981
    private static function mergeIfNeeded(?Text $first, ?Text $last)
72
    {
73 981
        if ($first === null || $last === null || $first === $last) {
74
            // No merging needed
75 708
            return;
76
        }
77
78 420
        $s = $first->getContent();
79
80 420
        $node = $first->next();
81 420
        $stop = $last->next();
82 420
        while ($node !== $stop && $node instanceof Text) {
83 420
            $s .= $node->getContent();
84 420
            $unlink = $node;
85 420
            $node = $node->next();
86 420
            $unlink->detach();
87
        }
88
89 420
        $first->setContent($s);
90 420
    }
91
}
92