• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PHPCSStandards / PHP_CodeSniffer / 14516416464

17 Apr 2025 01:09PM UTC coverage: 77.945% (+0.3%) from 77.666%
14516416464

push

github

web-flow
Merge pull request #1010 from PHPCSStandards/phpcs-4.0/feature/sq-1612-stdout-vs-stderr

(Nearly) All status, debug, and progress output is now sent to STDERR instead of STDOUT

63 of 457 new or added lines in 18 files covered. (13.79%)

1 existing line in 1 file now uncovered.

19455 of 24960 relevant lines covered (77.94%)

78.64 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/Files/LocalFile.php
1
<?php
2
/**
3
 * A local file represents a chunk of text has a file system location.
4
 *
5
 * @author    Greg Sherwood <gsherwood@squiz.net>
6
 * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
7
 * @license   https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
8
 */
9

10
namespace PHP_CodeSniffer\Files;
11

12
use PHP_CodeSniffer\Config;
13
use PHP_CodeSniffer\Ruleset;
14
use PHP_CodeSniffer\Util\Cache;
15
use PHP_CodeSniffer\Util\Common;
16
use PHP_CodeSniffer\Util\Writers\StatusWriter;
17

18
class LocalFile extends File
19
{
20

21

22
    /**
23
     * Creates a LocalFile object and sets the content.
24
     *
25
     * @param string                   $path    The absolute path to the file.
26
     * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run.
27
     * @param \PHP_CodeSniffer\Config  $config  The config data for the run.
28
     *
29
     * @return void
30
     */
31
    public function __construct($path, Ruleset $ruleset, Config $config)
×
32
    {
33
        $this->path = trim($path);
×
34
        if (Common::isReadable($this->path) === false) {
×
35
            parent::__construct($this->path, $ruleset, $config);
×
36
            $error = 'Error opening file; file no longer exists or you do not have access to read the file';
×
37
            $this->addMessage(true, $error, 1, 1, 'Internal.LocalFile', [], 5, false);
×
38
            $this->ignored = true;
×
39
            return;
×
40
        }
41

42
        // Before we go and spend time tokenizing this file, just check
43
        // to see if there is a tag up top to indicate that the whole
44
        // file should be ignored. It must be on one of the first two lines.
45
        if ($config->annotations === true) {
×
46
            $handle = fopen($this->path, 'r');
×
47
            if ($handle !== false) {
×
48
                $firstContent  = fgets($handle);
×
49
                $firstContent .= fgets($handle);
×
50
                fclose($handle);
×
51

52
                if (stripos($firstContent, 'phpcs:ignorefile') !== false) {
×
53
                    // We are ignoring the whole file.
54
                    $this->ignored = true;
×
55
                    return;
×
56
                }
57
            }
58
        }
59

60
        $this->reloadContent();
×
61

62
        parent::__construct($this->path, $ruleset, $config);
×
63

64
    }//end __construct()
65

66

67
    /**
68
     * Loads the latest version of the file's content from the file system.
69
     *
70
     * @return void
71
     */
72
    public function reloadContent()
×
73
    {
74
        $this->setContent(file_get_contents($this->path));
×
75

76
    }//end reloadContent()
77

78

79
    /**
80
     * Processes the file.
81
     *
82
     * @return void
83
     */
84
    public function process()
×
85
    {
86
        if ($this->ignored === true) {
×
87
            return;
×
88
        }
89

90
        if ($this->configCache['cache'] === false) {
×
91
            parent::process();
×
92
            return;
×
93
        }
94

95
        $hash  = md5_file($this->path);
×
96
        $hash .= fileperms($this->path);
×
97
        $cache = Cache::get($this->path);
×
98
        if ($cache !== false && $cache['hash'] === $hash) {
×
99
            // We can't filter metrics, so just load all of them.
100
            $this->metrics = $cache['metrics'];
×
101

102
            if ($this->configCache['recordErrors'] === true) {
×
103
                // Replay the cached errors and warnings to filter out the ones
104
                // we don't need for this specific run.
105
                $this->configCache['cache'] = false;
×
106
                $this->replayErrors($cache['errors'], $cache['warnings']);
×
107
                $this->configCache['cache'] = true;
×
108
            } else {
109
                $this->errorCount   = $cache['errorCount'];
×
110
                $this->warningCount = $cache['warningCount'];
×
111
                $this->fixableCount = $cache['fixableCount'];
×
112
            }
113

114
            if (PHP_CODESNIFFER_VERBOSITY > 0
×
115
                || (PHP_CODESNIFFER_CBF === true && empty($this->config->files) === false)
×
116
            ) {
NEW
117
                StatusWriter::write('[loaded from cache]... ', 0, 0);
×
118
            }
119

120
            $this->numTokens = $cache['numTokens'];
×
121
            $this->fromCache = true;
×
122
            return;
×
123
        }//end if
124

125
        if (PHP_CODESNIFFER_VERBOSITY > 1) {
×
NEW
126
            StatusWriter::writeNewline();
×
127
        }
128

129
        parent::process();
×
130

131
        $cache = [
132
            'hash'         => $hash,
×
133
            'errors'       => $this->errors,
×
134
            'warnings'     => $this->warnings,
×
135
            'metrics'      => $this->metrics,
×
136
            'errorCount'   => $this->errorCount,
×
137
            'warningCount' => $this->warningCount,
×
138
            'fixableCount' => $this->fixableCount,
×
139
            'numTokens'    => $this->numTokens,
×
140
        ];
141

142
        Cache::set($this->path, $cache);
×
143

144
        // During caching, we don't filter out errors in any way, so
145
        // we need to do that manually now by replaying them.
146
        if ($this->configCache['recordErrors'] === true) {
×
147
            $this->configCache['cache'] = false;
×
148
            $this->replayErrors($this->errors, $this->warnings);
×
149
            $this->configCache['cache'] = true;
×
150
        }
151

152
    }//end process()
153

154

155
    /**
156
     * Clears and replays error and warnings for the file.
157
     *
158
     * Replaying errors and warnings allows for filtering rules to be changed
159
     * and then errors and warnings to be reapplied with the new rules. This is
160
     * particularly useful while caching.
161
     *
162
     * @param array $errors   The list of errors to replay.
163
     * @param array $warnings The list of warnings to replay.
164
     *
165
     * @return void
166
     */
167
    private function replayErrors($errors, $warnings)
×
168
    {
169
        $this->errors       = [];
×
170
        $this->warnings     = [];
×
171
        $this->errorCount   = 0;
×
172
        $this->warningCount = 0;
×
173
        $this->fixableCount = 0;
×
174

175
        $this->replayingErrors = true;
×
176

177
        foreach ($errors as $line => $lineErrors) {
×
178
            foreach ($lineErrors as $column => $colErrors) {
×
179
                foreach ($colErrors as $error) {
×
180
                    $this->activeListener = $error['listener'];
×
181
                    $this->addMessage(
×
182
                        true,
×
183
                        $error['message'],
×
184
                        $line,
×
185
                        $column,
×
186
                        $error['source'],
×
187
                        [],
×
188
                        $error['severity'],
×
189
                        $error['fixable']
×
190
                    );
191
                }
192
            }
193
        }
194

195
        foreach ($warnings as $line => $lineErrors) {
×
196
            foreach ($lineErrors as $column => $colErrors) {
×
197
                foreach ($colErrors as $error) {
×
198
                    $this->activeListener = $error['listener'];
×
199
                    $this->addMessage(
×
200
                        false,
×
201
                        $error['message'],
×
202
                        $line,
×
203
                        $column,
×
204
                        $error['source'],
×
205
                        [],
×
206
                        $error['severity'],
×
207
                        $error['fixable']
×
208
                    );
209
                }
210
            }
211
        }
212

213
        $this->replayingErrors = false;
×
214

215
    }//end replayErrors()
216

217

218
}//end class
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc