Skip to content

PHPLIB-330: Implement checks for coding standard #668

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 26, 2019

Conversation

alcaeus
Copy link
Member

@alcaeus alcaeus commented Aug 21, 2019

This introduces a coding standard that is automatically checked during the build using phpcs. The coding standard itself is derived from doctrine/coding-standard. I've tried to keep :

  • All sniffs that would produce code incompatible with PHP 5.6 are excluded (strict typing, null coalesce operator, class constant visibilities, and most notably type hints)
  • All sniffs that cause BC breaks are excluded (again, mostly type hints as well as class naming sniffs)
  • Sniffs that would cause functional changes are excluded, amongst other:
    • Using known aliases of common PHP functions (e.g. sizeof instead of count)
    • Unused private elements: side effects of this have to be carefully reviewed
    • Yoda comparisons
    • Reducing code nesting in favour of early exit
    • Useless if conditions instead of returning directly
    • Static closures
    • Unused variables in closures
    • Using the equal operator
  • A follow-up pull request will add type hints to all properties in classes. This was extracted from this pull request to keep the diffs manageable.

This PR was designed to not really have to be reviewed. Most fixes were applied automatically (see last commit), with only some changes done manually.

Note: I've made a point of disabling some sniffs in DocumentationExamplesTest. This was done to keep the examples "portable" and allow people to simply copy/paste them to their code, e.g. by preserving fully qualified namespaces.

@alcaeus alcaeus self-assigned this Aug 21, 2019
@alcaeus alcaeus requested a review from jmikola August 21, 2019 11:45
<file>src</file>
<file>tests</file>

<rule ref="Doctrine">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we change this to "MongoDB" if it's only going to be derived from Doctrine and modified for our needs? Alternatively, is this just indicating that we're inheriting the Doctrine rule set and then applying our own modifications below?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pulls in all rules from the Doctrine coding standard and allows us to exclude/modify some of them. Since we just configure phpcs.xml our ruleset doesn't have a name, that would only happen if we create a ruleset.xml in the standardised directory structure, which isn't necessary if we're not going to distribute the coding standard.

// Since doctrine/coding-standard requires PHP 7, we can't add it as a dependency
// yet. This autoload file adds more information to the phpcs error message,
// telling the user how they can fix the error presented to them by phpcs.
if (! file_exists(__DIR__ . '/../vendor/doctrine/coding-standard')) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a particular reason we only pull doctrine/coding-standard in from the smoke test stage in .travis.yml and don't include it in our require-dev dependencies?

Copy link
Member Author

@alcaeus alcaeus Aug 22, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since doctrine/coding-standard requires PHP 7.1, including it in require-dev would implicitly bump our PHP requirement to 7.1 on CI systems, breaking tests for older PHP versions. That's why the check stage requires it manually.

To make the generic error message from phpcs more helpful I decided to use the autoload functionality of phpcs to include this error message if doctrine/coding-standard wasn't installed. Now that you mention it, it's probably best to also mention this in the contribution docs.

env:
- CHECKS=phpunit
- stage: Smoke Testing
php: "7.1"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a particular reason to use 7.1?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of the sniffs we use have feature detection where they disable/enable functionality based on PHP version. For example, the sniff requiring type hints does not enforce an object type hint on methods unless running on PHP 7.2 or later. Thus, it's always a good idea to target the lowest supported version for the coding standard in CI.

@@ -202,7 +203,7 @@ private function onIteration($incrementKey)

/* Return early if there is not a current result. Avoid any attempt to
* increment the iterator's key. */
if (!$this->valid()) {
if (! $this->valid()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this have spaces on both sides of the !? I see some later occurrences of ! were left as-is so I'm wondering if the coding standard permits both but only applies a trailing space when formatting incorrectly styled code.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is only a sniff to enforce a space after the negation operator, but not to enforce it before it, hence the different styles. The space after the opening parenthesis in function calls is forbidden by PSR-2, which serves as the base of doctrine/coding-standard. The space before is left over from me excluding a sniff for now (see comment below about control structure spacing)

use function stream_copy_to_stream;
use function stream_get_meta_data;
use function stream_get_wrappers;
use function urlencode;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh my.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll get used to them. It greatly reduces eyestrain from seeing too many \ all over the place. FWIW, if you give in and start using PhpStorm, it will do this for you automagically.

@@ -156,7 +156,7 @@ public function __construct($databaseName, $collectionName, JavascriptInterface
}

if (isset($options['finalize']) && ! $options['finalize'] instanceof JavascriptInterface) {
throw InvalidArgumentException::invalidType('"finalize" option', $options['finalize'], Javascript::class);
throw InvalidArgumentException::invalidType('"finalize" option', $options['finalize'], JavascriptInterface::class);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch!

@alcaeus alcaeus mentioned this pull request Aug 26, 2019
alcaeus added a commit that referenced this pull request Aug 26, 2019
@alcaeus alcaeus merged commit b00ceb1 into mongodb:master Aug 26, 2019
@alcaeus alcaeus deleted the phplib-330 branch August 26, 2019 10:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants