mirror of
https://github.com/nextcloud/server.git
synced 2026-02-03 20:41:22 -05:00
feat(rector): Add strict config for new code
Signed-off-by: provokateurin <kate@provokateurin.de>
This commit is contained in:
parent
3d09e8d912
commit
8713730419
6 changed files with 172 additions and 82 deletions
45
.github/workflows/rector.yml
vendored
Normal file
45
.github/workflows/rector.yml
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
# SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
name: Rector
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: rector-${{ github.head_ref || github.run_id }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
strict:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
if: ${{ github.event_name != 'push' && github.repository_owner != 'nextcloud-gmbh' }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
submodules: true
|
||||||
|
|
||||||
|
- name: Set up php
|
||||||
|
uses: shivammathur/setup-php@ec406be512d7077f68eed36e63f4d91bc006edc4 #v2.35.4
|
||||||
|
with:
|
||||||
|
php-version: '8.2'
|
||||||
|
extensions: apcu,ctype,curl,dom,fileinfo,ftp,gd,imagick,intl,json,ldap,mbstring,openssl,pdo_sqlite,posix,sqlite,xml,zip
|
||||||
|
coverage: none
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Composer install
|
||||||
|
run: composer i
|
||||||
|
|
||||||
|
- name: Rector
|
||||||
|
run: composer run rector:strict
|
||||||
|
|
||||||
|
- name: Show changes
|
||||||
|
if: always()
|
||||||
|
run: git diff --exit-code -- . ':!lib/composer'
|
||||||
|
|
@ -74,6 +74,7 @@ $expectedFiles = [
|
||||||
'package.json',
|
'package.json',
|
||||||
'psalm-ncu.xml',
|
'psalm-ncu.xml',
|
||||||
'psalm-ocp.xml',
|
'psalm-ocp.xml',
|
||||||
|
'psalm-strict.xml',
|
||||||
'psalm.xml',
|
'psalm.xml',
|
||||||
'public.php',
|
'public.php',
|
||||||
'remote.php',
|
'remote.php',
|
||||||
|
|
|
||||||
92
build/rector-shared.php
Normal file
92
build/rector-shared.php
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
use Nextcloud\Rector\Set\NextcloudSets;
|
||||||
|
use PhpParser\Node;
|
||||||
|
use Rector\CodingStyle\Contract\ClassNameImport\ClassNameImportSkipVoterInterface;
|
||||||
|
use Rector\Config\RectorConfig;
|
||||||
|
use Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector;
|
||||||
|
use Rector\PHPUnit\Set\PHPUnitSetList;
|
||||||
|
use Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedObjectType;
|
||||||
|
use Rector\ValueObject\Application\File;
|
||||||
|
|
||||||
|
$nextcloudDir = dirname(__DIR__);
|
||||||
|
|
||||||
|
class NextcloudNamespaceSkipVoter implements ClassNameImportSkipVoterInterface {
|
||||||
|
private array $namespacePrefixes = [
|
||||||
|
'OC',
|
||||||
|
'OCA',
|
||||||
|
'OCP',
|
||||||
|
];
|
||||||
|
private array $skippedClassNames = [
|
||||||
|
'Backend',
|
||||||
|
'Connection',
|
||||||
|
'Exception',
|
||||||
|
'IManager',
|
||||||
|
'IProvider',
|
||||||
|
'Manager',
|
||||||
|
'Plugin',
|
||||||
|
'Provider',
|
||||||
|
];
|
||||||
|
public function shouldSkip(File $file, FullyQualifiedObjectType $fullyQualifiedObjectType, Node $node) : bool {
|
||||||
|
if (in_array($fullyQualifiedObjectType->getShortName(), $this->skippedClassNames)) {
|
||||||
|
// Skip common class names to avoid confusion
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
foreach ($this->namespacePrefixes as $prefix) {
|
||||||
|
if (str_starts_with($fullyQualifiedObjectType->getClassName(), $prefix . '\\')) {
|
||||||
|
// Import Nextcloud namespaces
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Skip everything else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$config = RectorConfig::configure()
|
||||||
|
->withSkip([
|
||||||
|
$nextcloudDir . '/apps/*/3rdparty/*',
|
||||||
|
$nextcloudDir . '/apps/*/build/stubs/*',
|
||||||
|
$nextcloudDir . '/apps/*/composer/*',
|
||||||
|
$nextcloudDir . '/apps/*/config/*',
|
||||||
|
// The mock classes are excluded, as the tests explicitly test the annotations which should not be migrated to attributes
|
||||||
|
$nextcloudDir . '/tests/lib/AppFramework/Middleware/Mock/*',
|
||||||
|
$nextcloudDir . '/tests/lib/AppFramework/Middleware/Security/Mock/*',
|
||||||
|
])
|
||||||
|
// uncomment to reach your current PHP version
|
||||||
|
// ->withPhpSets()
|
||||||
|
->withImportNames(importShortClasses:false)
|
||||||
|
->withConfiguredRule(ClassPropertyAssignToConstructorPromotionRector::class, [
|
||||||
|
'inline_public' => true,
|
||||||
|
'rename_property' => true,
|
||||||
|
])
|
||||||
|
->withSets([
|
||||||
|
NextcloudSets::NEXTCLOUD_27,
|
||||||
|
PHPUnitSetList::PHPUNIT_100,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$config->registerService(NextcloudNamespaceSkipVoter::class, tag:ClassNameImportSkipVoterInterface::class);
|
||||||
|
|
||||||
|
/* Ignore all files ignored by git */
|
||||||
|
$ignoredEntries = shell_exec('git status --porcelain --ignored ' . escapeshellarg($nextcloudDir));
|
||||||
|
$ignoredEntries = explode("\n", $ignoredEntries);
|
||||||
|
$ignoredEntries = array_filter($ignoredEntries, static fn (string $line) => str_starts_with($line, '!! '));
|
||||||
|
$ignoredEntries = array_map(static fn (string $line) => substr($line, 3), $ignoredEntries);
|
||||||
|
$ignoredEntries = array_values($ignoredEntries);
|
||||||
|
|
||||||
|
foreach ($ignoredEntries as $ignoredEntry) {
|
||||||
|
if (str_ends_with($ignoredEntry, '/')) {
|
||||||
|
$config->withSkip([$ignoredEntry . '*']);
|
||||||
|
} else {
|
||||||
|
$config->withSkip([$ignoredEntry . '/*']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $config;
|
||||||
31
build/rector-strict.php
Normal file
31
build/rector-strict.php
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
$nextcloudDir = dirname(__DIR__);
|
||||||
|
|
||||||
|
return (require __DIR__ . '/rector-shared.php')
|
||||||
|
->withPaths([
|
||||||
|
$nextcloudDir . '/build/rector-strict.php',
|
||||||
|
// TODO: Add more files. The entry above is just there to stop rector from complaining about the fact that it ran without checking any files.
|
||||||
|
])
|
||||||
|
->withPreparedSets(
|
||||||
|
deadCode: true,
|
||||||
|
codeQuality: true,
|
||||||
|
codingStyle: true,
|
||||||
|
typeDeclarations: true,
|
||||||
|
typeDeclarationDocblocks: true,
|
||||||
|
privatization: true,
|
||||||
|
instanceOf: true,
|
||||||
|
earlyReturn: true,
|
||||||
|
rectorPreset: true,
|
||||||
|
phpunitCodeQuality: true,
|
||||||
|
doctrineCodeQuality: true,
|
||||||
|
symfonyCodeQuality: true,
|
||||||
|
symfonyConfigs: true,
|
||||||
|
)->withPhpSets(
|
||||||
|
php82: true,
|
||||||
|
);
|
||||||
|
|
@ -7,50 +7,9 @@ declare(strict_types=1);
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Nextcloud\Rector\Set\NextcloudSets;
|
|
||||||
use PhpParser\Node;
|
|
||||||
use Rector\CodingStyle\Contract\ClassNameImport\ClassNameImportSkipVoterInterface;
|
|
||||||
use Rector\Config\RectorConfig;
|
|
||||||
use Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector;
|
|
||||||
use Rector\PHPUnit\Set\PHPUnitSetList;
|
|
||||||
use Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedObjectType;
|
|
||||||
use Rector\ValueObject\Application\File;
|
|
||||||
|
|
||||||
$nextcloudDir = dirname(__DIR__);
|
$nextcloudDir = dirname(__DIR__);
|
||||||
|
|
||||||
class NextcloudNamespaceSkipVoter implements ClassNameImportSkipVoterInterface {
|
return (require 'rector-shared.php')
|
||||||
private array $namespacePrefixes = [
|
|
||||||
'OC',
|
|
||||||
'OCA',
|
|
||||||
'OCP',
|
|
||||||
];
|
|
||||||
private array $skippedClassNames = [
|
|
||||||
'Backend',
|
|
||||||
'Connection',
|
|
||||||
'Exception',
|
|
||||||
'IManager',
|
|
||||||
'IProvider',
|
|
||||||
'Manager',
|
|
||||||
'Plugin',
|
|
||||||
'Provider',
|
|
||||||
];
|
|
||||||
public function shouldSkip(File $file, FullyQualifiedObjectType $fullyQualifiedObjectType, Node $node) : bool {
|
|
||||||
if (in_array($fullyQualifiedObjectType->getShortName(), $this->skippedClassNames)) {
|
|
||||||
// Skip common class names to avoid confusion
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
foreach ($this->namespacePrefixes as $prefix) {
|
|
||||||
if (str_starts_with($fullyQualifiedObjectType->getClassName(), $prefix . '\\')) {
|
|
||||||
// Import Nextcloud namespaces
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Skip everything else
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$config = RectorConfig::configure()
|
|
||||||
->withPaths([
|
->withPaths([
|
||||||
$nextcloudDir . '/apps',
|
$nextcloudDir . '/apps',
|
||||||
$nextcloudDir . '/core',
|
$nextcloudDir . '/core',
|
||||||
|
|
@ -71,43 +30,4 @@ $config = RectorConfig::configure()
|
||||||
// $nextcloudDir . '/lib',
|
// $nextcloudDir . '/lib',
|
||||||
// $nextcloudDir . '/themes',
|
// $nextcloudDir . '/themes',
|
||||||
])
|
])
|
||||||
->withSkip([
|
->withTypeCoverageLevel(0);
|
||||||
$nextcloudDir . '/apps/*/3rdparty/*',
|
|
||||||
$nextcloudDir . '/apps/*/build/stubs/*',
|
|
||||||
$nextcloudDir . '/apps/*/composer/*',
|
|
||||||
$nextcloudDir . '/apps/*/config/*',
|
|
||||||
// The mock classes are excluded, as the tests explicitly test the annotations which should not be migrated to attributes
|
|
||||||
$nextcloudDir . '/tests/lib/AppFramework/Middleware/Mock/*',
|
|
||||||
$nextcloudDir . '/tests/lib/AppFramework/Middleware/Security/Mock/*',
|
|
||||||
])
|
|
||||||
// uncomment to reach your current PHP version
|
|
||||||
// ->withPhpSets()
|
|
||||||
->withImportNames(importShortClasses:false)
|
|
||||||
->withTypeCoverageLevel(0)
|
|
||||||
->withConfiguredRule(ClassPropertyAssignToConstructorPromotionRector::class, [
|
|
||||||
'inline_public' => true,
|
|
||||||
'rename_property' => true,
|
|
||||||
])
|
|
||||||
->withSets([
|
|
||||||
NextcloudSets::NEXTCLOUD_27,
|
|
||||||
PHPUnitSetList::PHPUNIT_100,
|
|
||||||
]);
|
|
||||||
|
|
||||||
$config->registerService(NextcloudNamespaceSkipVoter::class, tag:ClassNameImportSkipVoterInterface::class);
|
|
||||||
|
|
||||||
/* Ignore all files ignored by git */
|
|
||||||
$ignoredEntries = shell_exec('git status --porcelain --ignored ' . escapeshellarg($nextcloudDir));
|
|
||||||
$ignoredEntries = explode("\n", $ignoredEntries);
|
|
||||||
$ignoredEntries = array_filter($ignoredEntries, static fn (string $line) => str_starts_with($line, '!! '));
|
|
||||||
$ignoredEntries = array_map(static fn (string $line) => substr($line, 3), $ignoredEntries);
|
|
||||||
$ignoredEntries = array_values($ignoredEntries);
|
|
||||||
|
|
||||||
foreach ($ignoredEntries as $ignoredEntry) {
|
|
||||||
if (str_ends_with($ignoredEntry, '/')) {
|
|
||||||
$config->withSkip([$ignoredEntry . '*']);
|
|
||||||
} else {
|
|
||||||
$config->withSkip([$ignoredEntry . '/*']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $config;
|
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,7 @@
|
||||||
"test:db": "@composer run test -- --group DB --group SLOWDB",
|
"test:db": "@composer run test -- --group DB --group SLOWDB",
|
||||||
"test:files_external": "phpunit --fail-on-warning --fail-on-risky --display-warnings --display-deprecations --display-phpunit-deprecations --colors=always --configuration tests/phpunit-autotest-external.xml",
|
"test:files_external": "phpunit --fail-on-warning --fail-on-risky --display-warnings --display-deprecations --display-phpunit-deprecations --colors=always --configuration tests/phpunit-autotest-external.xml",
|
||||||
"rector": "rector --config=build/rector.php && composer cs:fix",
|
"rector": "rector --config=build/rector.php && composer cs:fix",
|
||||||
|
"rector:strict": "rector --config=build/rector-strict.php && composer cs:fix",
|
||||||
"openapi": "./build/openapi-checker.sh"
|
"openapi": "./build/openapi-checker.sh"
|
||||||
},
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue