Skip to content

Commit 8e1fc14

Browse files
authored
Merge pull request #61 from andrewnicols/noLeadingBackslash
Check namespaces and class imports for leading backslash
2 parents 5f76734 + e3dae34 commit 8e1fc14

File tree

11 files changed

+203
-45
lines changed

11 files changed

+203
-45
lines changed

.phplint.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ path: ./
22
exclude:
33
- vendor
44
- moodle/Tests/fixtures
5+
- moodle/Tests/Sniffs/Namespaces/fixtures
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
// This file is part of Moodle - http://moodle.org/
3+
//
4+
// Moodle is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// Moodle is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License
15+
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16+
17+
/**
18+
* Checks that each file contains the standard GPL comment.
19+
*
20+
* @package moodle-cs
21+
* @copyright 2023 Andrew Lyons <[email protected]>
22+
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23+
*/
24+
25+
namespace MoodleHQ\MoodleCS\moodle\Sniffs\Namespaces;
26+
27+
use PHP_CodeSniffer\Sniffs\Sniff;
28+
use PHP_CodeSniffer\Files\File;
29+
use PHP_CodeSniffer\Util\Tokens;
30+
31+
// phpcs:disable moodle.NamingConventions
32+
33+
class NamespaceStatementSniff implements Sniff {
34+
public function register()
35+
{
36+
return [
37+
T_NAMESPACE,
38+
];
39+
}
40+
41+
public function process(File $file, $stackPtr)
42+
{
43+
$tokens = $file->getTokens();
44+
// Format should be:
45+
// - T_NAMESPACE
46+
// - T_WHITESPACE
47+
// - T_STRING
48+
49+
$checkPtr = $stackPtr + 2;
50+
$token = $tokens[$checkPtr];
51+
if ($token['code'] === T_NS_SEPARATOR) {
52+
$fqdn = '';
53+
$stop = $file->findNext(Tokens::$emptyTokens, ($stackPtr + 2));
54+
for ($i = $stackPtr + 2; $i < $stop; $i++) {
55+
$fqdn .= $tokens[$i]['content'];
56+
}
57+
$fix = $file->addFixableError(
58+
'Namespace should not start with a slash: %s',
59+
$checkPtr,
60+
'LeadingSlash',
61+
[$fqdn]
62+
);
63+
64+
if ($fix) {
65+
$file->fixer->beginChangeset();
66+
$file->fixer->replaceToken($checkPtr, '');
67+
$file->fixer->endChangeset();
68+
}
69+
}
70+
}
71+
}

moodle/Tests/MoodleCSBaseTestCase.php

Lines changed: 10 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -80,53 +80,18 @@ public function set_component_mapping(array $mapping): void {
8080
*
8181
* @param string $standard name of the standard to be tested.
8282
*/
83-
protected function set_standard($standard) {
84-
$installedStandards = \PHP_CodeSniffer\Util\Standards::getInstalledStandardDetails();
85-
86-
foreach (array_keys($installedStandards) as $standard) {
87-
if (\PHP_CodeSniffer\Util\Standards::isInstalledStandard($standard) === false) {
88-
// They didn't select a valid coding standard, so help them
89-
// out by letting them know which standards are installed.
90-
$error = 'ERROR: the "'.$standard.'" coding standard is not installed. ';
91-
ob_start();
92-
\PHP_CodeSniffer\Util\Standards::printInstalledStandards();
93-
$error .= ob_get_contents();
94-
ob_end_clean();
95-
throw new \PHP_CodeSniffer\Exceptions\DeepExitException($error, 3);
96-
}
83+
protected function set_standard(string$standard) {
84+
if (\PHP_CodeSniffer\Util\Standards::isInstalledStandard($standard) === false) {
85+
// They didn't select a valid coding standard, so help them
86+
// out by letting them know which standards are installed.
87+
$error = "ERROR: the '{$standard}' coding standard is not installed.\n";
88+
ob_start();
89+
\PHP_CodeSniffer\Util\Standards::printInstalledStandards();
90+
$error .= ob_get_contents();
91+
ob_end_clean();
92+
throw new \PHP_CodeSniffer\Exceptions\DeepExitException($error, 3);
9793
}
9894
$this->standard = $standard;
99-
return;
100-
// Since 2.9 arbitrary standard directories are not allowed by default,
101-
// only those under the CodeSniffer/Standards dir are detected. Other base
102-
// dirs containing standards can be added using CodeSniffer.conf or the
103-
// PHP_CODESNIFFER_CONFIG_DATA global (installed_paths setting).
104-
// We are using the global way here to avoid changes in the phpcs import.
105-
// phpcs:disable
106-
if (!isset($GLOBALS['PHP_CODESNIFFER_CONFIG_DATA']['installed_paths'])) {
107-
$localcodecheckerpath = realpath(__DIR__ . '/../');
108-
$GLOBALS['PHP_CODESNIFFER_CONFIG_DATA'] = ['installed_paths' => $localcodecheckerpath];
109-
}
110-
// phpcs:enable
111-
112-
// Basic search of standards in the allowed directories.
113-
$stdsearch = array(
114-
__DIR__ . '/../phpcs/src/Standards', // PHPCS standards dir.
115-
__DIR__ . '/..', // Plugin local_codechecker dir, allowed above via global.
116-
);
117-
118-
foreach ($stdsearch as $stdpath) {
119-
$stdpath = realpath($stdpath . '/' . $standard);
120-
$stdfile = $stdpath . '/ruleset.xml';
121-
if (file_exists($stdfile)) {
122-
$this->standard = $stdpath; // Need to pass the path here.
123-
break;
124-
}
125-
}
126-
// Standard not found, fail.
127-
if ($this->standard === null) {
128-
$this->fail('Standard "' . $standard . '" not found.');
129-
}
13095
}
13196

13297
/**
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
// This file is part of Moodle - http://moodle.org/
3+
//
4+
// Moodle is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// Moodle is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License
15+
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16+
17+
namespace MoodleHQ\MoodleCS\moodle\Tests\Sniffs\Namespaces;
18+
19+
use MoodleHQ\MoodleCS\moodle\Tests\MoodleCSBaseTestCase;
20+
21+
// phpcs:disable moodle.NamingConventions
22+
23+
/**
24+
* Test the NoLeadingSlash sniff.
25+
*
26+
* @package moodle-cs
27+
* @category test
28+
* @copyright 2023 Andrew Lyons <[email protected]>
29+
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
30+
*
31+
* @covers \MoodleHQ\MoodleCS\moodle\Sniffs\Namespaces\NoLeadingSlashSniff
32+
*/
33+
class NamespaceStatementSniffTest extends MoodleCSBaseTestCase
34+
{
35+
public static function leading_slash_provider(): array
36+
{
37+
return [
38+
[
39+
'fixture' => 'correct_namespace',
40+
'warnings' => [],
41+
'errors' => [],
42+
],
43+
[
44+
'fixture' => 'leading_backslash',
45+
'warnings' => [],
46+
'errors' => [
47+
3 => 'Namespace should not start with a slash: \MoodleHQ\MoodleCS\moodle\Tests\Sniffs\Namespaces',
48+
],
49+
],
50+
[
51+
'fixture' => 'curly_namespace',
52+
'warnings' => [],
53+
'errors' => [
54+
3 => 'Namespace should not start with a slash: \MoodleHQ\MoodleCS\moodle\Tests\Sniffs\Namespaces',
55+
],
56+
],
57+
];
58+
}
59+
/**
60+
* @dataProvider leading_slash_provider
61+
*/
62+
public function test_leading_slash(
63+
string $fixture,
64+
array $warnings,
65+
array $errors
66+
): void
67+
{
68+
$this->set_standard('moodle');
69+
$this->set_sniff('moodle.Namespaces.NamespaceStatement');
70+
$this->set_fixture(sprintf("%s/fixtures/%s.php", __DIR__, $fixture));
71+
$this->set_warnings($warnings);
72+
$this->set_errors($errors);
73+
74+
$this->verify_cs_results();
75+
}
76+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace MoodleHQ\MoodleCS\moodle\Tests\Sniffs\Namespaces;
4+
5+
defined('MOODLE_INTERNAL') || die(); // Make this always the 1st line in all CS fixtures.
6+
7+
class correct_test extends base_test {
8+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php
2+
3+
namespace \MoodleHQ\MoodleCS\moodle\Tests\Sniffs\Namespaces {
4+
class leading_backslash {}
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php
2+
3+
namespace MoodleHQ\MoodleCS\moodle\Tests\Sniffs\Namespaces {
4+
class leading_backslash {}
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php
2+
3+
namespace MoodleHQ\MoodleCS\moodle\Tests\Sniffs\Namespaces {
4+
class leading_backslash {}
5+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace \MoodleHQ\MoodleCS\moodle\Tests\Sniffs\Namespaces;
4+
5+
defined('MOODLE_INTERNAL') || die(); // Make this always the 1st line in all CS fixtures.
6+
7+
class leading_backslash extends base_test {
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace MoodleHQ\MoodleCS\moodle\Tests\Sniffs\Namespaces;
4+
5+
defined('MOODLE_INTERNAL') || die(); // Make this always the 1st line in all CS fixtures.
6+
7+
class leading_backslash extends base_test {
8+
}

0 commit comments

Comments
 (0)