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

Commit

Permalink
Start with PSR-1 (#1)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
thewilkybarkid authored Aug 30, 2018
1 parent 111701e commit 26d3fec
Show file tree
Hide file tree
Showing 29 changed files with 617 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/*.* export-ignore
/tests export-ignore
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/.phpcs-cache
/composer.lock
/phpcs.xml
/phpunit.xml
/vendor/
42 changes: 42 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
sudo: false

language: php

php:
- 7.2
- nightly

before_install:
- phpenv config-rm xdebug.ini || true
- phpenv config-add .travis/php.ini

install:
- travis_retry composer install --classmap-authoritative --no-suggest --prefer-dist

script:
- vendor/bin/phpunit

jobs:
include:

- stage: Test
env: DEPENDENCIES=low
php: 7.2
install:
- travis_retry composer update --classmap-authoritative --no-suggest --prefer-dist --prefer-lowest --prefer-stable

- stage: Code Quality
env: CODING_STANDARDS
script:
- vendor/bin/phpcs -p

allow_failures:
- php: nightly

cache:
directories:
- $HOME/.composer/cache/files

branches:
only:
- master
1 change: 1 addition & 0 deletions .travis/php.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
short_open_tag = On
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,35 @@
Libero PHP coding standard
==========================

[![Build Status](https://travis-ci.com/libero/php-coding-standard.svg?branch=master)](https://travis-ci.com/libero/php-coding-standard)

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/).

Getting started
---------------

Using [Composer](https://getcomposer.org/) you can install the coding standard into your project:

```
composer require --dev libero/coding-standard
```

You can then find violations of the standard by running:

```
vendor/bin/phpcs --standard=Libero /path/to/some/file/to/sniff.php
```

Or automatically correct (at least some of) these violations by running:

```
vendor/bin/phpcbf --standard=Libero /path/to/some/file/to/sniff.php
```

See the [PHP_CodeSniffer documentation](https://github.com/squizlabs/PHP_CodeSniffer/wiki) for more details.

Getting help
------------

- Report a bug or request a feature on [GitHub](https://github.com/libero/libero/issues/new/choose).
- Ask a question on the [Libero Community Slack](https://libero-community.slack.com/).
30 changes: 30 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "libero/coding-standard",
"description": "Libero PHP coding standard",
"type": "phpcodesniffer-standard",
"license": "MIT",
"autoload-dev": {
"psr-4": {
"tests\\Libero\\CodingStandard\\": "tests/"
}
},
"require": {
"php": "^7.2",
"dealerdirect/phpcodesniffer-composer-installer": "^0.4",
"squizlabs/php_codesniffer": "^3.3"
},
"require-dev": {
"ext-tokenizer": "*",
"lstrojny/functional-php": "^1.8",
"phpunit/phpunit": "^7.3",
"symfony/finder": "^4.1"
},
"config": {
"sort-packages": true
},
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
}
}
21 changes: 21 additions & 0 deletions phpcs.xml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>

<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/squizlabs/php_codesniffer/phpcs.xsd">

<arg name="basepath" value="."/>
<arg name="cache" value=".phpcs-cache"/>
<arg name="colors"/>
<arg name="extensions" value="php"/>
<arg value="s"/>

<rule ref="Libero"/>

<file>src/</file>
<file>tests/</file>

<rule ref="PSR1.Methods.CamelCapsMethodName.NotCamelCaps">
<exclude-pattern>*/tests/*</exclude-pattern>
</rule>

</ruleset>
23 changes: 23 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>

<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/7.3/phpunit.xsd" colors="true"
bootstrap="vendor/autoload.php">

<php>
<const name="PHP_CODESNIFFER_CBF" value="true"/>
</php>

<testsuites>
<testsuite name="Libero Coding Standard">
<directory suffix=".php">tests</directory>
</testsuite>
</testsuites>

<filter>
<whitelist>
<directory>src</directory>
</whitelist>
</filter>

</phpunit>
12 changes: 12 additions & 0 deletions src/Libero/ruleset.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>

<ruleset name="Libero" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../vendor/squizlabs/php_codesniffer/phpcs.xsd">

<description>The Libero coding standard.</description>

<rule ref="PSR1"/>

<rule ref="Squiz.Classes.ClassFileName"/>

</ruleset>
142 changes: 142 additions & 0 deletions tests/RulesetTests.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
<?php

namespace tests\Libero\CodingStandard;

use LogicException;
use ParseError;
use PHP_CodeSniffer\Config;
use PHP_CodeSniffer\Files\DummyFile;
use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Runner;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Finder\Finder;
use function array_combine;
use function array_filter;
use function array_map;
use function explode;
use function Functional\flatten;
use function ini_get;
use function preg_match_all;
use function sort;
use function strpos;
use function token_get_all;
use const TOKEN_PARSE;

final class RulesetTests extends TestCase
{
/** @var Runner */
private static $codeSniffer;

public static function setUpBeforeClass()
{
self::$codeSniffer = new Runner();
self::$codeSniffer->config = new Config(['--standard=Libero']);
self::$codeSniffer->init();
}

/**
* @test
* @dataProvider cases
*/
public function it_finds_and_fixes_violations(
string $filename,
string $contents,
string $fixed,
array $messages,
?string $description
) : void {
$file = $this->createFile($filename, $contents);
$actual = flatten($this->getMessages($file));

sort($actual);
sort($messages);

$this->assertSame($messages, $actual, $description);
$this->assertSame($fixed, $file->fixer->getContents());
}

public function cases() : iterable
{
$files = Finder::create()->files()->in(__DIR__.'/cases');

foreach ($files as $file) {
preg_match_all('~(?:---)?([A-Z]+)---\s+([\s\S]+?)\n---~', $file->getContents(), $matches);

$parts = array_combine(array_map('strtolower', $matches[1]), $matches[2]);

if (isset($parts['messages'])) {
$parts['messages'] = array_filter(explode("\n", $parts['messages']));
}

if (empty($parts['contents'])) {
throw new LogicException("Couldn't find contents in {$file->getRelativePathname()}");
} elseif (empty($parts['fixed']) && empty($parts['messages'])) {
throw new LogicException("Expected one of fixed or messages in {$file->getRelativePathname()}");
}

try {
token_get_all($parts['contents'], TOKEN_PARSE);
} catch (ParseError $exception) {
$message = "Failed to parse content in {$file->getRelativePathname()}: {$exception->getMessage()}";
throw new LogicException($message, 0, $exception);
}

if (!empty($parts['fixed'])) {
try {
token_get_all($parts['fixed'], TOKEN_PARSE);
} catch (ParseError $exception) {
$message = "Failed to parse fixed in {$file->getRelativePathname()}: {$exception->getMessage()}";
throw new LogicException($message, 0, $exception);
}
}

yield $file->getRelativePathname() => [
$parts['filename'] ?? 'test.php',
$parts['contents'],
$parts['fixed'] ?? $parts['contents'],
$parts['messages'] ?? [],
$parts['description'] ?? null,
];
}
}

private function createFile(string $filename, string $content) : File
{
if (!ini_get('short_open_tag') && false === strpos($content, '<?php')) {
$this->markTestSkipped('short_open_tag option is disabled');
}

$file = new DummyFile(
"phpcs_input_file:${filename}\n{$content}",
self::$codeSniffer->ruleset,
self::$codeSniffer->config
);

$file->process();

$file->fixer->fixFile();

$file = new DummyFile(
"phpcs_input_file:${filename}\n{$file->fixer->getContents()}",
self::$codeSniffer->ruleset,
self::$codeSniffer->config
);

$file->process();

return $file;
}

private function getMessages(File $file) : iterable
{
foreach ([$file->getErrors(), $file->getWarnings()] as $messages) {
foreach ($messages as $line => $lineMessages) {
foreach ($lineMessages as $column => $columnMessages) {
foreach ($columnMessages as $data) {
yield "{$line}:{$column} {$data['source']}";
}
}
}
}
}
}
6 changes: 6 additions & 0 deletions tests/bootstrap.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php

namespace tests\Libero\CodingStandard;

require __DIR__.'/../vendor/autoload.php';
require __DIR__.'/../vendor/squizlabs/php_codesniffer/autoload.php';
16 changes: 16 additions & 0 deletions tests/cases/classes/case
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---DESCRIPTION---
Class name must be in camel case
---FILENAME---
foobar.php
---CONTENTS---
<?php

namespace Vendor;

class foobar
{
}

---MESSAGES---
5:1 Squiz.Classes.ValidClassName.NotCamelCaps
---
17 changes: 17 additions & 0 deletions tests/cases/classes/constant-name
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---DESCRIPTION---
Class constants must be in all upper case
---FILENAME---
Foo.php
---CONTENTS---
<?php

namespace Vendor;

class Foo
{
const foo = 'bar';
}

---MESSAGES---
7:11 Generic.NamingConventions.UpperCaseConstantName.ClassConstantNotUpperCase
---
16 changes: 16 additions & 0 deletions tests/cases/classes/file-name
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---DESCRIPTION---
Filename must match class name
---FILENAME---
Foo.php
---CONTENTS---
<?php

namespace Vendor;

class Bar
{
}

---MESSAGES---
5:1 Squiz.Classes.ClassFileName.NoMatch
---
Loading

0 comments on commit 26d3fec

Please sign in to comment.