确定字符串是否为camelCase

时间:2015-03-09 18:18:55

标签: php camelcasing phpcodesniffer

我试图让PHP_CodeSniffer检查类名中的camelCase,但是在我看来,camelCase检查是不可能的(没有字典,包括 techy 字样)。

我已经对互联网进行了调整,但到目前为止,我所看到的唯一选择是,如果字符串有一些常见的分隔符可以爆炸 - 即下划线,单词之间的空格等。

如果名称​​准确/始终在每个单词之间包含分隔符,则检查只能是准确的。 并且"检查"将确定名称是否格式不正确,这可能包括没有正确分隔。

此外,PHP_CodeSniffer上的资源要么很少,要么只有作者/开发人员才能理解它的基础和技术。

当前标准嗅探检查

我在一些当前的Sniffs(即Squiz和PEAR标准)中找到了这段代码:

if (PHP_CodeSniffer::isCamelCaps($functionName, false, true, false) === false) 

但是,我查看了PHP_CodeSniffer核心代码,此函数仅执行以下操作:

// Check the first character first.
// Check that the name only contains legal characters.
// Check that there are not two capital letters next to each other.
// The character is a number, so it cant be a capital.

这些基本检查总比没有好,虽然对于他们所谓的预期用途可能没用,因为他们根本没有真正检查camelCase。

问题

Sniff(或PHP脚本)如何知道哪些"单词"检查给定的字符串以确定该字符串是否为100%camelCase?


修改

实施例

正确的camelCase:class calculateAdminLoginCount

// Not camelCase
class calculateadminlogincount

// Partially camelCase
class calculateadminLogincount

isCamelCaps()函数(或任何PHP脚本)如何捕获上述两个示例?

该函数或PHP脚本如何识别"单独的单词"从一个字符串,当它没有"字"的概念时没有提供那些信息(即从字典中)?

即使脚本在哪里爆炸,它会在哪些基础上爆炸?

class calculateadminLogincount
任何PHP脚本如何识别calculate admin Login count是该字符串中的不同单词,然后才能检查:第一个字母第一个单词是小写,然后全部后续的单词第一个字母是大写的?

isCamelCaps()功能

public static function isCamelCaps(
    $string,
    $classFormat=false,
    $public=true,
    $strict=true
) {

        // Check the first character first.
        if ($classFormat === false) {
            $legalFirstChar = '';
            if ($public === false) {
                $legalFirstChar = '[_]';
            }

            if ($strict === false) {
                // Can either start with a lowercase letter, 
                // or multiple uppercase
                // in a row, representing an acronym.
                $legalFirstChar .= '([A-Z]{2,}|[a-z])';
            } else {
                $legalFirstChar .= '[a-z]';
            }
        } else {
            $legalFirstChar = '[A-Z]';
        }

        if (preg_match("/^$legalFirstChar/", $string) === 0) {
            return false;
        }

        // Check that the name only contains legal characters.
        $legalChars = 'a-zA-Z0-9';
        if (preg_match("|[^$legalChars]|", substr($string, 1)) > 0) {
            return false;
        }

        if ($strict === true) {
            // Check that there are not two capital letters 
            // next to each other.
            $length          = strlen($string);
            $lastCharWasCaps = $classFormat;

            for ($i = 1; $i < $length; $i++) {
                $ascii = ord($string{$i});
                if ($ascii >= 48 && $ascii <= 57) {
                    // The character is a number, so it cant be a capital.
                    $isCaps = false;
                } else {
                    if (strtoupper($string{$i}) === $string{$i}) {
                        $isCaps = true;
                    } else {
                        $isCaps = false;
                    }
                }

                if ($isCaps === true && $lastCharWasCaps === true) {
                    return false;
                }

                $lastCharWasCaps = $isCaps;
            }
        }//end if

        return true;

    }//end isCamelCaps()

编辑2

对于那些想知道这是否值得的人,或者如果我只是&#34;搞乱&#34;和#34;玩得开心&#34;:

必须始终正确命名类名,因为文件/文件夹结构以及名称和类名必须匹配才能使自动加载器稳定工作。

虽然如果无法加载脚本,类等等,我检查并处理此类问题时,我会检查和处理此类问题,但是通过所有其他脚本(PHP_CodeSniffer)运行并没有错文件并告诉我可能存在的问题 即使只进行第二次检查,特别是因为它还确保代码库整洁,结构正确,并且始终具有连续性。

2 个答案:

答案 0 :(得分:0)

您可以通过拆分案例转换的单词来分析函数名称以获得正确的大小写。对于原始函数名称的每个部分,在字典或字典+行话文件中查找该子字('calc','url','admin'等(可能先检查行话))。如果任何子词失败,则没有适当的大写字母。

您可以使用Solr或ElasticSearch使用Lucene中的WordDelimiterFilter为您分开单词。这将在案例发生变化时创建子词:

"PowerShot" -> "Power" "Shot" "LoginURL" => "Login" "URL"

您可以将这些单词直接插入这些NoSQL数据库并稍后进行分析,或者您可以(至少在ES中)使用单词分隔符标记过滤器来分解查询而不实际保存结果。

http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/analysis-word-delimiter-tokenfilter.html

https://wiki.apache.org/solr/AnalyzersTokenizersTokenFilters#solr.WordDelimiterFilterFactory

示例:

calcAdminLogin =&gt; calc Admin登录

calcadminlogin =&gt; calcadminlogin

如果您的补充词典中包含“calc”和“admin”等词,那么第一个函数名将分解为3个将出现在字典中的单词,因此驼峰案例是正确的。

在第二个例子中,'calcadminlogin'将无法在字典中找到,因此驼峰套管不正确。

答案 1 :(得分:0)

我已经制作了一些脚本来尝试“松散地”识别类名是否为camelCase。

我为我的场景编写的一些脚本对其他人没有帮助,例如他们特定于我自己的命名约定(我没有把它们包含在这里)。
所以我的实际脚本集合使这一切都值得,但希望下面更通用的脚本将帮助其他人。

例如,我使用小写字母为类名添加前缀,因此我检查该前缀后面的单词是否为大写 对于那些不使用特定单词为类名添加前缀的人(大多数人),那么检查字符串的第一个字符是小写是很容易的。

批评非常欢迎。


仅允许混合大小写alpha

这确保类名只包含大写或小写字母(Az),这是camelCase检查所需的(如果删除此脚本,则需要更改其他脚本以适应潜在的非alpha字符)。

/** Check string is only alpha (A-z) */
if (ctype_alpha($name) === false) {
  $error = '%s name must only contain alpha chars (A-z)';
  $phpcsFile->addError($error, $stackPtr, 'AlphaChars', $errorData);
  return;
}

没有两个大写字符

某些标准允许使用首字母缩略词等,但我的标准不允许这样做,因为它不是严格的camelCase并打破了阅读流程。

e.g。 userSitePHPLogin无效,userSitePhpLogin有效。

(有一种更优雅的方式可以做到这一点,但它工作得很好,并且考虑到PHP_CodeSniffer,我不需要微优化)

/** Check for uppercase chars together */
$nameUppercaseExplode = preg_split('/(?=[A-Z])/', $name);
$totalIllegalUpperChars = 0;

foreach ($nameUppercaseExplode as $namePiece) {
  if (strlen($namePiece) == 1) {
    $totalIllegalUpperChars++;
  }
}

if ($totalIllegalUpperChars >0) {
  $warning = 'Class name seems invalid; 
  Total '.$totalIllegalUpperChars.' uppercase chars not part of camelCase';
  $phpcsFile->addWarning($warning, $stackPtr, 'UppercaseTogether', $errorData);
}

e.g。类名DUserPHPUserclassLogin返回:

  

班级名称似乎无效;共有4个大写字符不属于camelCase

这不完美,因为它在那张支票上是1 但是如果一起出现至少1次大写,它只会返回警告。

e.g。类名classDUserPhpUserLogin返回:

  

班级名称似乎无效;总共1个大写字符不属于camelCase

因此,这至少会提示开发人员检查名称并根据需要进行修复。


检查总大写字母是否小于总字数

感谢sjagr的想法。

“总词数”当然是一个“猜测”数字,基于每个单词的5个字符平均值 - 因为看起来官方平均值大约是每个字平均值4.7个字符。

/** Loose check if total (guessed) words not match total uppercase chars */
$totalWordsGuess = ceil(strlen($name) / 5);
$totalUpperChars = strlen(preg_replace('![^A-Z]+!', '', $name));

// Pointless if only 1 word (camelCase not exist)
if ($totalWordsGuess >1) {

  // Remove the first word which should be lowercase
  // (first word should be checked in separate check above this one)
  $totalWordsGuess--;

  if ($totalUpperChars < $totalWordsGuess) {
    $warning = 'Expected '.$totalWordsGuess.' camelCase words in class name; 
    Found '.$totalUpperChars;
    $phpcsFile->addWarning($warning, $stackPtr, 'BadCamelCase', $errorData);
  }

}

我已经对它进行了测试并且效果很好(这只是对潜在问题的警告)。

例如,使用类名UserLoginToomanywordsWithoutcamelCase,PHP_CodeSniffer返回:

  

课堂名称中有7个camelCase单词;找到5

如果返回的误报太多(不同的开发者使用不同的单词等),则将当前的“5”向上或向下调整一个档位。

修改:更新了以上脚本:

  • 添加条件,因此脚本仅在超过1个单词时运行,为1个单词 不能是camelCase。
  • 添加了代码,以便从总猜测的单词(var --)中扣除1 帐户的第一个单词是小写,因此没有大写计数 将存在。

您应该在此上方单独检查以检查第一个单词,如果第一个单词不是小写,则returns