Skip to content

Commit 371df28

Browse files
committed
Generic DuplicateClassNameSniff is no longer a multi-file sniff, so it won't max out your memory
1 parent f25f73d commit 371df28

File tree

3 files changed

+71
-90
lines changed

3 files changed

+71
-90
lines changed

CodeSniffer/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.php

Lines changed: 65 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -23,71 +23,86 @@
2323
* @version Release: @package_version@
2424
* @link http://pear.php.net/package/PHP_CodeSniffer
2525
*/
26-
class Generic_Sniffs_Classes_DuplicateClassNameSniff implements PHP_CodeSniffer_MultiFileSniff
26+
class Generic_Sniffs_Classes_DuplicateClassNameSniff implements PHP_CodeSniffer_Sniff
2727
{
2828

29+
/**
30+
* List of classes that have been found during checking.
31+
*
32+
* @var array
33+
*/
34+
public $foundClasses = array();
35+
36+
37+
/**
38+
* Registers the tokens that this sniff wants to listen for.
39+
*
40+
* @return array(integer)
41+
*/
42+
public function register()
43+
{
44+
return array(T_OPEN_TAG);
45+
46+
}//end register()
47+
2948

3049
/**
31-
* Called once per script run to allow for processing of this sniff.
50+
* Processes this test, when one of its tokens is encountered.
3251
*
33-
* @param array(PHP_CodeSniffer_File) $files The PHP_CodeSniffer files processed
34-
* during the script run.
52+
* @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
53+
* @param int $stackPtr The position of the current token
54+
* in the stack passed in $tokens.
3555
*
3656
* @return void
3757
*/
38-
public function process(array $files)
58+
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
3959
{
40-
$foundClasses = array();
60+
$tokens = $phpcsFile->getTokens();
4161

42-
foreach ($files as $phpcsFile) {
43-
$tokens = $phpcsFile->getTokens();
62+
$namespace = '';
63+
$stackPtr = $phpcsFile->findNext(array(T_CLASS, T_INTERFACE, T_NAMESPACE), 0);
64+
while ($stackPtr !== false) {
65+
// Keep track of what namespace we are in.
66+
if ($tokens[$stackPtr]['code'] === T_NAMESPACE) {
67+
$nsEnd = $phpcsFile->findNext(
68+
array(T_NS_SEPARATOR, T_STRING, T_WHITESPACE),
69+
($stackPtr + 1),
70+
null,
71+
true
72+
);
4473

45-
$namespace = '';
46-
$stackPtr = $phpcsFile->findNext(array(T_CLASS, T_INTERFACE, T_NAMESPACE), 0);
47-
while ($stackPtr !== false) {
48-
// Keep track of what namespace we are in.
49-
if ($tokens[$stackPtr]['code'] === T_NAMESPACE) {
50-
$nsEnd = $phpcsFile->findNext(
51-
array(T_NS_SEPARATOR, T_STRING, T_WHITESPACE),
52-
($stackPtr + 1),
53-
null,
54-
true
55-
);
74+
$namespace = trim($phpcsFile->getTokensAsString(($stackPtr + 1), ($nsEnd - $stackPtr - 1)));
75+
$stackPtr = $nsEnd;
76+
} else {
77+
$nameToken = $phpcsFile->findNext(T_STRING, $stackPtr);
78+
$name = $tokens[$nameToken]['content'];
79+
if ($namespace !== '') {
80+
$name = $namespace.'\\'.$name;
81+
}
5682

57-
$namespace = trim($phpcsFile->getTokensAsString(($stackPtr + 1), ($nsEnd - $stackPtr - 1)));
58-
$stackPtr = $nsEnd;
83+
$compareName = strtolower($name);
84+
if (isset($this->foundClasses[$compareName]) === true) {
85+
$type = strtolower($tokens[$stackPtr]['content']);
86+
$file = $this->foundClasses[$compareName]['file'];
87+
$line = $this->foundClasses[$compareName]['line'];
88+
$error = 'Duplicate %s name "%s" found; first defined in %s on line %s';
89+
$data = array(
90+
$type,
91+
$name,
92+
$file,
93+
$line,
94+
);
95+
$phpcsFile->addWarning($error, $stackPtr, 'Found', $data);
5996
} else {
60-
$nameToken = $phpcsFile->findNext(T_STRING, $stackPtr);
61-
$name = $tokens[$nameToken]['content'];
62-
if ($namespace !== '') {
63-
$name = $namespace.'\\'.$name;
64-
}
65-
66-
$compareName = strtolower($name);
67-
if (isset($foundClasses[$compareName]) === true) {
68-
$type = strtolower($tokens[$stackPtr]['content']);
69-
$file = $foundClasses[$compareName]['file'];
70-
$line = $foundClasses[$compareName]['line'];
71-
$error = 'Duplicate %s name "%s" found; first defined in %s on line %s';
72-
$data = array(
73-
$type,
74-
$name,
75-
$file,
76-
$line,
77-
);
78-
$phpcsFile->addWarning($error, $stackPtr, 'Found', $data);
79-
} else {
80-
$foundClasses[$compareName] = array(
81-
'file' => $phpcsFile->getFilename(),
82-
'line' => $tokens[$stackPtr]['line'],
83-
);
84-
}
97+
$this->foundClasses[$compareName] = array(
98+
'file' => $phpcsFile->getFilename(),
99+
'line' => $tokens[$stackPtr]['line'],
100+
);
85101
}
102+
}
86103

87-
$stackPtr = $phpcsFile->findNext(array(T_CLASS, T_INTERFACE, T_NAMESPACE), ($stackPtr + 1));
88-
}//end while
89-
90-
}//end foreach
104+
$stackPtr = $phpcsFile->findNext(array(T_CLASS, T_INTERFACE, T_NAMESPACE), ($stackPtr + 1));
105+
}//end while
91106

92107
}//end process()
93108

package.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
4040
- Sniffs inside PHP 5.3 namespaces are now supported, along with the existing underscore-style emulated namespaces
4141
-- For example: namespace MyStandard\Sniffs\Arrays; class ArrayDeclarationSniff implements \PHP_CodeSniffer_Sniff { ...
4242
-- Thanks to Till Klampaeckel for the patch
43+
- Generic DuplicateClassNameSniff is no longer a multi-file sniff, so it won't max out your memory
44+
-- Multi-file sniff support should be considered deprecated as standard sniffs can now do the same thing
4345
- Added Generic DisallowSpaceIndent to check that files are indented using tabs
4446
- Added Generic OneClassPerFileSniff to check that only one class is defined in each file
4547
-- Thanks to Andy Grunwald for the contribution

tests/Standards/AbstractSniffUnitTest.php

Lines changed: 4 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -116,31 +116,20 @@ protected final function runTest()
116116
}
117117
}
118118

119-
// Get them in order. This is particularly important for multi-file sniffs.
119+
// Get them in order.
120120
sort($testFiles);
121121

122+
self::$phpcs->process(array(), $standardName, array($sniffClass));
123+
self::$phpcs->setIgnorePatterns(array());
124+
122125
$failureMessages = array();
123-
$multiFileSniff = false;
124126
foreach ($testFiles as $testFile) {
125127
try {
126-
self::$phpcs->process(array(), $standardName, array($sniffClass));
127-
self::$phpcs->setIgnorePatterns(array());
128128
self::$phpcs->processFile($testFile);
129-
self::$phpcs->processMulti();
130129
} catch (Exception $e) {
131130
$this->fail('An unexpected exception has been caught: '.$e->getMessage());
132131
}
133132

134-
// After processing a file, check if the sniff was actually
135-
// a multi-file sniff (i.e., had no individual file sniffs).
136-
// If it is, we can skip checking of the other files and
137-
// do a single multi-file check.
138-
$sniffs = self::$phpcs->getTokenSniffs();
139-
if (empty($sniffs['file']) === true) {
140-
$multiFileSniff = true;
141-
break;
142-
}
143-
144133
$files = self::$phpcs->getFiles();
145134
if (empty($files) === true) {
146135
// File was skipped for some reason.
@@ -154,31 +143,6 @@ protected final function runTest()
154143
$failureMessages = array_merge($failureMessages, $failures);
155144
}//end foreach
156145

157-
if ($multiFileSniff === true) {
158-
try {
159-
self::$phpcs->process(array(), $standardName, array($sniffClass));
160-
self::$phpcs->setIgnorePatterns(array());
161-
foreach ($testFiles as $testFile) {
162-
self::$phpcs->processFile($testFile);
163-
}
164-
165-
self::$phpcs->processMulti();
166-
} catch (Exception $e) {
167-
$this->fail('An unexpected exception has been caught: '.$e->getMessage());
168-
}
169-
170-
$files = self::$phpcs->getFiles();
171-
if (empty($files) === true) {
172-
// File was skipped for some reason.
173-
$this->markTestSkipped();
174-
} else {
175-
foreach ($files as $file) {
176-
$failures = $this->generateFailureMessages($file);
177-
$failureMessages = array_merge($failureMessages, $failures);
178-
}
179-
}
180-
}//end if
181-
182146
if (empty($failureMessages) === false) {
183147
$this->fail(implode(PHP_EOL, $failureMessages));
184148
}

0 commit comments

Comments
 (0)