Skip to content
This repository was archived by the owner on Nov 21, 2019. It is now read-only.

Commit 26d3fec

Browse files
Start with PSR-1 (#1)
* Start with PSR-2 * Set up Travis * Enable short open tags * Not working * Try lowest dependency versions * Try and run separate tasks * XDebug might not be installed * Not sure what happened there * And again * Check file names * Method case * Constant names * Namespaces * Namespace/use blank lines * Property visibility * Method visibility * Start trying to make sure code is actually valid * Invalid PHP * Braces * PHP casing * Back to PSR-1 * More details * Show PHP_CodeSniffer progress * Better name * Use sniff names * Lowest working version for short tags * Match sniff name * Missing one-per-file tests
1 parent 111701e commit 26d3fec

29 files changed

+617
-0
lines changed

.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/*.* export-ignore
2+
/tests export-ignore

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/.phpcs-cache
2+
/composer.lock
3+
/phpcs.xml
4+
/phpunit.xml
5+
/vendor/

.travis.yml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
sudo: false
2+
3+
language: php
4+
5+
php:
6+
- 7.2
7+
- nightly
8+
9+
before_install:
10+
- phpenv config-rm xdebug.ini || true
11+
- phpenv config-add .travis/php.ini
12+
13+
install:
14+
- travis_retry composer install --classmap-authoritative --no-suggest --prefer-dist
15+
16+
script:
17+
- vendor/bin/phpunit
18+
19+
jobs:
20+
include:
21+
22+
- stage: Test
23+
env: DEPENDENCIES=low
24+
php: 7.2
25+
install:
26+
- travis_retry composer update --classmap-authoritative --no-suggest --prefer-dist --prefer-lowest --prefer-stable
27+
28+
- stage: Code Quality
29+
env: CODING_STANDARDS
30+
script:
31+
- vendor/bin/phpcs -p
32+
33+
allow_failures:
34+
- php: nightly
35+
36+
cache:
37+
directories:
38+
- $HOME/.composer/cache/files
39+
40+
branches:
41+
only:
42+
- master

.travis/php.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
short_open_tag = On

README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,35 @@
11
Libero PHP coding standard
22
==========================
3+
4+
[![Build Status](https://travis-ci.com/libero/php-coding-standard.svg?branch=master)](https://travis-ci.com/libero/php-coding-standard)
5+
6+
The Libero PHP coding standard is a set of [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) rules applied to all Libero PHP projects. It is based on [PSR-1](https://www.php-fig.org/psr/psr-1/).
7+
8+
Getting started
9+
---------------
10+
11+
Using [Composer](https://getcomposer.org/) you can install the coding standard into your project:
12+
13+
```
14+
composer require --dev libero/coding-standard
15+
```
16+
17+
You can then find violations of the standard by running:
18+
19+
```
20+
vendor/bin/phpcs --standard=Libero /path/to/some/file/to/sniff.php
21+
```
22+
23+
Or automatically correct (at least some of) these violations by running:
24+
25+
```
26+
vendor/bin/phpcbf --standard=Libero /path/to/some/file/to/sniff.php
27+
```
28+
29+
See the [PHP_CodeSniffer documentation](https://github.com/squizlabs/PHP_CodeSniffer/wiki) for more details.
30+
31+
Getting help
32+
------------
33+
34+
- Report a bug or request a feature on [GitHub](https://github.com/libero/libero/issues/new/choose).
35+
- Ask a question on the [Libero Community Slack](https://libero-community.slack.com/).

composer.json

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"name": "libero/coding-standard",
3+
"description": "Libero PHP coding standard",
4+
"type": "phpcodesniffer-standard",
5+
"license": "MIT",
6+
"autoload-dev": {
7+
"psr-4": {
8+
"tests\\Libero\\CodingStandard\\": "tests/"
9+
}
10+
},
11+
"require": {
12+
"php": "^7.2",
13+
"dealerdirect/phpcodesniffer-composer-installer": "^0.4",
14+
"squizlabs/php_codesniffer": "^3.3"
15+
},
16+
"require-dev": {
17+
"ext-tokenizer": "*",
18+
"lstrojny/functional-php": "^1.8",
19+
"phpunit/phpunit": "^7.3",
20+
"symfony/finder": "^4.1"
21+
},
22+
"config": {
23+
"sort-packages": true
24+
},
25+
"extra": {
26+
"branch-alias": {
27+
"dev-master": "1.0.x-dev"
28+
}
29+
}
30+
}

phpcs.xml.dist

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:noNamespaceSchemaLocation="vendor/squizlabs/php_codesniffer/phpcs.xsd">
5+
6+
<arg name="basepath" value="."/>
7+
<arg name="cache" value=".phpcs-cache"/>
8+
<arg name="colors"/>
9+
<arg name="extensions" value="php"/>
10+
<arg value="s"/>
11+
12+
<rule ref="Libero"/>
13+
14+
<file>src/</file>
15+
<file>tests/</file>
16+
17+
<rule ref="PSR1.Methods.CamelCapsMethodName.NotCamelCaps">
18+
<exclude-pattern>*/tests/*</exclude-pattern>
19+
</rule>
20+
21+
</ruleset>

phpunit.xml.dist

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/7.3/phpunit.xsd" colors="true"
5+
bootstrap="vendor/autoload.php">
6+
7+
<php>
8+
<const name="PHP_CODESNIFFER_CBF" value="true"/>
9+
</php>
10+
11+
<testsuites>
12+
<testsuite name="Libero Coding Standard">
13+
<directory suffix=".php">tests</directory>
14+
</testsuite>
15+
</testsuites>
16+
17+
<filter>
18+
<whitelist>
19+
<directory>src</directory>
20+
</whitelist>
21+
</filter>
22+
23+
</phpunit>

src/Libero/ruleset.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<ruleset name="Libero" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:noNamespaceSchemaLocation="../../vendor/squizlabs/php_codesniffer/phpcs.xsd">
5+
6+
<description>The Libero coding standard.</description>
7+
8+
<rule ref="PSR1"/>
9+
10+
<rule ref="Squiz.Classes.ClassFileName"/>
11+
12+
</ruleset>

tests/RulesetTests.php

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
<?php
2+
3+
namespace tests\Libero\CodingStandard;
4+
5+
use LogicException;
6+
use ParseError;
7+
use PHP_CodeSniffer\Config;
8+
use PHP_CodeSniffer\Files\DummyFile;
9+
use PHP_CodeSniffer\Files\File;
10+
use PHP_CodeSniffer\Runner;
11+
use PHPUnit\Framework\TestCase;
12+
use Symfony\Component\Finder\Finder;
13+
use function array_combine;
14+
use function array_filter;
15+
use function array_map;
16+
use function explode;
17+
use function Functional\flatten;
18+
use function ini_get;
19+
use function preg_match_all;
20+
use function sort;
21+
use function strpos;
22+
use function token_get_all;
23+
use const TOKEN_PARSE;
24+
25+
final class RulesetTests extends TestCase
26+
{
27+
/** @var Runner */
28+
private static $codeSniffer;
29+
30+
public static function setUpBeforeClass()
31+
{
32+
self::$codeSniffer = new Runner();
33+
self::$codeSniffer->config = new Config(['--standard=Libero']);
34+
self::$codeSniffer->init();
35+
}
36+
37+
/**
38+
* @test
39+
* @dataProvider cases
40+
*/
41+
public function it_finds_and_fixes_violations(
42+
string $filename,
43+
string $contents,
44+
string $fixed,
45+
array $messages,
46+
?string $description
47+
) : void {
48+
$file = $this->createFile($filename, $contents);
49+
$actual = flatten($this->getMessages($file));
50+
51+
sort($actual);
52+
sort($messages);
53+
54+
$this->assertSame($messages, $actual, $description);
55+
$this->assertSame($fixed, $file->fixer->getContents());
56+
}
57+
58+
public function cases() : iterable
59+
{
60+
$files = Finder::create()->files()->in(__DIR__.'/cases');
61+
62+
foreach ($files as $file) {
63+
preg_match_all('~(?:---)?([A-Z]+)---\s+([\s\S]+?)\n---~', $file->getContents(), $matches);
64+
65+
$parts = array_combine(array_map('strtolower', $matches[1]), $matches[2]);
66+
67+
if (isset($parts['messages'])) {
68+
$parts['messages'] = array_filter(explode("\n", $parts['messages']));
69+
}
70+
71+
if (empty($parts['contents'])) {
72+
throw new LogicException("Couldn't find contents in {$file->getRelativePathname()}");
73+
} elseif (empty($parts['fixed']) && empty($parts['messages'])) {
74+
throw new LogicException("Expected one of fixed or messages in {$file->getRelativePathname()}");
75+
}
76+
77+
try {
78+
token_get_all($parts['contents'], TOKEN_PARSE);
79+
} catch (ParseError $exception) {
80+
$message = "Failed to parse content in {$file->getRelativePathname()}: {$exception->getMessage()}";
81+
throw new LogicException($message, 0, $exception);
82+
}
83+
84+
if (!empty($parts['fixed'])) {
85+
try {
86+
token_get_all($parts['fixed'], TOKEN_PARSE);
87+
} catch (ParseError $exception) {
88+
$message = "Failed to parse fixed in {$file->getRelativePathname()}: {$exception->getMessage()}";
89+
throw new LogicException($message, 0, $exception);
90+
}
91+
}
92+
93+
yield $file->getRelativePathname() => [
94+
$parts['filename'] ?? 'test.php',
95+
$parts['contents'],
96+
$parts['fixed'] ?? $parts['contents'],
97+
$parts['messages'] ?? [],
98+
$parts['description'] ?? null,
99+
];
100+
}
101+
}
102+
103+
private function createFile(string $filename, string $content) : File
104+
{
105+
if (!ini_get('short_open_tag') && false === strpos($content, '<?php')) {
106+
$this->markTestSkipped('short_open_tag option is disabled');
107+
}
108+
109+
$file = new DummyFile(
110+
"phpcs_input_file:${filename}\n{$content}",
111+
self::$codeSniffer->ruleset,
112+
self::$codeSniffer->config
113+
);
114+
115+
$file->process();
116+
117+
$file->fixer->fixFile();
118+
119+
$file = new DummyFile(
120+
"phpcs_input_file:${filename}\n{$file->fixer->getContents()}",
121+
self::$codeSniffer->ruleset,
122+
self::$codeSniffer->config
123+
);
124+
125+
$file->process();
126+
127+
return $file;
128+
}
129+
130+
private function getMessages(File $file) : iterable
131+
{
132+
foreach ([$file->getErrors(), $file->getWarnings()] as $messages) {
133+
foreach ($messages as $line => $lineMessages) {
134+
foreach ($lineMessages as $column => $columnMessages) {
135+
foreach ($columnMessages as $data) {
136+
yield "{$line}:{$column} {$data['source']}";
137+
}
138+
}
139+
}
140+
}
141+
}
142+
}

0 commit comments

Comments
 (0)