All Projects → gskema → Phpcs Type Sniff

gskema / Phpcs Type Sniff

Licence: mit
PHP CodeSniffer sniff to enforce PHP 7 types and documentation of array variables

Projects that are alternatives of or similar to Phpcs Type Sniff

nest-typed-config
Intuitive, type-safe configuration module for Nest framework ✨
Stars: ✭ 47 (+34.29%)
Mutual labels:  type-safety
Structopt
Parse command line arguments by defining a struct
Stars: ✭ 323 (+822.86%)
Mutual labels:  type-safety
Swift Tagged
🏷 A wrapper type for safer, expressive code.
Stars: ✭ 801 (+2188.57%)
Mutual labels:  type-safety
Dry Struct
Typed struct and value objects
Stars: ✭ 263 (+651.43%)
Mutual labels:  type-safety
Vuex Smart Module
Type safe Vuex module with powerful module features
Stars: ✭ 306 (+774.29%)
Mutual labels:  type-safety
Topshell
TopShell - a purely functional, reactive scripting language
Stars: ✭ 422 (+1105.71%)
Mutual labels:  type-safety
typed
Typed variables for PHP 7.4+ ( don't use this please )
Stars: ✭ 66 (+88.57%)
Mutual labels:  type-safety
Type safe
Zero overhead utilities for preventing bugs at compile time
Stars: ✭ 866 (+2374.29%)
Mutual labels:  type-safety
Jni.hpp
A modern, type-safe, header-only, C++14 wrapper for JNI
Stars: ✭ 313 (+794.29%)
Mutual labels:  type-safety
Nexus Plugin Prisma
A plugin for Nexus that integrates Prisma
Stars: ✭ 728 (+1980%)
Mutual labels:  type-safety
Identity
🆔 Type-safe identifiers in Swift
Stars: ✭ 282 (+705.71%)
Mutual labels:  type-safety
Mammoth
A type-safe Postgres query builder for TypeScript.
Stars: ✭ 305 (+771.43%)
Mutual labels:  type-safety
Swift Nonempty
🎁 A compile-time guarantee that a collection contains a value.
Stars: ✭ 585 (+1571.43%)
Mutual labels:  type-safety
Cone
Cone Programming Language
Stars: ✭ 257 (+634.29%)
Mutual labels:  type-safety
Flow Runtime
A runtime type system for JavaScript with full Flow compatibility.
Stars: ✭ 813 (+2222.86%)
Mutual labels:  type-safety
postgresql-typed
Haskell PostgreSQL library with compile-time type inference
Stars: ✭ 72 (+105.71%)
Mutual labels:  type-safety
Graphaello
A Tool for Writing Declarative, Type-Safe and Data-Driven Applications in SwiftUI using GraphQL
Stars: ✭ 355 (+914.29%)
Mutual labels:  type-safety
Zion
A statically-typed strictly-evaluated garbage-collected readable programming language.
Stars: ✭ 33 (-5.71%)
Mutual labels:  type-safety
Pcf Nominal
A formalisation of PCF in Agda using naive nominal binding
Stars: ✭ 5 (-85.71%)
Mutual labels:  type-safety
Gentype
Auto generation of idiomatic bindings between Reason and JavaScript: either vanilla or typed with TypeScript/FlowType.
Stars: ✭ 683 (+1851.43%)
Mutual labels:  type-safety

PHPCS Type Sniff

Latest Version on Packagist Software License Build Status Coverage Status Quality Score Total Downloads

Custom phpcs CodeSniffer rule that:

  • Enforces usage of PHP 7 type declarations (where possible)
  • Enforces documenting array types with more specific types (e.g. int[])
  • Checks for useless PHPDoc blocks (no repeated information)
  • Many more other checks

Example PHP class (comments on the right = phpcs warnings):

<?php

namespace Fruits;

/**
 * Class Banana                     // useless description
 * @package Fruits                  // useless tag
 */
class Banana
{
    const C1 = [];                  // missing typed array doc type

    /** @var array */               // must use typed array doc type
    const C2 = [];

    /** @var array[] */             // must use specific typed array doc type
    const C3 = [[]];

    /** @var bool|false */          // redundant false type
    const C4 = false;

    /**
     * @var int                     // incompatible int type, missing null type
     */
    const C5 = null;

    /** @var int */
    const C6 = 1;                   // useless PHPDoc

    public $prop1 = [];             // missing typed array doc type

    /** @var array */               // must use typed array doc type
    public $prop2 = [];

    public $prop3;                  // missing @var tag, missing null doc type

    /** @var */                     // missing doc type, missing null doc type
    public $prop4;

    /** @var array[][] */           // must use specific typed array doc type, missing null doc type
    public $prop5;

    /** @var array|string[] */      // redundant array type, missing null doc type
    public $prop6;

    /** @var int|string */          // missing null doc type
    public $prop7 = null;

    /** @var int $prop8 */          // prop name must be removed, missing null doc type
    public $prop8;

    /** @var int */
    public $prop9;                  // Not initialized, missing null doc type

    /** @var int */
    public $prop10;                 // Initialized, missing null doc type

    /** @var int */
    public $prop11;

    /** @var int */
    public $prop12;

    public function __construct()
    {
        $this->prop10 = null;
        $this->prop11 = 11;
        $this->setProp12();
    }

    public function setProp12(): void
    {
        $this->prop12 = 1;
    }

    public function func1(
        $param1,                    // missing param type decl.
        int $param2
    ) {                             // missing return type decl.
    }

    /**
     * @param int|null  $param1
     * @param int|null  $param2
     * @param array     $param3     // must use typed array doc type
     *
     * @param           $param5     // suggested int doc type
     * @param           $param6     // missing doc type
     * @param array[]   $param7     // must use specific typed array doc type
     * @param bool|true $param8     // remove true doc type
     * @param null      $param9     // suggested compound doc type, e.g. int|null
     * @param string    $param10    // incompatible string type, missing int, null types
     * @param stdClass  $param11
     * @param bool|int  $param12
     *
     * @return void                 // useless tag
     */
    public function func2(
        $param1,                    // suggested ?int type decl.
        int $param2 = null,         // suggested ?int type decl.
        array $param3,
        $param4,                    // missing @param tag
        int $param5,
        $param6,
        array $param7,
        bool $param8,
        $param9 = null,             // missing type decl.
        ?int $param10 = null,
        stdClass $param11,
        $param12
    ): void {
    }

    /**
     * @return int
     */
    public function func3(): int    // useless PHPDoc
    {
    }

    /**
     * @param array<int, bool>           $arg1 // alternative array documentation
     * @param array{foo: bool, bar: int} $arg2 // supported, no warning
     * @param (int|string)[]             $arg3 //
     * @param array('key1' => int, ...)  $arg4 //
     */
    public function func4(
        array $arg1,
        array $arg2,
        array $arg3,
        array $arg4
    ): void {
    }
}

Install

Via Composer

$ composer require --dev gskema/phpcs-type-sniff

Usage

This is a standalone sniff file, you need to add it to your phpcs.xml file.

Usage Without Reflection

Inspections for methods with @inheritdoc tag are skipped. If a method does not have this tag, it is inspected. This is the recommend setup.

<ruleset name="your_ruleset">
    <!-- your configuration -->
    <rule ref="PSR2"/>

    <!-- phpcs-type-sniff configuration -->   
    <rule ref="./vendor/gskema/phpcs-type-sniff/src/Sniffs/CompositeCodeElementSniff.php"/>
</ruleset>

Usage With Reflection

With reflection enabled, this sniff can assert if @inheritoc tag is needed. Inspections for extended/implemented methods are skipped. Reflections need to load actual classes, which is why we need to include the autoloader. This option is good for inspecting extended methods, however using ReflectionClass may cause phpcs crashes while editing (not possible to catch FatalError).

<ruleset name="your_ruleset">
    <!-- your configuration -->
    <rule ref="PSR2"/>

    <!-- phpcs-type-sniff configuration -->   
    <autoload>./vendor/autoload.php</autoload>
    <rule ref="./vendor/gskema/phpcs-type-sniff/src/Sniffs/CompositeCodeElementSniff.php">
        <properties>
            <property name="useReflection" value="true"/>
        </properties>
    </rule>
</ruleset>

Configuration

Sniffs are registered and saved by their short class name. This allows easily specifying configuration options for a specific code element sniff, e.g. FqcnMethodSniff.invalidTags. All custom code sniff classes must have unique short class names.

String true/false values are automatically converted to booleans.

<ruleset name="your_ruleset">
    <!-- your configuration -->
    <rule ref="PSR2"/>

    <!-- phpcs-type-sniff configuration -->   

    <!-- Includes an autoloader which is needed when using reflection API -->
    <!-- or custom code element sniff(s) -->
    <autoload>./vendor/autoload.php</autoload>

    <!-- Includes a standalone sniff to your custom coding standard -->
    <rule ref="./vendor/gskema/phpcs-type-sniff/src/Sniffs/CompositeCodeElementSniff.php">
        <properties>

            <!-- Enables usage of reflection API when inspecting extended classes. -->
            <!-- Autoloader is needed. -->
            <property name="useReflection" value="true"/>

            <!-- Disables one of the default code element sniffs -->
            <property name="FqcnConstSniff.enabled" value="false" />
            <property name="FqcnMethodSniff.enabled" value="false" />
            <property name="FqcnPropSniff.enabled" value="false" />
            <property name="FqcnDescriptionSniff.enabled" value="false" />

            <!-- Change violation report type for all sniffs. Default is warning. -->
            <property name="reportType" value="error" />

            <!-- Or change violation report type for individual sniffs. Default is warning. -->
            <property name="FqcnConstSniff.reportType" value="error" />
            <property name="FqcnMethodSniff.reportType" value="error" />
            <property name="FqcnPropSniff.reportType" value="warning" />
            <property name="FqcnDescriptionSniff.reportType" value="warning" />

            <!-- Tags that should be removed from method PHPDoc -->
            <property name="FqcnMethodSniff.invalidTags" type="array">
                <element value="@someTag1"/>
                <element value="@someTag2"/>
            </property>

            <!-- Description lines and tags that should be removed from FQCN PHPDoc -->
            <property name="FqcnDescriptionSniff.invalidPatterns" type="array">
                <element value="^Nothing.+Useful$"/>
            </property>
            <property name="FqcnDescriptionSniff.invalidTags" type="array">
                <element value="@api"/>
            </property>

            <!-- Disables reporting missing @param, @return tags in non-empty method PHPDoc -->
            <!-- when method type declarations are present -->
            <property name="FqcnMethodSniff.reportMissingTags" value="false"/>

            <!-- Disables reporting missing null type in basic getter return PHPDoc -->
            <!-- and return type declaration -->
            <property name="FqcnPropSniff.reportNullableBasicGetter" value="false"/>

            <!-- Disables reporting missing null type in property PHPDoc -->
            <!-- when there is no default value and no assigned value in __construct() -->
            <!--- Some false positives in exotic cases may be reported -->
            <property name="FqcnPropSniff.reportUninitializedProp" value="false"/>

            <!-- Your own custom code element sniff(s). Autoloader is needed. -->
            <!-- These classes implement CodeElementSniffInterface -->
            <property name="sniffs" type="array">
                <element value="\Acme\CustomCodeElementSniff" />
                <element value="\Acme\AnotherCustomMethodSniff" />
            </property>

            <!-- Configuration options for custom code element sniffs -->
            <property name="CustomCodeElementSniff.opt1" value="str1" />
            <!-- Specifying element key(s) will create an associative array -->
            <property name="AnotherCustomMethodSniff.arrayOpt1" type="array">
                <element key="key1" value="str1"/>
                <element key="key2" value="str2"/>
            </property>

        </properties>
    </rule>
</ruleset>

Change log

Please see CHANGELOG for more information on what has changed recently.

Testing

$ ./vendor/bin/phpunit

License

The MIT License (MIT). Please see License File for more information.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].