首页 > 其他分享 >统一规范化项目的命名风格

统一规范化项目的命名风格

时间:2023-05-09 18:33:43浏览次数:45  
标签:node Node return name method 命名 风格 规范化 class

最近在迁移一个上古项目到 laravel 中。我这边的做法是先用 rector 做一个整体初步的语法升级与 laravel 写法的替换,然后主要就是手动重写数据操作的部分。到目前为止除了应用到 rector 自带的规则外,还写了一些自定义的规则,其中有一个规范化命名风格的规则(RenameToPsrNameRector)适用于所有的 PHP 项目,所以在此分享出来。该规则主要是针对常量、变量、函数、类、属性、方法等命名进行统一的规范。其中,常量名遵循大写蛇形命名风格,函数名遵循小写蛇形命名风格,类名遵循大驼峰命名风格,变量名、属性名、方法名遵循小驼峰命名风格。

效果

 <?php

 // lower snake
-function functionName(){}
-functionName();
-call_user_func('functionName');
-call_user_func_array('functionName');
-function_exists('functionName');
+function function_name(){}
+\function_name();
+call_user_func('function_name');
+call_user_func_array('function_name');
+function_exists('function_name');

 // ucfirst camel
-class class_name{}
-enum enum_name{}
-enum Enum{case case_name;}
-interface interface_name{}
-trait trait_name{}
-class Foo extends class_name implements interface_name{}
-class_name::$property;
-class_name::CONST;
-class_name::method();
-enum Enum implements interface_name{}
-use class_name;
-use trait_name;
-class_alias('class_name', 'alias_class_name');
-class_exists('class_name');
-class_implements('class_name');
-class_parents('class_name');
-class_uses('class_name');
-enum_exists('enum_name');
-get_class_methods('class_name');
-get_class_vars('class_name');
-get_parent_class('class_name');
-interface_exists('interface_name');
-is_subclass_of('class_name', 'parent_class_name');
-trait_exists('trait_name', true);
+class ClassName{}
+enum EnumName{}
+enum Enum{case CaseName;}
+interface InterfaceName{}
+trait TraitName{}
+class Foo extends \ClassName implements \InterfaceName{}
+\ClassName::$property;
+\ClassName::CONST;
+\ClassName::method();
+enum Enum implements \InterfaceName{}
+use ClassName;
+use TraitName;
+class_alias('ClassName', 'AliasClassName');
+class_exists('ClassName');
+class_implements('ClassName');
+class_parents('ClassName');
+class_uses('ClassName');
+enum_exists('EnumName');
+get_class_methods('ClassName');
+get_class_vars('ClassName');
+get_parent_class('ClassName');
+interface_exists('InterfaceName');
+is_subclass_of('ClassName', 'ParentClassName');
+trait_exists('TraitName', true);

 // upper snake
-class Foo{public const constName = 'const';}
-Foo::constName;
-define('constName', 'const');
-defined('constName');
-constant('constName');
+class Foo{public const CONST_NAME = 'const';}
+Foo::CONST_NAME;
+define('CONST_NAME', 'const');
+defined('CONST_NAME');
+constant('CONST_NAME');
 constant('Foo::constName');
-constName;
+\CONST_NAME;

 // lcfirst camel
-$var_name;
-$object->method_name();
-$object->property_name;
-call_user_method('method_name', $object);
-call_user_method_array('method_name', $object);
-class Foo{public $property_name;}
-class Foo{public function method_name(){}}
-class Foo{public int $property_name;}
-Foo::$property_name;
-Foo::method_name();
-method_exists($object, 'method_name');
-property_exists($object, 'property_name');
+$varName;
+$object->methodName();
+$object->propertyName;
+call_user_method('methodName', $object);
+call_user_method_array('methodName', $object);
+class Foo{public $propertyName;}
+class Foo{public function methodName(){}}
+class Foo{public int $propertyName;}
+Foo::$propertyName;
+Foo::methodName();
+method_exists($object, 'methodName');
+property_exists($object, 'propertyName');

规则(RenameToPsrNameRector)

<?php

namespace App\Support\Rectors;

use Illuminate\Support\Str;
use PhpParser\Node;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Name;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use RectorPrefix202305\Webmozart\Assert\Assert;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

class RenameToPsrNameRector extends AbstractRector implements ConfigurableRectorInterface
{
    /**
     * @var array<string>
     */
    protected $except = [
        '*::*',
        'class',
        'false',
        'null',
        'stdClass',
        'true',
    ];

    public function getRuleDefinition(): RuleDefinition
    {
        return new RuleDefinition(
            'Rename to psr name',
            [
                new CodeSample(
                    <<<'CODE_SAMPLE'
// lower snake
function functionName(){}
functionName();
call_user_func('functionName');
call_user_func_array('functionName');
function_exists('functionName');

// ucfirst camel
class class_name{}
enum enum_name{}
enum Enum{case case_name;}
interface interface_name{}
trait trait_name{}
class Foo extends class_name implements interface_name{}
class_name::$property;
class_name::CONST;
class_name::method();
enum Enum implements interface_name{}
use class_name;
use trait_name;
class_alias('class_name', 'alias_class_name');
class_exists('class_name');
class_implements('class_name');
class_parents('class_name');
class_uses('class_name');
enum_exists('enum_name');
get_class_methods('class_name');
get_class_vars('class_name');
get_parent_class('class_name');
interface_exists('interface_name');
is_subclass_of('class_name', 'parent_class_name');
trait_exists('trait_name', true);

// upper snake
class Foo{public const constName = 'const';}
Foo::constName;
define('constName', 'const');
defined('constName');
constant('constName');
constant('Foo::constName');
constName;

// lcfirst camel
$var_name;
$object->method_name();
$object->property_name;
call_user_method('method_name', $object);
call_user_method_array('method_name', $object);
class Foo{public $property_name;}
class Foo{public function method_name(){}}
class Foo{public int $property_name;}
Foo::$property_name;
Foo::method_name();
method_exists($object, 'method_name');
property_exists($object, 'property_name');
CODE_SAMPLE
                    ,
                    <<<'CODE_SAMPLE'
// lower snake
function function_name(){}
function_name();
call_user_func('function_name');
call_user_func_array('function_name');
function_exists('function_name');

// ucfirst camel
class ClassName{}
enum EnumName{}
enum Enum{case CaseName;}
interface InterfaceName{}
trait TraitName{}
class Foo extends ClassName implements InterfaceName{}
ClassName::$property;
ClassName::CONST;
ClassName::method();
enum Enum implements InterfaceName{}
use ClassName;
use TraitName;
class_alias('ClassName', 'AliasClassName');
class_exists('ClassName');
class_implements('ClassName');
class_parents('ClassName');
class_uses('ClassName');
enum_exists('EnumName');
get_class_methods('ClassName');
get_class_vars('ClassName');
get_parent_class('ClassName');
interface_exists('InterfaceName');
is_subclass_of('ClassName', 'ParentClassName');
trait_exists('TraitName', true);

// upper snake
class Foo{public const CONST_NAME = 'const';}
Foo::CONST_NAME;
define('CONST_NAME', 'const');
defined('CONST_NAME');
constant('CONST_NAME');
constant('Foo::CONST_NAME');
CONST_NAME;

// lcfirst camel
$varName
$object->methodName();
$object->propertyName;
class Foo{public $propertyName;}
class Foo{public function methodName(){}}
class Foo{public int $propertyName;}
Foo::$propertyName;
Foo::methodName();
call_user_method('methodName', $object);
call_user_method_array('methodName', $object);
method_exists($object, 'methodName');
property_exists($object, 'propertyName');
CODE_SAMPLE
                ),
            ]);
    }

    /**
     * {@inheritDoc}
     */
    public function getNodeTypes(): array
    {
        return [
            \PhpParser\Node\Name::class,
            \PhpParser\Node\Expr\FuncCall::class,
            \PhpParser\Node\Expr\Variable::class,
            \PhpParser\Node\Identifier::class,
        ];
    }

    /**
     * @param  \PhpParser\Node\Name|\PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Expr\Variable|\PhpParser\Node\Identifier  $node
     */
    public function refactor(Node $node)
    {
        try {
            if ($this->shouldLowerSnakeName($node)) {
                return $this->rename($node, static fn (string $name): string => Str::lower(Str::snake($name)));
            }

            if ($this->shouldUcfirstCamelName($node)) {
                return $this->rename($node, static fn (string $name): string => Str::ucfirst(Str::camel($name)));
            }

            if ($this->shouldUpperSnakeName($node)) {
                return $this->rename($node, static fn (string $name): string => Str::upper(Str::snake($name)));
            }

            if ($this->shouldLcfirstCamelName($node)) {
                return $this->rename($node, static fn (string $name): string => Str::lcfirst(Str::camel($name)));
            }
        } catch (\RuntimeException $e) {
            // skip
        }

        return null;
    }

    /**
     * @param  \PhpParser\Node\Name|\PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Expr\Variable|\PhpParser\Node\Identifier  $node
     */
    protected function rename(Node $node, callable $renamer): Node
    {
        $preprocessor = function (string $value): string {
            if ($this->is($this->except, $value)) {
                throw new \RuntimeException("The name[$value] is skipped.");
            }

            if (ctype_upper(preg_replace('/[^a-zA-Z]/', '', $value))) {
                return mb_strtolower($value, 'UTF-8');
            }

            return $value;
        };

        if ($node instanceof Name) {
            $node->parts[count($node->parts) - 1] = $renamer($preprocessor($node->parts[count($node->parts) - 1]));

            return $node;
        }

        if (
            $this->isSubclasses($node, [
                Node\Expr\Variable::class,
                Node\Identifier::class,
            ])
        ) {
            $node->name = $renamer($preprocessor($node->name));

            return $node;
        }

        if ($node instanceof FuncCall) {
            if (
                $this->isNames($node, [
                    'call_user_func',
                    'call_user_func_array',
                    'call_user_method',
                    'call_user_method_array',
                    'class_alias',
                    'class_exists',
                    'class_implements',
                    'class_parents',
                    'class_uses',
                    'constant',
                    'define',
                    'defined',
                    'enum_exists',
                    'function_exists',
                    'get_class_methods',
                    'get_class_vars',
                    'get_parent_class',
                    'interface_exists',
                    'is_subclass_of',
                    'trait_exists',
                ])
                && $this->hasFuncCallIndexStringArg($node, 0)
            ) {
                $node->args[0]->value->value = $renamer($preprocessor($node->args[0]->value->value));
            }

            if (
                $this->isNames($node, [
                    'class_alias',
                    'is_subclass_of',
                    'method_exists',
                    'property_exists',
                ])
                && $this->hasFuncCallIndexStringArg($node, 1)
            ) {
                $node->args[1]->value->value = $renamer($preprocessor($node->args[1]->value->value));
            }
        }

        return $node;
    }

    /**
     * @param  \PhpParser\Node\Name|\PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Expr\Variable|\PhpParser\Node\Identifier  $node
     */
    protected function shouldLowerSnakeName(Node $node): bool
    {
        $parent = $node->getAttribute('parent');

        // function function_name(){}
        if ($node instanceof Node\Identifier && $parent instanceof Node\Stmt\Function_) {
            return true;
        }

        // function_name();
        if ($node instanceof Node\Name && $parent instanceof FuncCall) {
            return true;
        }

        if (
            $node instanceof FuncCall
            && $this->isNames($node, [
                // function_exists('function_name');
                'function_exists',
                // call_user_func('function_name');
                'call_user_func',
                // call_user_func_array('function_name');
                'call_user_func_array',
            ])
            && $this->hasFuncCallIndexStringArg($node, 0)
        ) {
            return true;
        }

        return false;
    }

    /**
     * @param  \PhpParser\Node\Name|\PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Expr\Variable|\PhpParser\Node\Identifier  $node
     */
    protected function shouldUcfirstCamelName(Node $node): bool
    {
        $parent = $node->getAttribute('parent');

        if (
            $node instanceof Node\Identifier
            && $this->isSubclasses($parent, [
                // interface InterfaceName{}
                Node\Stmt\Interface_::class,
                // class ClassName{}
                Node\Stmt\Class_::class,
                // trait TraitName{}
                Node\Stmt\Trait_::class,
                // enum EnumName{}
                Node\Stmt\Enum_::class,
                // enum Enum{case CaseName;}
                Node\Stmt\EnumCase::class,
            ])
        ) {
            return true;
        }

        if (
            $node instanceof Node\Name
            && ! $this->isName($node, 'stdClass')
            && $this->isSubclasses($parent, [
                // ClassName::CONST;
                Node\Expr\ClassConstFetch::class,
                // ClassName::$property;
                Node\Expr\StaticPropertyFetch::class,
                // ClassName::method();
                Node\Expr\StaticCall::class,
                // class Foo extends ClassName implements InterfaceName{}
                Node\Stmt\Class_::class,
                // enum Enum implements InterfaceName{}
                Node\Stmt\Enum_::class,
                // use ClassName;
                Node\Stmt\UseUse::class,
                // use TraitName;
                Node\Stmt\TraitUse::class,
            ])
        ) {
            return true;
        }

        if ($node instanceof FuncCall) {
            if (
                $this->isNames($node, [
                    // class_alias('ClassName', 'AliasClassName');
                    'class_alias',
                    // class_exists('ClassName');
                    'class_exists',
                    // class_implements('ClassName');
                    'class_implements',
                    // class_parents('ClassName');
                    'class_parents',
                    // class_uses('ClassName');
                    'class_uses',
                    // enum_exists('EnumName');
                    'enum_exists',
                    // get_class_methods('ClassName');
                    'get_class_methods',
                    // get_class_vars('ClassName');
                    'get_class_vars',
                    // get_parent_class('ClassName');
                    'get_parent_class',
                    // interface_exists('InterfaceName');
                    'interface_exists',
                    // is_subclass_of('ClassName', 'ParentClassName');
                    'is_subclass_of',
                    // trait_exists('TraitName', true);
                    'trait_exists',
                ])
                && $this->hasFuncCallIndexStringArg($node, 0)
            ) {
                return true;
            }

            if (
                $this->isNames($node, [
                    // class_alias('ClassName', 'AliasClassName');
                    'class_alias',
                    // is_subclass_of('ClassName', 'ParentClassName');
                    'is_subclass_of',
                ])
                && $this->hasFuncCallIndexStringArg($node, 1)
            ) {
                return true;
            }
        }

        return false;
    }

    /**
     * @param  \PhpParser\Node\Name|\PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Expr\Variable|\PhpParser\Node\Identifier  $node
     */
    protected function shouldUpperSnakeName(Node $node): bool
    {
        $parent = $node->getAttribute('parent');

        if (
            $node instanceof Node\Identifier
            && ! $this->isName($node, 'class')
            && $this->isSubclasses($parent, [
                // class Foo{public const CONST_NAME = 'const';}
                Node\Const_::class,
                // Foo::CONST_NAME;
                Node\Expr\ClassConstFetch::class,
            ])
        ) {
            return true;
        }

        if (
            $node instanceof FuncCall
            && $this->isNames($node, [
                // define('CONST_NAME', 'const');
                'define',
                // defined('CONST_NAME');
                'defined',
                // constant('Foo::CONST_NAME');
                'constant',
            ])
            && $this->hasFuncCallIndexStringArg($node, 0)
        ) {
            return true;
        }

        // CONST_NAME;
        if (
            $node instanceof Name
            && ! $this->isNames($node, ['null', 'true', 'false'])
            && $parent instanceof Node\Expr\ConstFetch
        ) {
            return true;
        }

        return false;
    }

    /**
     * @param  \PhpParser\Node\Name|\PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Expr\Variable|\PhpParser\Node\Identifier  $node
     */
    protected function shouldLcfirstCamelName(Node $node): bool
    {
        // $varName;
        if ($node instanceof Node\Expr\Variable) {
            return true;
        }

        if (
            $node instanceof Node\Identifier
            && $this->isSubclasses($node->getAttribute('parent'), [
                // class Foo{public $propertyName;}
                Node\Stmt\Property::class,
                // class Foo{public int $propertyName;}
                Node\Stmt\PropertyProperty::class,
                // class Foo{public function methodName(){}}
                Node\Stmt\ClassMethod::class,
                // $object->propertyName;
                Node\Expr\PropertyFetch::class,
                // Foo::$propertyName;
                Node\Expr\StaticPropertyFetch::class,
                // $object->methodName();
                Node\Expr\MethodCall::class,
                // Foo::methodName();
                Node\Expr\StaticCall::class,
            ])
        ) {
            return true;
        }

        if ($node instanceof FuncCall) {
            if (
                $this->isNames($node, [
                    // call_user_method('methodName', $object);
                    'call_user_method',
                    // call_user_method_array('methodName', $object);
                    'call_user_method_array',
                ])
                && $this->hasFuncCallIndexStringArg($node, 0)
            ) {
                return true;
            }

            if (
                $this->isNames($node, [
                    // method_exists($object, 'methodName');
                    'method_exists',
                    // property_exists($object, 'propertyName');
                    'property_exists',
                ])
                && $this->hasFuncCallIndexStringArg($node, 1)
            ) {
                return true;
            }
        }

        return false;
    }

    protected function isSubclasses($object, array $classes): bool
    {
        if (! is_object($object)) {
            return false;
        }

        foreach ($classes as $class) {
            if ($object instanceof $class) {
                return true;
            }
        }

        return false;
    }

    /**
     * @param  string|iterable<string>  $patterns
     * @param  string  $value
     */
    public function is($patterns, $value): bool
    {
        $value = (string) $value;
        if (! is_iterable($patterns)) {
            $patterns = [$patterns];
        }

        foreach ($patterns as $pattern) {
            $pattern = (string) $pattern;
            if ($pattern === $value) {
                return true;
            }

            $pattern = preg_quote($pattern, '#');
            $pattern = str_replace('\*', '.*', $pattern);
            if (preg_match('#^'.$pattern.'\z#u', $value) === 1) {
                return true;
            }
        }

        return false;
    }

    protected function hasFuncCallIndexStringArg(FuncCall $funcCall, int $index): bool
    {
        return isset($funcCall->args[$index])
            && $funcCall->args[$index]->name === null
            && $funcCall->args[$index]->value instanceof Node\Scalar\String_;
    }

    protected function hasFuncCallNameStringArg(FuncCall $funcCall, string $name): bool
    {
        foreach ($funcCall->args as $arg) {
            if (
                $arg->name instanceof Node\Identifier
                && $arg->name->name === $name
                && $arg->value instanceof Node\Scalar\String_) {
                return true;
            }
        }

        return false;
    }

    public function configure(array $configuration): void
    {
        Assert::allStringNotEmpty($configuration);
        $this->except = [...$this->except, ...$configuration];
    }
}

使用

rector 配置文件中配置该规则即可

<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;

return static function (RectorConfig $rectorConfig): void {
    ...
    $rectorConfig->ruleWithConfiguration(\App\Support\Rectors\RenameToPsrNameRector::class, [
        'exceptName',
    ]);
    ...
};

参考链接

原文链接

标签:node,Node,return,name,method,命名,风格,规范化,class
From: https://www.cnblogs.com/guanguans/p/17385928.html

相关文章

  • 【开源游戏】Legends-Of-Heroes 基于ET 7.2的双端C#(.net7 + Unity3d)多人在线英雄联
    Legends-Of-Heroes一个LOL风格的球球大作战游戏,基于ET7.2,使用状态同步 Main基于C#双端框架[ET7.2],同步到ET主干详情请看日志。(https://github.com/egametang/ET)注意:已经升级.Net7,请安装.Net7SDK.此游戏为ET7.2的一个实践项目demo,玩法主要是球球大作战类型的吃食物吃敌人/......
  • node使用fs.rename重命名文件的时候,如果有该名称的文件会被替换的问题
    再项目中使用fs.rename给快捷方式重命名的时候,因为有两个版本,在开发人员电脑上都安装两个版本的时候,发现每次都只有快捷方式,然后在重新查看代码的时候。发现代码中使用到了fs.rename去重命名文件。于是做了以下处理letnewLnkPath=path.join(桌面地址,`{appName}.lnk`)if(exi......
  • K8S:分享一次“乌龙问题”(人为导致的无法正常删除命名空间)
    问题背景背景是这样的,我有一套测试用的K8S集群,发现无法正常删除命名空间了,一直处于Terminating状态,强制删除也不行。于是,再次手动创建了一个名为“test-b”的命名空间,同样也是不能正常删除。于是,展开了排查。不过,查到最后,发现是个毫无技术含量的“乌龙问题”。结果不重要,重要的......
  • 命名空间
    参考资料:6-命名空间_哔哩哔哩_bilibili1、什么是命名空间?一个区域、一个包裹、一个作用域、一个范围2、举例#include<iostream>namespacekkb{classWasher{public:std::stringstr;intvol;voidgetstr();voidwash();};v......
  • 使用 NutUI 搭建「自定义业务风格」的组件库 | 京东云技术团队
    本文介绍,如何使用NutUI组件库,搭建一套为专属业务风格的业务组件库。NutUI是一款京东风格的移动端组件库。NutUI目前支持Vue和React技术栈,支持Taro多端适配。当下的实现方式一般组件库,都会给用户提供修改主题的方式。比如在NutUI组件库中,给用户提供了两种方式:修改CSS变量,Nu......
  • C++ 命名空间
    C++命名空间假设这样一种情况,当一个班上有两个名叫Zara的学生时,为了明确区分它们,我们在使用名字之外,不得不使用一些额外的信息,比如他们的家庭住址,或者他们父母的名字等等。同样的情况也出现在C++应用程序中。例如,您可能会写一个名为xyz()的函数,在另一个可用的库中也存在......
  • 软件架构风格-黑板架构风格(Blackboard architecture)
    参考链接:https://cs.uwaterloo.ca/~m2nagapp/courses/CS446/1181/Arch_Design_Activity/Blackboard.pdfhttp://users.encs.concordia.ca/~gregb/home/PDF/soen6461_blackboard_arch.pdf......
  • 根据 大峡谷国家公园, 写一首李白风格的诗
    大峡谷,天然屏障,险峻绝壁挡云霄。沉淀岁月千万载,鬼斧神工刻画成。石壁上,千仞悬崖,奇峰怪石耸苍天。百里观音俯世间,宏伟壮阔震人心。流云间,孤鹰翱翔,蔚蓝天空放眼望。仰望群峰云雾里,犹如仙境梦中藏。李白曾谱华章诗,今我到此叹惊叹。壮观壮美妙不可言,大自然之美亘古传。......
  • k8s 使用 RBAC 鉴权 建立不同用户使用k8s。只有指定命名空间的权限
    k8s使用RBAC鉴权https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/rbac/#创建sa账号kubectlcreatesasa-test-20230408#使用sa账号创建pod资源[root@master01sa]#catpod.yamlapiVersion:v1kind:Podmetadata:name:sa-test-pod-20230408......
  • REST风格开发
    REST(RepresentationalStateTransfer),表现形式状态转换,是一种资源描述形式根据REST风格对资源进行访问称为RESTful优点:隐藏资源的访问行为,无法通过地址得知对资源是何种操作书写简化示例@PostMappingpublicStringsave(@RequestBodyBookbook){Sys......