Completed
Push — master ( 3b5f38...c5ceed )
by Tomáš
04:59
created

Fixer::replaceToken()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 4
Bugs 0 Features 0
Metric Value
dl 0
loc 23
ccs 0
cts 19
cp 0
rs 8.5906
c 4
b 0
f 0
cc 5
eloc 13
nc 4
nop 2
crap 30
1
<?php
2
3
/*
4
 * This file is part of Symplify
5
 * Copyright (c) 2016 Tomas Votruba (http://tomasvotruba.cz).
6
 */
7
8
namespace Symplify\PHP7_CodeSniffer;
9
10
use Symplify\PHP7_CodeSniffer\File\File;
11
12
final class Fixer
13
{
14
    /**
15
     * @var File
16
     */
17
    private $currentFile;
18
19
    /**
20
     * The list of tokens that make up the file contents.
21
     *
22
     * This is a simplified list which just contains the token content and nothing
23
     * else. This is the array that is updated as fixes are made, not the file's
24
     * token array. Imploding this array will give you the file content back.
25
     *
26
     * @var array<int, string>
27
     */
28
    private $tokens = array();
29
30
    /**
31
     * A list of tokens that have already been fixed.
32
     *
33
     * We don't allow the same token to be fixed more than once each time
34
     * through a file as this can easily cause conflicts between sniffs.
35
     *
36
     * @var int[]
37
     */
38
    private $fixedTokens = [];
39
40
    /**
41
     * A list of tokens that have been fixed during a changeset.
42
     *
43
     * @var array
44
     */
45
    private $changeset = [];
46
47
    /**
48
     * @var bool
49
     */
50
    private $inChangeset = false;
51
52
    public function startFile(File $file)
53
    {
54
        $this->currentFile = $file;
55
        $this->fixedTokens = [];
56
57
        $tokens = $file->getTokens();
58
59
        $this->tokens = [];
60
        foreach ($tokens as $index => $token) {
61
            if (isset($token['orig_content']) === true) {
62
                $this->tokens[$index] = $token['orig_content'];
63
            } else {
64
                $this->tokens[$index] = $token['content'];
65
            }
66
        }
67
    }
68
69
    public function getContents() : string
70
    {
71
        return implode($this->tokens);
72
    }
73
74 View Code Duplication
    public function getTokenContent(int $stackPtr) : string
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
75
    {
76
        if ($this->inChangeset === true
77
            && isset($this->changeset[$stackPtr]) === true
78
        ) {
79
            return $this->changeset[$stackPtr];
80
        } else {
81
            return $this->tokens[$stackPtr];
82
        }
83
    }
84
85
    public function beginChangeset()
86
    {
87
        $this->changeset = [];
88
        $this->inChangeset = true;
89
    }
90
91
    /**
92
     * @return bool|null
93
     */
94
    public function endChangeset()
95
    {
96
        $this->inChangeset = false;
97
98
        $success = true;
99
        $applied = [];
100
101
        foreach ($this->changeset as $stackPtr => $content) {
102
            $success = $this->replaceToken($stackPtr, $content);
103
            if ($success === false) {
104
                break;
105
            } else {
106
                $applied[] = $stackPtr;
107
            }
108
        }
109
110
        if ($success === false) {
111
            // Rolling back all changes.
112
            foreach ($applied as $stackPtr) {
113
                $this->revertToken($stackPtr);
114
            }
115
        }
116
117
        $this->changeset = [];
118
    }
119
120
    /**
121
     * Replace the entire contents of a token.
122
     *
123
     * @return bool If the change was accepted.
124
     */
125
    public function replaceToken(int $stackPtr, string $content) : bool
126
    {
127
        if ($this->inChangeset === false
128
            && isset($this->fixedTokens[$stackPtr]) === true
129
        ) {
130
            $indent = "\t";
131
            if (empty($this->changeset) === false) {
132
                $indent .= "\t";
133
            }
134
135
            return false;
136
        }
137
138
        if ($this->inChangeset === true) {
139
            $this->changeset[$stackPtr] = $content;
140
            return true;
141
        }
142
143
        $this->fixedTokens[$stackPtr] = $this->tokens[$stackPtr];
144
        $this->tokens[$stackPtr]      = $content;
145
146
        return true;
147
    }
148
149
    /**
150
     * @return bool If a change was reverted.
151
     */
152 View Code Duplication
    public function revertToken(int $stackPtr) : bool
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
153
    {
154
        if (isset($this->fixedTokens[$stackPtr]) === false) {
155
            return false;
156
        }
157
158
        $this->tokens[$stackPtr] = $this->fixedTokens[$stackPtr];
159
        unset($this->fixedTokens[$stackPtr]);
160
161
        return true;
162
    }
163
164
    public function substrToken(int $stackPtr, int $start, int $length = null) : bool
165
    {
166
        $current = $this->getTokenContent($stackPtr);
167
168
        if ($length === null) {
169
            $newContent = substr($current, $start);
170
        } else {
171
            $newContent = substr($current, $start, $length);
172
        }
173
174
        return $this->replaceToken($stackPtr, $newContent);
175
    }
176
177
    public function addNewline(int $stackPtr) : bool
178
    {
179
        $current = $this->getTokenContent($stackPtr);
180
        return $this->replaceToken($stackPtr, $current.$this->currentFile->eolChar);
181
    }
182
183
    public function addNewlineBefore(int $stackPtr) : bool
184
    {
185
        $current = $this->getTokenContent($stackPtr);
186
        return $this->replaceToken($stackPtr, $this->currentFile->eolChar.$current);
187
    }
188
189
    public function addContent(int $stackPtr, string $content) : bool
190
    {
191
        $current = $this->getTokenContent($stackPtr);
192
        return $this->replaceToken($stackPtr, $current.$content);
193
    }
194
195
    public function addContentBefore(int $stackPtr, string $content) : bool
196
    {
197
        $current = $this->getTokenContent($stackPtr);
198
        return $this->replaceToken($stackPtr, $content.$current);
199
    }
200
}
201