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

PHPCSStandards / PHP_CodeSniffer / 13887072476

16 Mar 2025 08:25PM UTC coverage: 78.682%. Remained the same
13887072476

Pull #882

github

web-flow
Merge 9fd6cc2aa into 384f8e824
Pull Request #882: Ruleset: add tests to document trimming behaviour

24832 of 31560 relevant lines covered (78.68%)

66.33 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

17
class LocalFile extends File
18
{
19

20

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

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

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

61
        $this->reloadContent();
×
62

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

65
    }//end __construct()
66

67

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

77
    }//end reloadContent()
78

79

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

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

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

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

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

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

126
        if (PHP_CODESNIFFER_VERBOSITY > 1) {
×
127
            echo PHP_EOL;
×
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
            'fixableCount' => $this->fixableCount,
×
140
            'numTokens'    => $this->numTokens,
×
141
        ];
142

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

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

153
    }//end process()
154

155

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

176
        $this->replayingErrors = true;
×
177

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

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

214
        $this->replayingErrors = false;
×
215

216
    }//end replayErrors()
217

218

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