Skip to content

Instantly share code, notes, and snippets.

@jakubkulhan
Last active October 10, 2018 06:43
Show Gist options
  • Save jakubkulhan/b054b89cb207822fcb71 to your computer and use it in GitHub Desktop.
Save jakubkulhan/b054b89cb207822fcb71 to your computer and use it in GitHub Desktop.
Skrz Coding Standard
<?php
class Skrz_Sniffs_Classes_ClassDeclarationSniff implements PHP_CodeSniffer_Sniff
{
public function register()
{
return [T_CLASS, T_INTERFACE, T_TRAIT];
}
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
if (!isset($tokens[$stackPtr]["scope_opener"]) || !isset($tokens[$stackPtr]["scope_closer"])) {
$phpcsFile->addWarning("Possible parse error: missing opening or closing brace", $stackPtr);
return;
}
$scopeOpenerPtr = $tokens[$stackPtr]["scope_opener"];
$scopeCloserPtr = $tokens[$stackPtr]["scope_closer"];
$emptyClassBody = true;
$openingContent = "";
$firstNonWhitespacePtr = null;
for ($i = $scopeOpenerPtr + 1; $i < $scopeCloserPtr; ++$i) {
if ($tokens[$i]["code"] !== T_WHITESPACE) {
$emptyClassBody = false;
$firstNonWhitespacePtr = $i;
break;
} else {
$openingContent .= $tokens[$i]["content"];
}
}
if ($emptyClassBody) {
if ($openingContent !== $phpcsFile->eolChar) {
$fix = $phpcsFile->addFixableError("Empty class body should not contain empty lines.", $stackPtr);
if ($fix) {
$phpcsFile->fixer->beginChangeset();
for ($i = $scopeOpenerPtr + 1; $i < $scopeCloserPtr; ++$i) {
$phpcsFile->fixer->replaceToken($i, "");
}
$phpcsFile->fixer->addNewline($scopeOpenerPtr);
$phpcsFile->fixer->endChangeset();
}
}
return;
}
$closingContent = "";
$lastNonWhitespacePtr = null;
for ($i = $scopeCloserPtr - 1; $i >= $scopeOpenerPtr; --$i) {
if ($tokens[$i]["code"] !== T_WHITESPACE) {
$lastNonWhitespacePtr = $i;
break;
} else {
$closingContent .= $tokens[$i]["content"];
}
}
$openingNewlines = substr_count($openingContent, $phpcsFile->eolChar);
$closingNewlines = substr_count($closingContent, $phpcsFile->eolChar);
if ($openingNewlines < 2) {
$fix = $phpcsFile->addFixableError("There should be an empty line after class opening brace.", $scopeOpenerPtr);
if ($fix) {
$phpcsFile->fixer->addNewline($scopeOpenerPtr);
}
} elseif ($openingNewlines > 2) {
$fix = $phpcsFile->addFixableError("There should be just one empty line after class opening brace.", $scopeOpenerPtr);
if ($fix) {
$phpcsFile->fixer->beginChangeset();
for ($i = $scopeOpenerPtr + 1; $i < $firstNonWhitespacePtr; ++$i) {
$phpcsFile->fixer->replaceToken($i, str_replace($phpcsFile->eolChar, "", $tokens[$i]["content"]));
}
$phpcsFile->fixer->addNewline($scopeOpenerPtr);
$phpcsFile->fixer->endChangeset();
}
}
if ($closingNewlines < 2) {
$fix = $phpcsFile->addFixableError("There should be an empty line before class closing brace.", $scopeCloserPtr);
if ($fix) {
$phpcsFile->fixer->addNewlineBefore($scopeCloserPtr);
}
} elseif ($closingNewlines > 2) {
$fix = $phpcsFile->addFixableError("There should be just one empty line after class closing brace.", $scopeCloserPtr);
if ($fix) {
$phpcsFile->fixer->beginChangeset();
for ($i = $lastNonWhitespacePtr + 1; $i < $scopeCloserPtr; ++$i) {
$phpcsFile->fixer->replaceToken($i, "");
}
$phpcsFile->fixer->addNewlineBefore($scopeCloserPtr);
$phpcsFile->fixer->endChangeset();
}
}
}
}
<?php
class Skrz_Sniffs_Commenting_DisallowHashCommentsSniff implements PHP_CodeSniffer_Sniff
{
public function register()
{
return [T_COMMENT];
}
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
$content = $tokens[$stackPtr]["content"];
if (strncmp($content, "#", 1) === 0) {
$fix = $phpcsFile->addFixableError("Hash comments are prohibited", $stackPtr);
if ($fix) {
$phpcsFile->fixer->replaceToken($stackPtr, "//" . substr($content, 1));
}
}
}
}
<?php
class Skrz_Sniffs_Namespaces_NamespaceDeclarationSniff implements PHP_CodeSniffer_Sniff
{
public function register()
{
return [T_NAMESPACE];
}
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
$openTagPtr = $phpcsFile->findPrevious(T_OPEN_TAG, $stackPtr);
if ($openTagPtr !== 0 || $tokens[$openTagPtr]["content"] !== "<?php\n") {
$phpcsFile->addErrorOnLine("PHP file has to start with open tag '<?php'.", 0);
}
$total = 0;
$whitespaces = 0;
for ($i = $openTagPtr + 1; $i < $stackPtr; ++$i) {
++$total;
if ($tokens[$i]["code"] === T_WHITESPACE) {
++$whitespaces;
}
}
if ($total < 1) {
return;
}
if ($whitespaces < $total) {
$phpcsFile->addError(
"Namespace declaration should immediately follow open tag '<?php'. " .
"Other tokens beside whitespaces, cannot fix automatically.",
$stackPtr
);
return;
}
$fix = $phpcsFile->addFixableError(
"Namespace declaration should immediately follow open tag '<?php'.",
$stackPtr
);
if ($fix) {
$phpcsFile->fixer->beginChangeset();
for ($i = $openTagPtr + 1; $i < $stackPtr; ++$i) {
$phpcsFile->fixer->replaceToken($i, "");
}
$phpcsFile->fixer->endChangeset();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<ruleset name="Skrz">
<description>Skrz Coding Standard</description>
<exclude-pattern>*/vendor/*</exclude-pattern>
<rule ref="PSR2">
<exclude name="Generic.WhiteSpace.DisallowTabIndent"/>
<!--
This is silly check, because of inability to pass null for type-hinted object parameters w/o null as default value.
public function findCategorySubtree(Category $category = null, array $categoryIds)
{
// null category means whole tree
}
-->
<exclude name="PEAR.Functions.ValidDefaultValue"/>
</rule>
<!--
Contradicts Skrz.Classes.ClassDeclaration.
-->
<rule ref="PSR2.Classes.ClassDeclaration.CloseBraceAfterBody">
<severity>0</severity>
</rule>
<rule ref="Generic.WhiteSpace.DisallowSpaceIndent"/>
<!--
Checks that there is a new line after class opening brace and before class closing brace.
class Foo
{
// class body
// ...
}
Classes with no constants/properties/methdods must have opening brace immediately followed by closing brace.
class FooException extends \Exception
{
}
-->
<rule ref="./ClassDeclarationSniff.php"/>
<!--
Disallows '#' comments. Replaces them with '//' comments.
-->
<rule ref="./DisallowHashCommentsSniff.php"/>
<!--
Namespace declaration has to immediately follow PHP open tag - '<?php'.
<?php
namespace Skrz\Bundle\AutowiringBundle;
-->
<rule ref="./NamespaceDeclarationSniff.php"/>
</ruleset>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment