
# Cmetrics工具规格说明
#### 工具介绍
Cmetrics是华为公司自研代码度量工具，通过扫描源码对各项指标进行度量。度量指标包括代码量、函数圈复杂度、文件代码行、函数代码行、文件重复、代码重复、危险函数、冗余代码等多项指标。当前工具版本为2.1.5。
#### 参数说明
表1参数说明 
| 参数                                   | 说明                                                                                                                                                                                                                                                                                                        |
|:---|:---|
| code_size                            | 代码规模。 统计工程中删除空行和注释行后的代码行数量。                                                                                                                                                                                                                                            |
| raw_lines                            | 原始代码行数。 统计工程中所有代码文件的物理行总数，包含空行和注释行。                                                                                                                                                                                                                                   |
| methods_total                        | 函数总数。 统计工程中所有代码文件的方法总个数。其中Java抽象方法的方法声明后不带函数体，不会被识别成函数。                                                                                                                                                                                                                |
| cyclomatic_complexity_total          | 圈复杂度总数。 统计所有函数圈复杂度数的总和。 method默认圈复杂度为1，每出现特定关键字一次，则圈复杂度加1，出现三目运算符圈复杂度加1。 圈复杂度与cca圈复杂度的区别在于switch语句统计方式：圈复杂度计算时switch里面有几个case，圈复杂度就加几，而cca圈复杂度计算时，无论switch里面有几个case，圈复杂度只加1。                   |
| cyclomatic_complexity_per_method     | 平均圈复杂度。 平均圈复杂度=圈复杂度总数/函数总数                                                                                                                                                                                                                                            |
| maximum_cyclomatic_complexity        | 最大圈复杂度。 代码检查任务执行完成后，统计所有函数中圈复杂度最大的值。                                                                                                                                                                                                                                  |
| huge_cyclomatic_complexity_total     | 超大圈复杂度函数总数。 统计圈复杂度大于阈值的函数个数。其中阈值由Cmetrics工具版本决定，详情可参考[表2]；部分语言可通过Cmetrics规则修改。                                                                                                                                                   |
| huge_cyclomatic_complexity_ratio     | 超大圈复杂度比例。 超大圈复杂度比例=超大圈复杂度数/函数总数\*100（单位：百分比%）                                                                                                                                                                                                                         |
| cca_cyclomatic_complexity_total      | cca圈复杂度总数。 统计所有函数cca圈复杂度数的总和。 method默认圈复杂度为1，每出现特定关键字一次，则圈复杂度加1，出现三目运算符圈复杂度加1。 圈复杂度与cca圈复杂度的区别在于switch语句统计方式：圈复杂度计算时switch里面有几个case，圈复杂度就加几，而cca圈复杂度计算时，无论switch里面有几个case，圈复杂度只加1。           |
| cca_cyclomatic_complexity_per_method | cca平均圈复杂度。 cca平均圈复杂度=cca圈复杂度总数/函数总数                                                                                                                                                                                                                                  |
| maximum_cca_cyclomatic_complexity    | cca最大圈复杂度。 代码检查任务执行完成后，统计所有函数中cca圈复杂度最大的值。                                                                                                                                                                                                                             |
| huge_cca_cyclomatic_complexity_total | 超大cca圈复杂度函数总数。 统计cca圈复杂度大于阈值的函数个数。其中阈值由Cmetrics工具版本决定，部分语言可通过Cmetrics规则修改。                                                                                                                                                                                            |
| cyclomatic_complexity_adequacy       | 圈复杂度满足度。 圈复杂度满足度=((函数总数-超大cca圈复杂度函数总数) / 函数总数)\*100（单位：百分比%） cyclomatic complexity adequacy的缩写即为cca。                                                                                                                            |
| maximum_depth                        | 最大深度。 代码检查任务执行完成后，统计所有函数中深度最大的值。                                                                                                                                                                                                                                       |
| huge_depth_total                     | 超大深度数。 统计最大深度大于阈值的函数个数。其中阈值由Cmetrics工具版本决定，详情可参考[表2]；部分语言可通过Cmetrics规则修改。                                                                                                                                                      |
| huge_depth_ratio                     | 超大深度占比。 超大深度占比=超大深度数/函数总数（单位：百分比%）                                                                                                                                                                                                                                   |
| method_lines                         | 函数总行数。 统计所有函数的非空非注释行代码行总和。 注意：在去掉空行注释行以后，统计函数内部代码块的行数，函数开头定义行不统计在内。                                                                                                                                                              |
| lines_per_method                     | 函数平均代码行。 函数平均代码行=函数总行数/函数总数                                                                                                                                                                                                                                           |
| huge_method_total                    | 超大函数数。 函数代码行大于阈值的函数个数。其中阈值由Cmetrics工具版本决定，详情可参考[表2]；部分语言可通过Cmetrics规则修改。                                                                                                                                                      |
| huge_method_ratio                    | 超大函数占比。 超大函数占比=超大函数数/函数总数\*100（单位：百分比%）                                                                                                                                                                                                                                 |
| files_total                          | 文件总数。 扫描工程目录中符合源码文件后缀名的文件总个数，其中空文件不会统计在内。不同语言对应的文件后缀可参考[表3]。                                                                                                                                                                  |
| folders_total                        | 目录总数。 工程里目录的总个数。其中空目录不会被计算在内。                                                                                                                                                                                                                                         |
| lines_per_file                       | 文件平均代码行。 文件平均代码行=代码行总数/文件总数                                                                                                                                                                                                                                          |
| huge_headerfile_total                | 超大头文件数。 C语言源码文件中后缀名为".h"，".hh"，".hpp"，".hxx"，".h++"，".inc"，".inl"的被认为是头文件，其中有效代码行大于阈值的认为是超大头文件。其中阈值由Cmetrics工具版本决定，详情可参考[表2]。                                                                                                    |
| huge_headerfile_ratio                | 超大头文件占比。 超大头文件占比=超大头文件数/文件总数\*100（单位：百分比%）                                                                                                                                                                                                                           |
| huge_non_headerfile_total            | 超大源文件数。 源码文件中后缀名不为头文件，并且有效代码行大于阈值的认为是超大源文件。其中阈值由Cmetrics工具版本决定，详情可参考[表2]；部分语言可通过Cmetrics规则修改。                                                                                                                                  |
| huge_non_headerfile_ratio            | 超大源文件占比。 超大源文件占比=超大源文件数/文件总数\*100（单位：百分比%）                                                                                                                                                                                                                            |
| huge_folder_total                    | 超大目录数。 统计某目录内的文件和子目录总数（不计算该目录节点下子目录下更深层次的子目录数和文件数），当总数大于阈值时，则判断为超大目录。空子目录（子目录里面没有源码文件的）不计算在内。其中阈值由Cmetrics工具版本决定，详情可参考[表2]；部分语言可通过Cmetrics规则修改。                                                                                |
| huge_folder_ratio                    | 超大目录占比。 超大目录占比=超大目录数/目录总数\*100（单位：百分比%）                                                                                                                                                                                                                              |
| file_duplication_total               | 重复文件数。 统计文件内容完全相同的文件个数。仅统计后缀名符合各语言源码文件后缀名的文件，不同语言对应的文件后缀可参考[表3]。                                                                                                                                                             |
| file_duplication_ratio               | 文件重复率。 文件重复率=重复文件数/文件总数\*100（单位：百分比%）                                                                                                                                                                                                                                  |
| non_hfile_duplication_total          | 重复源文件数。 统计C语言重复文件中后缀名为源文件的文件个数。其他语言没有头文件，所有文件都是源文件。                                                                                                                                                                                                                  |
| non_hfile_duplication_ratio          | 源文件重复率。 源文件重复率=重复源文件数/文件总数\*100（单位：百分比%）                                                                                                                                                                                                                               |
| code_duplication_total               | 代码重复数。 非空非注释行连续10行相同的代码片段和import行（第三方机构标准），会被识别是重复代码。 说明： 代码重复数是过每个文件的重复代码行相加得出，而不是以重复代码明细结果里的代码片段相加。如：三个文件都有相同的10行重复代码，则代码重复数为30；如：A文件1\~10行与B文件重复，A文件2\~11行与C文件重复，则取代码片段并集的行数，A文件重复代码行为11行。 |
| code_duplication_ratio               | 代码重复率。 代码重复率=代码重复数/代码行总数\*100（单位：百分比%）                                                                                                                                                                                                                                 |
| non_hfile_code_duplication_total     | 源文件代码重复数。 源文件的代码重复行数总数。即只统计后缀名符合源代码文件（C/C++语言不包含头文件）要求的文件的重复代码行。                                                                                                                                                                                                      |
| non_hfile_code_duplication_ratio     | 源文件代码重复率。 源文件代码重复率=源文件代码重复数/代码行总数（单位：百分比%）                                                                                                                                                                                                                           |
| unsafe_functions_total               | 危险函数总数。 统计代码中出现调用不安全函数，如memcpy、memmove等函数的调用次数。 说明： 目前clike检查不安全函数，其他语言不检查该指标。                                                                                                                 |
| unsafe_functions_kloc                | 危险函数密度（每千行代码中包含的危险函数个数）。 危险函数密度=危险函数总数/代码行总数\*1000                                                                                                                                                                                                                   |
| redundant_code_total                 | 冗余代码数。 统计注释中冗余代码块的个数。注释中的代码被视作冗余代码；注释中包含编程语言关键字的或符合语法规则的连续单词组会被判断为冗余代码。 其中块注释有多行冗余代码，只算一次冗余代码数。                                                                                                                                  |
| redundant_code_kloc                  | 冗余代码块密度（每千行代码中包含的冗余代码数）。 冗余代码块密度=冗余代码数/代码行总数\*1000 说明： 如果代码行总数少于1000，不计算密度，取值为0。                                                                                                         |
| warning_suppression_total            | 抑制告警数。 统计被扫描文件的告警抑制语句出现的数量。注释中的字符串符合特定正则表达式，则会被认为是告警抑制语句。不同语言对应的正则表达式请参考[表5]。 该参数需启用Cmetrics规则后生效。                                                                                      |
| warning_suppression_kloc             | 抑制告警密度。 抑制告警密度=抑制告警数/代码行总数\*1000（每千行代码中包含的冗余代码数） 该参数需启用Cmetrics规则后生效。                                                                                                                                                            |
   
 表2Cmetrics工具默认阈值 
| 阈值名称            | 默认值  |
|:---|:---|
| 超大圈复杂度函数-圈复杂度阈值 | 20   |
| 超大深度数函数-深度阈值    | 4    |
| 超大函数-行数阈值       | 50   |
| 超大头文件-行数阈值      | 500  |
| 超大源文件-行数阈值      | 2000 |
| 超大目录数-节点阈值      | 50   |
   
 表3Cmetrics工具编程语言与文件扩展名关联关系 
| 语言         | 后缀                                                            |
|:---|:---|
| JAVA       | .java                                                         |
| C/C++      | .c/.cc/.cpp/.cxx/.cp/.c++/.inc/.inl/.mm/.h/.hh/.hpp/.hxx/.h++ |
| TYPESCRIPT | .ts/.tsx                                                      |
| RUST       | .rs                                                           |
| ARKTS      | .ets                                                          |
| C#         | .cs                                                           |
| GO         | .go                                                           |
| JAVASCRIPT | .js/.jsx                                                      |
| LUA        | .lua                                                          |
| PYTHON     | .py                                                           |
   
表4Cmetrics工具支持检查C/C++的危险函数列表 
|  _fstrncat   |  _vsntprintf  |   strcatbuff   | vos_nsprintf  |
|---|---|---|---|
| _fstrncpy    | _vsnwprintf   | strcatbuffa    | vos_nvsprintf |
| _ftcscat     | _vstprintf    | strcatbuffw    | vos_snprintf  |
| _ftcscpy     | bcopy         | strcatchainw   | vos_sprintf   |
| _getts       | copymemory    | strcatn        | vos_sscanf    |
| _gettws      | fscanf        | strcatna       | vos_strcat    |
| _getws       | fwscanf       | strcatnw       | vos_strcpy    |
| _mbccat      | gets          | strcatw        | vos_strncat   |
| _mbccpy      | lstrcat       | strcpy         | vos_strncpy   |
| _mbscat      | lstrcata      | strcpya        | vos_vsprintf  |
| _mbscpy      | lstrcatn      | strcpyn        | vos_vsscanf   |
| _mbsnbcat    | lstrcatnA     | strcpyna       | vscanf        |
| _mbsnbcpy    | lstrcatnW     | strcpynw       | vsnprintf     |
| _mbsncat     | lstrcatw      | strcpyw        | vsprintf      |
| _mbsncpy     | lstrcpy       | strncat        | vsscanf       |
| _snprintf    | lstrcpya      | strncata       | vswprintf     |
| _sntprintf   | lstrcpyn      | strncatw       | vswscanf      |
| _sntscanf    | lstrcpyna     | strncpy        | vwscanf       |
| _snwprintf   | lstrcpynw     | strncpya       | wcscat        |
| _stprintf    | lstrcpyw      | strncpyw       | wcscpy        |
| _stscanf     | lstrncat      | swprintf       | wcsncat       |
| _tccat       | memcpy        | swscanf        | wcsncpy       |
| _tccpy       | memmove       | vfscanf        | wmemcpy       |
| _tcscat      | memset        | vfwscanf       | wmemmove      |
| _tcscpy      | nsprintf      | vos_chkmemcpy  | wnsprintf     |
| _tcsncat     | rtlcopymemory | vos_chkmemmove | wnsprintfA    |
| _tcsncpy     | scanf         | vos_chkmemset  | wnsprintfW    |
| _tscanf      | snprintf      | vos_chkstrcat  | wscanf        |
| _vos_bzero   | snscanf       | vos_chkstrcpy  | wsprintf      |
| _vos_memcpy  | sntprintf     | vos_chkstrncat | wsprintfa     |
| _vos_memmove | snwscanf      | vos_chkstrncpy | wsprintfw     |
| _vos_memset  | sprintf       | vos_mem_copy   | wvnsprintf    |
| _vos_strcat  | sprintfa      | vos_mem_set    | wvnsprintfa   |
| _vos_strcpy  | sprintfw      | vos_mem_zero   | wvnsprintfw   |
| _vos_strncat | sscanf        | vos_memcpy     | wvsprintf     |
| _vos_strncpy | strcat        | vos_memmove    | wvsprintfa    |
| _vsnprintf   | strcata       | vos_memset     | wvsprintfw    |
   
 表5Cmetrics工具告警抑制规则 
| 语言类型                             | 注释匹配正则表达式                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
|:---|:---|
| C/C++、JAVA、JAVASCRIPT、TYPESCRIPT | - r'(/(\\\*\|/)\\s\*(lint\\b\\s+\\S+\|coverity\\s\*\\\[.+?\\\]\|eslint-disable)'  - r'\|\^\\s\*#\\s\*pragma\\s+\\w+\\s+diagnostic\\s+(ignored\|warning)'  - r'\|\^\\s\*#\\s\*pragma\\s+warning\\s\*\\(\\s\*disable'  - r'\|\^\\s\*@(\\w+\\.)?SuppressWarnings)'   |
| PYTHON                           | r'#\\s\*pylint\\s\*:'                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
   
