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',
|
||||
'psalm-ncu.xml',
|
||||
'psalm-ocp.xml',
|
||||
'psalm-strict.xml',
|
||||
'psalm.xml',
|
||||
'public.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
|
||||
*/
|
||||
|
||||
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()
|
||||
return (require 'rector-shared.php')
|
||||
->withPaths([
|
||||
$nextcloudDir . '/apps',
|
||||
$nextcloudDir . '/core',
|
||||
|
|
@ -71,43 +30,4 @@ $config = RectorConfig::configure()
|
|||
// $nextcloudDir . '/lib',
|
||||
// $nextcloudDir . '/themes',
|
||||
])
|
||||
->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)
|
||||
->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;
|
||||
->withTypeCoverageLevel(0);
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@
|
|||
"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",
|
||||
"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"
|
||||
},
|
||||
"extra": {
|
||||
|
|
|
|||
Loading…
Reference in a new issue