Giter VIP home page Giter VIP logo

phpstan-rules's Introduction

phpstan-rules

Integrate Merge Release Renew

Code Coverage Type Coverage

Latest Stable Version Total Downloads Monthly Downloads

This project provides a composer package with rules for phpstan/phpstan.

Installation

Run

composer require --dev ergebnis/phpstan-rules

Usage

All of the rules provided (and used) by this library are included in rules.neon.

When you are using phpstan/extension-installer, rules.neon will be automatically included.

Otherwise you need to include rules.neon in your phpstan.neon:

includes:
	- vendor/ergebnis/phpstan-rules/rules.neon

๐Ÿ’ก You probably want to use these rules on top of the rules provided by:

Rules

This package provides the following rules for use with phpstan/phpstan:

Classes

Classes\FinalRule

This rule reports an error when a non-anonymous class is not final.

๐Ÿ’ก This rule ignores classes that

  • use @Entity, @ORM\Entity, or @ORM\Mapping\Entity annotations
  • use Doctrine\ORM\Mapping\Entity attributes

on the class level.

Disabling the rule

You can set the the enabled parameter to false to disable this rule.

parameters:
	ergebnis:
		final:
			enabled: false
Disallowing abstract classes

By default, this rule allows to declare abstract classes.

You can set the allowAbstractClasses parameter to false to disallow abstract classes.

parameters:
	ergebnis:
		final:
			allowAbstractClasses: false
Excluding classes from inspection

You can set the classesNotRequiredToBeAbstractOrFinal parameter to a list of class names that you want to exclude from inspection.

parameters:
	ergebnis:
		final:
			classesNotRequiredToBeAbstractOrFinal:
				- Foo\Bar\NeitherAbstractNorFinal
				- Bar\Baz\NeitherAbstractNorFinal

Classes\NoExtendsRule

This rule reports an error when a class extends another class.

Defaults

By default, this rule allows the following classes to be extended:

Disabling the rule

You can set the the enabled parameter to false to disable this rule.

parameters:
	ergebnis:
		noExtends:
			enabled: false
Allowing classes to be extended

You can set the classesAllowedToBeExtended parameter to a list of class names that you want to allow to be extended.

parameters:
	ergebnis:
		noExtends:
			classesAllowedToBeExtended:
				- Ergebnis\PHPStan\Rules\Test\Integration\AbstractTestCase
				- Ergebnis\PHPStan\Rules\Test\Integration\AbstractTestCase

Classes\PHPUnit\Framework\TestCaseWithSuffixRule

This rule reports an error when a concrete class is a sub-class of PHPUnit\Framework\TestCase but does not have a Test suffix.

Disabling the rule

You can set the the enabled parameter to false to disable this rule.

parameters:
	ergebnis:
		testCaseWithSuffix:
			enabled: false

Closures

Closures\NoNullableReturnTypeDeclarationRule

This rule reports an error when a closure uses a nullable return type declaration.

Disabling the rule

You can set the the enabled parameter to false to disable this rule.

parameters:
	ergebnis:
		noNullableReturnTypeDeclaration:
			enabled: false

Closures\NoParameterWithNullableTypeDeclarationRule

This rule reports an error when a closure has a parameter with a nullable type declaration.

Disabling the rule

You can set the the enabled parameter to false to disable this rule.

parameters:
	ergebnis:
		noParameterWithNullableTypeDeclaration:
			enabled: false

Closures\NoParameterWithNullDefaultValueRule

This rule reports an error when a closure has a parameter with null as default value.

Disabling the rule

You can set the the enabled parameter to false to disable this rule.

parameters:
	ergebnis:
		noParameterWithNullDefaultValue:
			enabled: false

Expressions

Expressions\NoCompactRule

This rule reports an error when the function compact() is used.

Disabling the rule

You can set the the enabled parameter to false to disable this rule.

parameters:
	ergebnis:
		noCompact:
			enabled: false

Expressions\NoEvalRule

This rule reports an error when the language construct eval() is used.

Disabling the rule

You can set the the enabled parameter to false to disable this rule.

parameters:
	ergebnis:
		noEval:
			enabled: false

Expressions\NoErrorSuppressionRule

This rule reports an error when @ is used to suppress errors.

Disabling the rule

You can set the the enabled parameter to false to disable this rule.

parameters:
	ergebnis:
		noErrorSuppression:
			enabled: false

Expressions\NoIssetRule

This rule reports an error when the language construct isset() is used.

Disabling the rule

You can set the the enabled parameter to false to disable this rule.

parameters:
	ergebnis:
		noIsset:
			enabled: false

Files

Files\DeclareStrictTypesRule

This rule reports an error when a non-empty file does not contain a declare(strict_types=1) declaration.

Disabling the rule

You can set the the enabled parameter to false to disable this rule.

parameters:
	ergebnis:
		declareStrictTypes:
			enabled: false

Functions

Functions\NoNullableReturnTypeDeclarationRule

This rule reports an error when a function uses a nullable return type declaration.

Disabling the rule

You can set the the enabled parameter to false to disable this rule.

parameters:
	ergebnis:
		noNullableReturnTypeDeclaration:
			enabled: false

Functions\NoParameterWithNullableTypeDeclarationRule

This rule reports an error when a function has a parameter with a nullable type declaration.

Disabling the rule

You can set the the enabled parameter to false to disable this rule.

parameters:
	ergebnis:
		noParameterWithNullableTypeDeclaration:
			enabled: false

Functions\NoParameterWithNullDefaultValueRule

This rule reports an error when a function has a parameter with null as default value.

Disabling the rule

You can set the the enabled parameter to false to disable this rule.

parameters:
	ergebnis:
		noParameterWithNullDefaultValue:
			enabled: false

Methods

Methods\FinalInAbstractClassRule

This rule reports an error when a concrete public or protected method in an abstract class is not final.

Disabling the rule

You can set the the enabled parameter to false to disable this rule.

parameters:
	ergebnis:
		finalInAbstractClass:
			enabled: false

Methods\NoConstructorParameterWithDefaultValueRule

This rule reports an error when a constructor declared in

  • an anonymous class
  • a class

has a default value.

Disabling the rule

You can set the the enabled parameter to false to disable this rule.

parameters:
	ergebnis:
		noConstructorParameterWithDefaultValue:
			enabled: false

Methods\NoNullableReturnTypeDeclarationRule

This rule reports an error when a method declared in

  • an anonymous class
  • a class
  • an interface

uses a nullable return type declaration.

Disabling the rule

You can set the the enabled parameter to false to disable this rule.

parameters:
	ergebnis:
		noNullableReturnTypeDeclaration:
			enabled: false

Methods\NoParameterWithContainerTypeDeclarationRule

This rule reports an error when a method has a type declaration for a known dependency injection container or service locator.

Defaults

By default, this rule disallows the use of type declarations indicating an implementation of

is expected to be injected into a method.

Disabling the rule

You can set the the enabled parameter to false to disable this rule.

parameters:
	ergebnis:
		noParameterWithContainerTypeDeclaration:
			enabled: false
Configuring container interfaces

You can set the interfacesImplementedByContainers parameter to a list of interface names of additional containers and service locators.

parameters:
	ergebnis:
		noParameterWithContainerTypeDeclaration:
			interfacesImplementedByContainers:
				- Fancy\DependencyInjection\ContainerInterface
				- Other\ServiceLocatorInterface
Configuring methods allowed to use parameters with container type declarations

You can set the methodsAllowedToUseContainerTypeDeclarations parameter to a list of method names that are allowed to use parameters with container type declarations.

parameters:
	ergebnis:
		noParameterWithContainerTypeDeclaration:
			methodsAllowedToUseContainerTypeDeclarations:
				- loadExtension

Methods\NoParameterWithNullableTypeDeclarationRule

This rule reports an error when a method declared in

  • an anonymous class
  • a class
  • an interface

has a parameter with a nullable type declaration.

Disabling the rule

You can set the the enabled parameter to false to disable this rule.

parameters:
	ergebnis:
		noParameterWithNullableTypeDeclaration:
			enabled: false

Methods\NoParameterWithNullDefaultValueRule

This rule reports an error when a method declared in

  • an anonymous class
  • a class
  • an interface

has a parameter with null as default value.

Disabling the rule

You can set the the enabled parameter to false to disable this rule.

parameters:
	ergebnis:
		noParameterWithNullDefaultValue:
			enabled: false

Methods\PrivateInFinalClassRule

This rule reports an error when a method in a final class is protected but could be private.

Disabling the rule

You can set the the enabled parameter to false to disable this rule.

parameters:
	ergebnis:
		privateInFinalClass:
			enabled: false

Statements

Statements\NoSwitchRule

This rule reports an error when the statement switch() is used.

Disabling the rule

You can set the the enabled parameter to false to disable this rule.

parameters:
	ergebnis:
		noSwitch:
			enabled: false

Changelog

The maintainers of this project record notable changes to this project in a changelog.

Contributing

The maintainers of this project suggest following the contribution guide.

Code of Conduct

The maintainers of this project ask contributors to follow the code of conduct.

General Support Policy

The maintainers of this project provide limited support.

You can support the maintenance of this project by sponsoring @localheinz or requesting an invoice for services related to this project.

PHP Version Support Policy

This project supports PHP versions with active and security support.

The maintainers of this project add support for a PHP version following its initial release and drop support for a PHP version when it has reached the end of security support.

Security Policy

This project has a security policy.

License

This project uses the MIT license.

Credits

The method FinalRule::isWhitelistedClass() is inspired by the work on FinalClassFixer and FinalInternalClassFixer, contributed by Dariusz Rumiล„ski, Filippo Tessarotto, and Spacepossum for friendsofphp/php-cs-fixer (originally licensed under MIT).

Social

Follow @localheinz and @ergebnis on Twitter.

phpstan-rules's People

Contributors

dependabot-preview[bot] avatar dependabot[bot] avatar dmecke avatar enumag avatar ergebnis-bot avatar great-antique avatar hpatoio avatar johnbillion avatar localheinz avatar nunomaduro avatar rpkamp avatar slamdunk avatar williamrijksen avatar wyrihaximus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

phpstan-rules's Issues

Prepare for PHPStan 1.0

Hello everyone ๐Ÿ‘‹

I announced today that PHPStan 1.0 is going to be released on November 1st 2021.

I'm approaching you as one of the most popular PHPStan extensions. I'd love if you could prepare your code for PHPStan 1.0 in advance so that it's ready to release on the same day.

Here's a brief guide how to approach the upgrade:

  1. Create a branch ๐ŸŒด
  2. Update your composer.json to "phpstan/phpstan": "^1.0", add "minimum-stability": "dev" and "prefer-stable": true if necessary.
  3. Update your code with the BC breaks below in mind. ๐Ÿ”ง
  4. Fix the code so that it passes PHPStan's analysis ๐Ÿค“
  5. Wait for PHPStan 1.0 release on November 1st, merge your branch and tag the next major version ๐Ÿ‘

Thank you!


Here are the BC breaks. The list is huge but most of those have very little impact.

There are new rules around using PHPStan internals in regard to backward compatibility promise: https://phpstan.org/developing-extensions/backward-compatibility-promise

It's possible that not everything you use is covered by it - so I'm here to help you to transition to correct usage, or add some @api annotations in PHPStan itself so that more is covered by the promise. Let me know!

BC breaks for end-users

The following are interesting only if you create a custom ruleset in your configuration file:

BC breaks for extension developers

Question regarding NoConstructorParameterWithDefaultValueRule

Hi,

Sorry if this is very basic question. I only recently started using phpstan and I came across this rule. I don't understand what is the proper way to do this? Why is a constructor parameter with default value bad?

I tried to research this, but I could not find anything..

Excerpt from my code that triggers this rule:

final class Client
{

public function __construct(
    protected string $endpoint,
    protected string $access_key,
    protected string $secret_key,
    protected int $timeout = 10,
    protected null|int $retryTimes = null,
    protected null|int $retryMilliseconds = null,
) {
}

Intentions and Solutions

First of all thank you for sharing your phpstan rules!

There are some rules (the nullable-rules to be precise) where I get the intention, but I am not sure how to avoid violations in some cases. I think there might also be a lack of understandment why some rules might be a good idea.

I think the rules would benefit from a brief description on why they should be applied and how to avoid violations.

PHP 8.0 support

I'm greeted with composer version restriction errors when installing on PHP 8.0 RC1, saying this package requires PHP 7.

Are you waiting for PHP 8.0 to become stable (i.e. leave beta) before providing an upgrade for this package or are you open to making this work with pre-stable versions of 8.0 as well?

Allow using ancestor classes in FinalRule whitelist parameter to whitelist their subclasses

Steps required to reproduce the problem

  1. Create a class as follows:
class MyTestCase extends \PHPUnit\Framework\TestCase
{
    // ...
}
  1. Add the following configuration to phpstan.neon:
services:
    -
        class: Localheinz\PHPStan\Rules\Classes\FinalRule
        arguments:
            allowAbstractClasses: true
            classesNotRequiredToBeAbstractOrFinal:
                - \PHPUnit\Framework\TestCase
        tags:
            - phpstan.rules.rule

Expected Result

  • FinalRule does not complain about MyTestCase not being final or abstract

Actual Result

  • Class MyTestCase is neither abstract nor final. is reported when running PHPStan.

Would it be sane to support parent classes and infer if a class inherits from them to allow skipping the final check? Or would a whole new option argument (e.g. ancestorClassesNotRequiredToBeAbstractOrFinal)?

Kinda defeats the purpose of this rule, but sometimes devs might have dependences that embrace the inheritance, and adding loads of exceptions into the config is not that feasible, and is error prone when it comes to teaching new devs about what that all is about and when to use it.

Suggestion: Suppress `NoParameterWithContainerTypeDeclarationRule` in a bundle's `loadExtension()`

When using Symfony's new way to set up a bundle https://symfony.com/doc/current/bundles/extension.html#loading-services-directly-in-your-bundle-class, the following error is emitted by NoParameterWithContainerTypeDeclarationRule:

Method FooBundle\FooBundle::loadExtension() has a parameter $builder with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.

I'm suggesting to make an exception for this case, i.e. don't show an error if the method name is xxxBundle::loadExtension()

StaticPrivateMethodWithoutObjectReference

Reference: https://twitter.com/localheinz/status/1174221387571109890

https://phpstan.org/r/3c374bde-8916-47c7-9442-58ccc2929047

declare(strict_types = 1);

final class HelloWorld
{
	/** @var int */
	private $foo = 1;
	
	public function getFoo(): int
	{
		return $this->addFoo($this->foo, 1);
	}
	
	private function addFoo(int $a, int $b): int
	{
		return $a + $b;
	}
}

Expected

+---------------------------------------------------------------------------------+
| Line | test.php                                                                 |
+---------------------------------------------------------------------------------+
| 13   | Method addFoo is not declared static but doesn't use any $this reference |
+---------------------------------------------------------------------------------+

 [ERROR] Found 1 error 

Actual

 [OK] No errors 

Methods\StaticRule

A private method that does not access any instance members of the containing class can be easily marked as static.

This has the following advantages:

  • a developer can immediately see that the method does not access any instance membes
  • a static method can be used in static closures, which means that by turning a non-static method into a static method, perhaps non-static closures can be marked as static

Also see #90.

Nullable return type declaration with explicit types

We just switch to doctrine/coding-standard 10.x, which enforces explicit types, like ?string=> string|null.
After the switch (and the code fix) ergebnis/phpstan-rules doesn't recognize these anymore, it says Ignored error pattern #Function ... has a nullable return type declaration# was not matched in reported errors.
Since it is still nullable, the error should still be thrown.

Is it possible to configure this to only use some rules?

I'd like to use some of the rules from this package. However some other rules are a bit too much. Is it possible to configure this to only use some of the rules but not all of them?

For instance I want to avoid the declare strict rule because that's already taken care of by my very strict coding standard and it's entirely unnecessary to make the already slow phpstan pipeline even slower by double checking it. And while I do agree with most of the rules, a few of them (especially those regarding nullable types) might be a bit too aggressive.

Note that I'm using phpstan/extension-installer so it isn't an option to avoid including your configuration and only copy some parts of it manually.

I'm using most of the rules from https://github.com/shipmonk-rnd/phpstan-rules for instance but it very easily allows me to disable some of them. Something like that would be ideal.

Exclude Doctrine Entities from the FinalRule

I would like to use the FinalRule and I've tried to write my own implementation before I stumbled over your package. Do you have any solution for the problem that doctrine entities must not be final because of their proxy classes? I understand that I can whitelist them one by one in your implementation, but that does not feel too clean as I have to adjust the config file of a CI tool every time I add something in my domain layer. I also don't put them into one huge Entity directory, so the location is no indication neither. Do you have any suggestions?

Rule disable option

Type: feature

Add rules disable functionality.
From config perpective it could look something like this:

ergebnis:
              NoExtendsRule:
                       enable: false

              // then other options to rules could look like this
              FinalRule:
                       allowAbstractClasses: false
                       classesNotRequiredToBeAbstractOrFinal:
			       - Foo\Bar\NeitherAbstractNorFinal

This way there is rule options indepencdence

`PrivateInFinalClassRule` should not report trait methods

Steps required to reproduce the problem

Define a trait with a protected method and a final class using this trait.

Expected Result

No error, methods defined in a trait should be ignored by this rule.

Actual Result

PrivateInFinalClassRule will report this method as that it should be private, however this is only true in the context of that class and may not be true for other usages of the trait.

Closures\StaticRule

Related PHP-CS-Fixer rule: static_lambda

Lambdas should always be static to ensure no one can rebind them and so no one can alter their behavior.

FinalInAbstractClassRule complains not final method in interface

Starting with version 0.12 an check failed on an interface.

Steps required to reproduce the problem

<?php
/**
 * This file is part of the ios-build package.
 *
 * Copyright (c) 2019, Thomas Mueller <[email protected]>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

declare(strict_types = 1);
namespace IosBuild;

interface IosBuildInterface
{
    /**
     * Takes iOS build code and returns corresponding iOS version.
     *
     * @param string $needle the build code
     *
     * @throws BuildException
     * @throws NotFoundException
     *
     * @return string JSON encoded string
     */
    public function getVersion(string $needle): string;
}
  1. run PHPStan including this library against this file.

Expected Result

 [OK] No errors

Actual Result

 ------ -------------------------------------------------------------------------------------------------------------------------
  Line   IosBuildInterface.php
 ------ -------------------------------------------------------------------------------------------------------------------------
  26     Method IosBuild\IosBuildInterface::getVersion() is not final, but since the containing class is abstract, it should be.
 ------ -------------------------------------------------------------------------------------------------------------------------


 [ERROR] Found 1 error

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.