Skip to content
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

[Feature/59] Add rules against arrow function feature #62

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from 18 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 0 additions & 76 deletions .github/workflows/php-qa.yml

This file was deleted.

51 changes: 51 additions & 0 deletions .github/workflows/quality-assurance-php.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: PHP Quality Assurance

on:
push:
paths:
- '**workflows/quality-assurance-php.yml'
- '**.php'
- '**phpcs.xml.dist'
- '**phpunit.xml.dist'
- '**psalm.xml'
workflow_dispatch:
inputs:
jobs:
required: true
type: choice
default: 'Run all'
description: 'Choose jobs to run'
options:
- 'Run all'
- 'Run PHPCS only'
- 'Run Psalm only'
- 'Run lint only'
- 'Run static analysis'
- 'Run unit tests only'

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
lint-php:
uses: inpsyde/reusable-workflows/.github/workflows/lint-php.yml@main
if: ${{ (github.event_name != 'workflow_dispatch') || ((github.event.inputs.jobs == 'Run all') || (github.event.inputs.jobs == 'Run lint only') || (github.event.inputs.jobs == 'Run static analysis')) }}
with:
PHP_MATRIX: '["7.4", "8.0", "8.1", "8.2"]'
LINT_ARGS: '-e php --colors --show-deprecated ./Inpsyde'

coding-standards-analysis-php:
if: ${{ (github.event_name != 'workflow_dispatch') || ((github.event.inputs.jobs == 'Run all') || (github.event.inputs.jobs == 'Run PHPCS only') || (github.event.inputs.jobs == 'Run static analysis')) }}
uses: inpsyde/reusable-workflows/.github/workflows/coding-standards-php.yml@main

static-code-analysis-php:
if: ${{ (github.event_name != 'workflow_dispatch') || ((github.event.inputs.jobs == 'Run all') || (github.event.inputs.jobs == 'Run Psalm only') || (github.event.inputs.jobs == 'Run static analysis')) }}
uses: inpsyde/reusable-workflows/.github/workflows/static-analysis-php.yml@main

tests-unit-php:
if: ${{ (github.event_name != 'workflow_dispatch') || ((github.event.inputs.jobs == 'Run all') || (github.event.inputs.jobs == 'Run unit tests only')) }}
uses: inpsyde/reusable-workflows/.github/workflows/tests-unit-php.yml@main
with:
PHP_MATRIX: '["7.4", "8.0", "8.1", "8.2"]'
PHPUNIT_ARGS: '--no-coverage'
7 changes: 0 additions & 7 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,4 @@ composer.phar
composer.lock
/vendor/
/phpunit.xml

# Commit your application's lock file http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file
# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
# composer.lock
.buildpath
.project
.settings/
.phpunit.result.cache
63 changes: 36 additions & 27 deletions Inpsyde/PhpcsHelpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,14 @@ public static function findOopContext(File $file, int $position): int
$targetLevel = (int)$tokens[$position]['level'] - 1;

foreach ($tokens[$position]['conditions'] as $condPosition => $condCode) {
assert(is_int($condPosition));
$condLevel = (int)($tokens[$condPosition]['level'] ?? -1);

if (
in_array($condCode, Tokens::$ooScopeTokens, true)
&& ($condLevel === $targetLevel)
) {
return (int)$condPosition;
return $condPosition;
}
}

Expand Down Expand Up @@ -288,7 +289,7 @@ public static function isHookClosure(
/** @var array<int, array<string, mixed>> $tokens */
$tokens = $file->getTokens();

if (($tokens[$position]['code'] ?? '') !== T_CLOSURE) {
if (!in_array(($tokens[$position]['code'] ?? ''), [T_CLOSURE, T_FN], true)) {
return false;
}

Expand Down Expand Up @@ -341,7 +342,7 @@ public static function functionDocBlockTags(

if (
!array_key_exists($position, $tokens)
|| !in_array($tokens[$position]['code'], [T_FUNCTION, T_CLOSURE], true)
|| !in_array($tokens[$position]['code'], [T_FUNCTION, T_CLOSURE, T_FN], true)
) {
return [];
}
Expand Down Expand Up @@ -387,7 +388,7 @@ public static function functionDocBlockTags(
$normalizedTags = [];
static $rand;
$rand or $rand = bin2hex(random_bytes(3));
foreach ($tags as list($tagName, $tagContent)) {
foreach ($tags as [$tagName, $tagContent]) {
empty($normalizedTags[$tagName]) and $normalizedTags[$tagName] = [];
if (!$normalizeContent) {
$normalizedTags[$tagName][] = $tagContent;
Expand Down Expand Up @@ -433,7 +434,7 @@ public static function functionDocBlockParamTypes(File $file, int $functionPosit

$types = [];
foreach ($params as $param) {
preg_match('~^([^$]+)\s*(\$(?:[^\s]+))~', trim($param), $matches);
preg_match('~^([^$]+)\s*(\$\S+)~', trim($param), $matches);
if (empty($matches[1]) || empty($matches[2])) {
continue;
}
Expand Down Expand Up @@ -461,7 +462,7 @@ public static function isHookFunction(File $file, int $position): bool
*/
public static function functionBody(File $file, int $position): string
{
list($start, $end) = static::functionBoundaries($file, $position);
[$start, $end] = static::functionBoundaries($file, $position);
if ($start < 0 || $end < 0) {
return '';
}
Expand All @@ -470,7 +471,7 @@ public static function functionBody(File $file, int $position): string
$tokens = $file->getTokens();
$body = '';
for ($i = $start + 1; $i < $end; $i++) {
$body .= (string)$tokens[$i]['content'];
$body .= (string)($tokens[$i]['content'] ?? '');
}

return $body;
Expand All @@ -479,30 +480,24 @@ public static function functionBody(File $file, int $position): string
/**
* @param File $file
* @param int $position
* @return array{int, int}
* @return list{int, int}
*/
public static function functionBoundaries(File $file, int $position): array
{
/** @var array<int, array<string, mixed>> $tokens */
$tokens = $file->getTokens();

if (!in_array(($tokens[$position]['code'] ?? null), [T_FUNCTION, T_CLOSURE], true)) {
if (!in_array(($tokens[$position]['code'] ?? null), [T_FUNCTION, T_CLOSURE, T_FN], true)) {
return [-1, -1];
}

$functionStart = (int)($tokens[$position]['scope_opener'] ?? 0);
$functionEnd = (int)($tokens[$position]['scope_closer'] ?? 0);
if ($functionStart <= 0 || $functionEnd <= 0 || $functionStart >= ($functionEnd - 1)) {
return [-1, -1];
}

return [$functionStart, $functionEnd];
return static::boundaries($tokens, $position);
}

/**
* @param File $file
* @param int $position
* @return array{int, int}
* @return list{int, int}
*/
public static function classBoundaries(File $file, int $position): array
{
Expand All @@ -513,13 +508,7 @@ public static function classBoundaries(File $file, int $position): array
return [-1, -1];
}

$start = (int)($tokens[$position]['scope_opener'] ?? 0);
$end = (int)($tokens[$position]['scope_closer'] ?? 0);
if ($start <= 0 || $end <= 0 || $start >= ($end - 1)) {
return [-1, -1];
}

return [$start, $end];
return static::boundaries($tokens, $position);
}

/**
Expand All @@ -531,18 +520,22 @@ public static function returnsCountInfo(File $file, int $position): array
{
$returnCount = ['nonEmpty' => 0, 'void' => 0, 'null' => 0, 'total' => 0];

list($start, $end) = self::functionBoundaries($file, $position);
[$start, $end] = self::functionBoundaries($file, $position);
if ($start < 0 || $end <= 0) {
return $returnCount;
}

/** @var array<int, array<string, mixed>> $tokens */
$tokens = $file->getTokens();

if (T_FN === ($tokens[$position]['code'] ?? null)) {
return ['nonEmpty' => 1, 'void' => 0, 'null' => 0, 'total' => 1];
}

$pos = $start + 1;
while ($pos < $end) {
list(, $innerFunctionEnd) = self::functionBoundaries($file, $pos);
list(, $innerClassEnd) = self::classBoundaries($file, $pos);
[, $innerFunctionEnd] = self::functionBoundaries($file, $pos);
[, $innerClassEnd] = self::classBoundaries($file, $pos);
if ($innerFunctionEnd > 0 || $innerClassEnd > 0) {
$pos = ($innerFunctionEnd > 0) ? $innerFunctionEnd + 1 : $innerClassEnd + 1;
continue;
Expand Down Expand Up @@ -723,4 +716,20 @@ public static function isUntypedPsrMethod(File $file, int $position): bool

return false;
}

/**
* @param array<int, array<string, mixed>> $tokens
* @param int $position
* @return list{int, int}
*/
private static function boundaries(array $tokens, int $position): array
{
$start = (int)($tokens[$position]['scope_opener'] ?? 0);
$end = (int)($tokens[$position]['scope_closer'] ?? 0);
if ($start <= 0 || $end <= 0 || $start >= ($end - 1)) {
return [-1, -1];
}

return [$start, $end];
}
}
Loading