Skip to content

Commit

Permalink
Merge pull request #257 from PHPCSStandards/develop
Browse files Browse the repository at this point in the history
Release PHPCSExtra 1.1.0
  • Loading branch information
jrfnl authored Jul 19, 2023
2 parents 029af41 + ae2326d commit 61a9be9
Show file tree
Hide file tree
Showing 82 changed files with 6,306 additions and 19 deletions.
40 changes: 31 additions & 9 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -168,36 +168,58 @@ jobs:
- name: Run the unit tests with code coverage
run: composer coverage

# Uploading the results with PHP Coveralls v1 won't work from GH Actions, so switch the PHP version.
- name: Switch to PHP 7.4
if: ${{ success() && matrix.php != '7.4' }}
# PHP Coveralls v2 (which supports GH Actions) has a PHP 5.5 minimum, so switch the PHP version.
- name: Switch to PHP latest
if: ${{ success() && matrix.php == '5.4' }}
uses: shivammathur/setup-php@v2
with:
php-version: 7.4
php-version: 'latest'
coverage: none

# Global install is used to prevent a conflict with the local composer.lock in PHP 8.0+.
# Global install is used to prevent a conflict with the local composer.lock.
- name: Install Coveralls
if: ${{ success() }}
run: composer global require php-coveralls/php-coveralls:"^2.5.3" --no-interaction
run: composer global require php-coveralls/php-coveralls:"^2.6.0" --no-interaction

- name: Upload coverage results to Coveralls
if: ${{ success() }}
- name: Upload coverage results to Coveralls (normal)
if: ${{ success() && github.actor != 'dependabot[bot]' }}
env:
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
COVERALLS_PARALLEL: true
COVERALLS_FLAG_NAME: php-${{ matrix.php }}-phpcs-${{ matrix.phpcs_version }}
run: php-coveralls -v -x build/logs/clover.xml

# Dependabot does not have access to secrets, other than the GH token.
# Ref: https://docs.github.com/en/code-security/dependabot/working-with-dependabot/automating-dependabot-with-github-actions
# Ref: https://github.com/lemurheavy/coveralls-public/issues/1721
- name: Upload coverage results to Coveralls (Dependabot)
if: ${{ success() && github.actor == 'dependabot[bot]' }}
env:
COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COVERALLS_PARALLEL: true
COVERALLS_FLAG_NAME: php-${{ matrix.php }}-phpcs-${{ matrix.phpcs_version }}
run: php-coveralls -v -x build/logs/clover.xml

coveralls-finish:
needs: coverage
if: always() && needs.coverage.result == 'success'

runs-on: ubuntu-latest

steps:
- name: Coveralls Finished
- name: Coveralls Finished (normal)
if: ${{ github.actor != 'dependabot[bot]' }}
uses: coverallsapp/github-action@v2
with:
github-token: ${{ secrets.COVERALLS_TOKEN }}
parallel-finished: true

# Dependabot does not have access to secrets, other than the GH token.
# Ref: https://docs.github.com/en/code-security/dependabot/working-with-dependabot/automating-dependabot-with-github-actions
# Ref: https://github.com/lemurheavy/coveralls-public/issues/1721
- name: Coveralls Finished (Dependabot)
if: ${{ github.actor == 'dependabot[bot]' }}
uses: coverallsapp/github-action@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel-finished: true
52 changes: 50 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,60 @@ This projects adheres to [Keep a CHANGELOG](http://keepachangelog.com/) and uses

_Nothing yet._

## [1.1.0] - 2023-07-19

### Added

#### Universal

* :wrench: :books: New `Universal.CodeAnalysis.NoEchoSprintf` sniff to detect use of the inefficient `echo [v]sprintf(...);` combi and recommends using `[v]printf()` instead. [#242]
* :bar_chart: :books: New `Universal.FunctionDeclarations.NoLongClosures` sniff to detect "long" closures and recommend using a named function instead. [#240]
The sniff offers the following properties to influence its behaviour: `recommendedLines` (defaults to `5`), `maxLines` (defaults to `8`), `ignoreCommentLines` (defaults to `true`) and `ignoreEmptyLines` (defaults to `true`).
* :wrench: :bar_chart: :books: New `Universal.FunctionDeclarations.RequireFinalMethodsInTraits` sniff to enforce non-private, non-abstract methods in traits to be declared as `final`. [#243], [#245]
There is a separate `NonFinalMagicMethodFound` error code for magic methods to allow those to be excluded from the check.
* :wrench: :bar_chart: :books: New `Universal.UseStatements.DisallowMixedGroupUse` sniff to disallow group use statements which import a combination of namespace/OO construct, functions and/or constants in one statement. [#241], [#246]
Note: the fixer will use a semi-standardized format for group use statements. If there are more specific requirements for the formatting of group use statements, the ruleset configurator should ensure that additional sniffs are included in the ruleset to enforce the required format.
* :wrench: :bar_chart: :books: New `Universal.UseStatements.KeywordSpacing` sniff to enforce the use of a single space after the `use`, `function`, `const` keywords and both before and after the `as` keyword in import `use` statements. [#247]
The sniff has modular error codes to allow for disabling individual checks.
* :wrench: :books: New `Universal.UseStatements.NoUselessAliases` sniff to detect useless aliases (aliasing something to its original name) in import use statements. [#244]
Note: as OO and function names in PHP are case-insensitive, aliasing to the same name, using a different case is also considered useless.
* :wrench: :bar_chart: :books: New `Universal.WhiteSpace.CommaSpacing` sniff to enforce that there is no space before a comma and exactly one space, or a new line, after a comma. [#254]
Additionally, the sniff also enforces that the comma should follow the code and not be placed after a trailing comment.
The sniff has modular error codes to allow for disabling individual checks and checks in certain contexts.
The sniff will respect a potentially set [`php_version` configuration option][php_version-config] when deciding how to handle the spacing after a heredoc/nowdoc closer.

### Changed

#### Universal

* Minor performance improvements for the `Universal.Arrays.DuplicateArrayKey` and the `Universal.CodeAnalysis.ConstructorDestructorReturn` sniffs. [#251], [#252]

#### Other

* Composer: The minimum `PHPCSUtils` requirement has been updated to `^1.0.8` (was `^1.0.6`). [#249], [#254]
* Various housekeeping.

[#240]: https://github.com/PHPCSStandards/PHPCSExtra/pull/240
[#241]: https://github.com/PHPCSStandards/PHPCSExtra/pull/241
[#242]: https://github.com/PHPCSStandards/PHPCSExtra/pull/242
[#243]: https://github.com/PHPCSStandards/PHPCSExtra/pull/243
[#244]: https://github.com/PHPCSStandards/PHPCSExtra/pull/244
[#245]: https://github.com/PHPCSStandards/PHPCSExtra/pull/245
[#246]: https://github.com/PHPCSStandards/PHPCSExtra/pull/246
[#247]: https://github.com/PHPCSStandards/PHPCSExtra/pull/247
[#249]: https://github.com/PHPCSStandards/PHPCSExtra/pull/249
[#251]: https://github.com/PHPCSStandards/PHPCSExtra/pull/251
[#252]: https://github.com/PHPCSStandards/PHPCSExtra/pull/252
[#254]: https://github.com/PHPCSStandards/PHPCSExtra/pull/254


## [1.0.4] - 2023-06-18

### Changed

#### Other

* Composer: The minimum `PHPCSUtils` requirement has been updated to `^1.0.6` (was ^1.0.0). [#237]
* Composer: The minimum `PHPCSUtils` requirement has been updated to `^1.0.6` (was `^1.0.0`). [#237]
* Various housekeeping.

### Fixed
Expand Down Expand Up @@ -183,7 +230,7 @@ For the full list of features, please see the changelogs of the alpha/rc release
* Updated the sniffs for compatibility with PHPCSUtils 1.0.0-alpha4. [#134]
* Updated the sniffs to correctly handle PHP 8.0/8.1/8.2 features whenever relevant.
* Readme: Updated installation instructions for compatibility with Composer 2.2+. [#101]
* Composer: The minimum `PHP_CodeSniffer` requirement has been updated to `^3.7.1` (was ^3.3.1). [#115], [#130]
* Composer: The minimum `PHP_CodeSniffer` requirement has been updated to `^3.7.1` (was `^3.3.1`). [#115], [#130]
* Composer: The package will now identify itself as a static analysis tool. Thanks [@GaryJones]! [#126]
* All non-`abstract` classes in this package are now `final`. [#121]
* All XML documentation now has a schema annotation. [#128]
Expand Down Expand Up @@ -441,6 +488,7 @@ This initial alpha release contains the following sniffs:
[php_version-config]: https://github.com/squizlabs/PHP_CodeSniffer/wiki/Configuration-Options#setting-the-php-version

[Unreleased]: https://github.com/PHPCSStandards/PHPCSExtra/compare/stable...HEAD
[1.1.0]: https://github.com/PHPCSStandards/PHPCSExtra/compare/1.0.4...1.1.0
[1.0.4]: https://github.com/PHPCSStandards/PHPCSExtra/compare/1.0.3...1.0.4
[1.0.3]: https://github.com/PHPCSStandards/PHPCSExtra/compare/1.0.2...1.0.3
[1.0.2]: https://github.com/PHPCSStandards/PHPCSExtra/compare/1.0.1...1.0.2
Expand Down
72 changes: 69 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Minimum Requirements

* PHP 5.4 or higher.
* [PHP_CodeSniffer][phpcs-gh] version **3.7.1** or higher.
* [PHPCSUtils][phpcsutils-gh] version **1.0.0** or higher.
* [PHPCSUtils][phpcsutils-gh] version **1.0.8** or higher.


Installation
Expand All @@ -61,15 +61,15 @@ Installing via Composer is highly recommended.
Run the following from the root of your project:
```bash
composer config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true
composer require --dev phpcsstandards/phpcsextra:"^1.0"
composer require --dev phpcsstandards/phpcsextra:"^1.1.0"
```

### Composer Global Installation

Alternatively, you may want to install this standard globally:
```bash
composer global config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true
composer global require --dev phpcsstandards/phpcsextra:"^1.0"
composer global require --dev phpcsstandards/phpcsextra:"^1.1.0"
```

### Updating to a newer version
Expand Down Expand Up @@ -220,6 +220,10 @@ Require a consistent modifier keyword order for class declarations.
If a [`php_version` configuration option][php_version-config] has been passed to PHPCS using either `--config-set` or `--runtime-set`, it will be respected by the sniff.
In effect, this means that the sniff will only report on PHP4-style constructors if the configured PHP version is less than 8.0.

#### `Universal.CodeAnalysis.NoEchoSprintf` :wrench: :books:

Detects use of the inefficient `echo [v]sprintf(...);` combi. Use `[v]printf()` instead.

#### `Universal.CodeAnalysis.ForeachUniqueAssignment` :wrench: :books:

Detects `foreach` control structures which use the same variable for both the key as well as the value assignment as this will lead to unexpected - and most likely unintended - behaviour.
Expand Down Expand Up @@ -278,6 +282,26 @@ Enforce for a file to either declare (global/namespaced) functions or declare OO
* Also note: This sniff has no opinion on multiple OO structures being declared in one file.
If you want to sniff for that, use the PHPCS native `Generic.Files.OneObjectStructurePerFile` sniff.

#### `Universal.FunctionDeclarations.NoLongClosures` :bar_chart: :books:

Detects "long" closures and recommends using a named function instead.

The sniff is configurable by setting any of the following properties in a custom ruleset:
* `recommendedLines` (int): determines when a warning will be thrown.
Defaults to `5`, meaning a warning with the errorcode `ExceedsRecommended` will be thrown if the closure is more than 5 lines long.
* `maxLines` (int): determines when an error will be thrown.
Defaults to `8`, meaning that an error with the errorcode `ExceedsMaximum` will be thrown if the closure is more than 8 lines long.
* `ignoreCommentLines` (bool): whether or not comment-only lines should be ignored for the lines count.
Defaults to `true`.
* `ignoreEmptyLines` (bool): whether or not blank lines should be ignored for the lines count.
Defaults to `true`.

#### `Universal.FunctionDeclarations.RequireFinalMethodsInTraits` :wrench: :bar_chart: :books:

Enforce non-private, non-abstract methods in traits to be declared as `final`.

The available error codes are: `NonFinalMethodFound` and `NonFinalMagicMethodFound`.

#### `Universal.Lists.DisallowLongListSyntax` :wrench: :books:

Disallow the use of long `list`s.
Expand Down Expand Up @@ -368,6 +392,13 @@ The available error codes are: `UnionTypeSpacesBefore`, `UnionTypeSpacesAfter`,

Disallow short open echo tags `<?=` containing more than one PHP statement.

#### `Universal.UseStatements.DisallowMixedGroupUse` :wrench: :bar_chart: :books:

Disallow group use statements which import a combination of namespace/OO construct, functions and/or constants in one statement.

Note: the fixer will use a semi-standardized format for group use statements.
If there are more specific requirements for the formatting of group use statements, the ruleset configurator should ensure that additional sniffs are included in the ruleset to enforce the required format.

#### `Universal.UseStatements.DisallowUseClass` :bar_chart: :books:

Forbid using import `use` statements for classes/traits/interfaces/enums.
Expand All @@ -394,6 +425,14 @@ Enforce that `function` and `const` keywords when used in an import `use` statem

Companion sniff to the PHPCS native `Generic.PHP.LowerCaseKeyword` sniff which doesn't cover these keywords when used in an import `use` statement.

#### `Universal.UseStatements.KeywordSpacing` :wrench: :bar_chart: :books:

Enforce the use of a single space after the `use`, `function`, `const` keywords and both before and after the `as` keyword in import `use` statements.

Companion sniff to the PHPCS native `Generic.WhiteSpace.LanguageConstructSpacing` sniff which doesn't cover the `function`, `const` and `as` keywords when used in an import `use` statement.

The sniff has modular error codes to allow for disabling individual checks. The error codes are: `SpaceAfterUse`, `SpaceAfterFunction`, `SpaceAfterConst`, `SpaceBeforeAs` and `SpaceAfterAs`.

#### `Universal.UseStatements.NoLeadingBackslash` :wrench: :bar_chart: :books:

Verify that a name being imported in an import `use` statement does not start with a leading backslash.
Expand All @@ -402,13 +441,40 @@ Names in import `use` statements should always be fully qualified, so a leading

This sniff handles all types of import use statements supported by PHP, in contrast to other sniffs for the same in, for instance, the PHPCS native `PSR12` or the Slevomat standard, which are incomplete.

#### `Universal.UseStatements.NoUselessAliases` :wrench: :books:

Detects useless aliases in import use statements.

Aliasing something to the same name as the original construct is considered useless (though allowed in PHP).
Note: as OO and function names in PHP are case-insensitive, aliasing to the same name, using a different case is also considered useless.

#### `Universal.WhiteSpace.AnonClassKeywordSpacing` :wrench: :bar_chart: :books:

Standardize the amount of spacing between the `class` keyword and the open parenthesis (if any) for anonymous class declarations.

* This sniff contains an `spacing` property to set the amount of spaces the sniff should check for.
Accepted values: (int) number of spaces. Defaults to `0` (spaces).

#### `Universal.WhiteSpace.CommaSpacing` :wrench: :bar_chart: :books:

Enforce that there is no space before a comma and exactly one space, or a new line, after a comma.

Additionally, the sniff also enforces that the comma should follow the code and not be placed after a trailing comment.

For the spacing part, the sniff makes the following exceptions:
1. A comma preceded or followed by a parenthesis, curly or square bracket.
These will not be flagged to prevent conflicts with sniffs handling spacing around braces.
2. A comma preceded or followed by another comma, like for skipping items in a list assignment.
These will not be flagged.

* The sniff has a separate error code - `TooMuchSpaceAfterCommaBeforeTrailingComment` - for when a comma is found with more than one space after it, followed by a trailing comment.
Exclude this error code to allow trailing comment alignment.
* The other error codes the sniff uses, `SpaceBefore`, `TooMuchSpaceAfter` and `NoSpaceAfter`, may be suffixed with a context indicator - `*InFunctionDeclaration`, `*InFunctionCall`, `*InClosureUse` or `*InDeclare` -.
This allows for disabling the sniff in any of these contexts by excluding the specific suffixed error codes.
* The sniff will respect a potentially set [`php_version` configuration option][php_version-config] when deciding how to handle the spacing after a heredoc/nowdoc closer.
In effect, this means that the sniff will enforce a new line between the closer and a comma if the configured PHP version is less than 7.3.
When no `php_version` is passed, the sniff will handle the spacing between a heredoc/nowdoc closer and a comma based on whether it is a cross-version compatible heredoc/nowdoc (enforce new line) or a flexible heredoc/nowdoc (enforce no space).

#### `Universal.WhiteSpace.DisallowInlineTabs` :wrench: :books:

Enforce using spaces for mid-line alignment.
Expand Down
25 changes: 25 additions & 0 deletions Universal/Docs/CodeAnalysis/NoEchoSprintfStandard.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0"?>
<documentation xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://phpcsstandards.github.io/PHPCSDevTools/phpcsdocs.xsd"
title="No Echo Sprintf"
>
<standard>
<![CDATA[
Detects use of `echo [v]sprintf(...);`. Use `[v]printf()` instead.
]]>
</standard>
<code_comparison>
<code title="Valid: using [v]printf() or echo with anything but [v]sprintf().">
<![CDATA[
<em>printf</em>('text %s text', $var);
<em>echo callMe</em>('text %s text', $var);
]]>
</code>
<code title="Invalid: using echo [v]sprintf().">
<![CDATA[
<em>echo sprintf</em>('text %s text', $var);
<em>echo vsprintf</em>('text %s text', [$var]);
]]>
</code>
</code_comparison>
</documentation>
42 changes: 42 additions & 0 deletions Universal/Docs/FunctionDeclarations/NoLongClosuresStandard.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?xml version="1.0"?>
<documentation xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://phpcsstandards.github.io/PHPCSDevTools/phpcsdocs.xsd"
title="No Long Closures"
>
<standard>
<![CDATA[
Forbids the use of long closures and recommends using named functions instead.
By default a closure is considered "longish" (warning) when it contains more than 5 lines of code and too long (error) when it contains more than 8 lines of code.
Also, by default only code lines are counted and blank lines and comment lines are ignored.
Each of these settings can be changed via the sniff configuration.
]]>
</standard>
<code_comparison>
<code title="Valid: Short closure.">
<![CDATA[
$closure = function() {
line1();
line2();
line3();
};
]]>
</code>
<code title="Invalid: Long closure.">
<![CDATA[
$closure = function() {
line1();
line2();
line3();
line4();
line5();
line6();
line7();
line8();
line9();
line10();
};
]]>
</code>
</code_comparison>
</documentation>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?xml version="1.0"?>
<documentation xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://phpcsstandards.github.io/PHPCSDevTools/phpcsdocs.xsd"
title="Require Final Methods in Traits"
>
<standard>
<![CDATA[
Requires the use of the `final` keyword for non-abstract, non-private methods in traits.
]]>
</standard>
<code_comparison>
<code title="Valid: Final methods in a trait.">
<![CDATA[
trait Foo {
<em>final</em> public function bar() {}
<em>final</em> public static function baz() {}
// Also valid (out of scope):
protected abstract function overload() {}
private function okay() {}
}
]]>
</code>
<code title="Invalid: Non-final methods in a trait.">
<![CDATA[
trait Foo {
<em>public function</em> bar() {}
<em>protected static function</em> baz() {}
}
]]>
</code>
</code_comparison>
</documentation>
Loading

0 comments on commit 61a9be9

Please sign in to comment.