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

PHPCSStandards / PHP_CodeSniffer / 15114979259

19 May 2025 01:58PM UTC coverage: 78.674% (+0.04%) from 78.632%
15114979259

Pull #880

github

web-flow
Merge 17601e27d into ad852ee16
Pull Request #880: Generic/InlineControlStructure: bail early for control structures without body

48 of 48 new or added lines in 1 file covered. (100.0%)

1 existing line in 1 file now uncovered.

19663 of 24993 relevant lines covered (78.67%)

88.73 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->fixableErrorCount   = $cache['fixableErrorCount'];
×
112
                $this->fixableWarningCount = $cache['fixableWarningCount'];
×
113
            }
114

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

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

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

130
        parent::process();
×
131

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

144
        Cache::set($this->path, $cache);
×
145

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

154
    }//end process()
155

156

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

178
        $this->replayingErrors = true;
×
179

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

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

216
        $this->replayingErrors = false;
×
217

218
    }//end replayErrors()
219

220

221
}//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

© 2026 Coveralls, Inc