OCLint官方规则文档中文说明

本文详细介绍了OClint工具用于检查Objective-C代码质量的各项规则,包括基本规则、Cocoa特定规则、命名规范、冗余检查等内容,帮助开发者提高代码质量和可维护性。

简书作者:帅裂苍穹的七爷爷

原文链接:http://www.jianshu.com/p/35cf99c07eaa

本文基于OClint官方文档进行翻译,本章顺序与官网相同,如果查看后仍不能明白问题原因,请前往官方文档查看示例,官方文档地址

Basic

1.Bitwise operator in conditional

说明:对于按位与或者按位或的情况,OClint认为这不便于理解。

2.Broken Nil Check

说明:nil检查,在某些情况会返回相反的结果

3.Broken Null Check

说明:NULL检查会导致程序crash

4.Broken Oddness Check

说明:X%2==1对负数不起作用,需要使用X&1 ==1或者X%2!=0来代替

5.collapsible if statements

说明:判断两个相连的if是否能够合并

6.Constant Conditional Operator

说明:条件是否永远为true或者永远false?

7. constant if expression

说明:if判断中的值是恒定的,比如if(true),其中的值永远为真。

8.dead code

说明:表示标示位置有永远不会被执行的代码。

9.Double Negative

说明:表示不需要使用双重否定,形如!!1,~~1等,因为这并没有用处。

10.ForLoop Should Be WhileLoop

说明:表示此处不应该用for循环而应该使用while循环。

10.Goto Statement

说明:提示谨慎使用Goto语句。

11.Jumbled Incrementer

说明:混乱的增量,多数出现在嵌套for循环中,如果不是因为笔误写错了,那么这种混乱的写法容易造成代码阅读的问题。

12.Misplaced Null Check

说明:Null Check被放错地方,在OC中向一个空指针发送消息并不会发生什么,但是在C或者C++中可能会引起crash,同时可能会造成代码阅读的困惑。

13.Multiple Unary Operator

说明:多重一元操作很难被理解。形如:int b = -(+(!(~1)));)

14.Return From Finally Block

说明:在最后一个block中return的做法是不推荐的。

15.Throw Exception From Finally Block

说明:不要在最后一个BLOCK中抛出异常,因为这样的情况可能会掩盖其他异常或者代码缺陷。

Cocoa(OC)

1.Must Override Hash With IsEqual

说明:如果重写isEqual,一定也要重写hash,原名为ObjCVerifyIsEqualHash。

2.Must Call Super

说明:提示需要增加call super的情况,例如layoutSubviews方法,需要添加[super layoutSubviews].

3.Verify Prohibited Call

说明:当一个方法声明时含有attribute((annotate("oclint:enforce[prohibited call]"))),它的所有调用都是被禁止的。

4.Verify Protected Method

说明:当一个方法声明含有attribute((annotate("oclint:enforce[protected method]")))时,只有它和它的子类可以调用,因为OC中没有Protected,可以用这种方式达到Protected效果。

5.Subclass Must Implement

说明:子类必须实现,哪怕是一个抽象方法。

Convention

1.Avoid Branching Statement As Last InLoop

说明:表示不要在for循环或者其他循环语句的末尾使用break.

2.Base Class Destructor Should Be Virtual Or Protected

说明:基类的析构函数要么是公共的虚函数,要么是保护性的非虚函数。

3.covered switch statements dont need default

说明:因为已经覆盖了所有的switch分支,所以不需要写default break部分。

4.Default Label Not Last In Switch Statement

说明:DeFault没有放在Switch的最后一行。

5.Destructor Of VirtualClass

说明:本规则强制要求虚类的析构函数必须也是虚函数。

6.Inverted Logic

说明:反转逻辑让人难以理解。一般是指用(!a)而非(a)来判断让人难以理解。

7.Missing Break In Switch Statement

说明:在Switch中如果缺少break很容易引入bug.

8.Non Case Label In Switch Statement

说明:不要把label放到switch中。

9.ivar assignment outside accessors or init

说明:意思是某些成员的初始化不在getter/setter或者init中,而在其他位置。

10.parameter reassignment

说明:通常认为是赋值问题,具体问题需要具体判断,有的时候是因为对传来的参数进行了重新赋值,大多数时候不能修改。

11.use early exits and continue

说明:意思是,有其他出口时,先执行其他出口,再继续代码。

12.Switch Statements Should Have Default

说明:如果并不是每一个分支都有一条路径,那么switch重必须含有default.

13.Too Few Branches In Switch Statement

说明:Switch中分支很少,可以用if代替。

Design

1.Avoid Default Arguments On Virtual Methods

说明:避免给虚函数设置默认参数,给虚函数设置默认参数会破坏多样性和引起不必要的层次结构发杂性。

2.Avoid Private Static Members

说明:避免使用私有静态成员,静态成员很容易破换封装性。

Empty

1.Empty Catch Statement

说明:主要发生在一个异常exception被catch到了,但是却没有对此做任何操作。

2.Empty Do While Statement

说明:在do-while循环中没有做任何事情。

3.Empty Else Block

说明:在if中有操作,else中却是空的,此时else可以被安全移除。

4.Empty Finally Statemen

说明:在@finally中没有进行任何操作。

5.Empty For Statement

说明:for循环为空。

6.Empty If Statement

说明:if中代码为空。

7.Empty Switch Statement

说明:Switch中代码为空。

8.Empty Try Statement

说明:try中代码为空。

9.Empty While Statement

说明:While循环中没有代码。

Migration

1.Replace With Boxed Expression

说明:用来说明umberWithInt和stringWithUTF8String:getenv的简写形式。

2.Replace With Container Literal

说明:用来说明arrayWithObjects和dictionaryWithObjects的简写形式。

3.replace with number literal

说明:用来说明numberWithInt和numberWithBOOL的简写形式。

4.replace with object subscripting

说明:用来说明objectAtIndex和objectForKey的简写形式。

Naming

1.Long Variable Name

说明:命名太长。

2.Short Variable Name

说明:命名过短。

Redundant

1.Redundant Conditional Operator

说明:冗余的条件运算符,可以一步到位的判断,不需要进行多余比较。

2.Redundant If Statement

说明:if判断是多余的。

3.Redundant local variable

说明:return中的参数可以使用一个表达式来表示。

4.RedundantNilCheck

说明:在C或者C++中适用的判空检查在OC中是多余的。因为在OC中向空对象发送消息会返回false值。

5.UnnecessaryElseStatement

说明:如果if中已经带有return,则不需要写else语句。

6.Unnecessary Null Check For Dealloc

说明:在Dealloc中不需要判空,就能Delete元素。

7.useless parentheses

说明:用来表示有些括号是不必要的。

Size

1.High Cyclomatic Complexity

说明:圈复杂度过高。V(G)=e-n+2。其中,e表示控制流图中边的数量,n表示控制流图中节点的数量,或者V(G)=区域数=判定节点数+1。

2.Long Class

说明:类行数太多。

3.Long Line

说明:一行字数过多。

4.Long Method

说明:在一个方法中试图完成很多事情,在一个方法中应该完成一个功能并把它做好。

5.High Ncss Method

说明:其实是指某个代码块中代码行数过多,查看代码块中代码是否能拆分,公共功能能否提供一个公共借口。

6.Deep Nested Block

说明:层次太深,多层嵌套。

7.High NPath Complexity

说明:NPath复杂度是一个方法中各种可能的执行路径总和,一般把200作为考虑降低复杂度的临界点,这里提示NPath复杂度过高。

8.Too Many Fields

说明:一个类中有太多的域表示它的东西太多了,需要进行适当的抽象。

9.Too Many Methods

说明:一个类中方法过多。

10.Too Many Parameters

说明:一个方法中参数过多。

Unused

1.Unused Local Variable

说明:没有被使用的局部变量。

2.Unused Method Parameter

说明:没有被使用的方法参数,请谨慎修改


<think>我们正在讨论OCLint自定义编码规则的问题。根据引用[1]和[4],我们知道OCLint允许用户自定义规则,并且规则是通过编写代码来实现的,这些代码会访问抽象语法树(AST)的节点。 引用[1]提到,我们可以通过`-R`参数指定规则所在的文件夹路径,然后在启动OCLint时加载这些规则。 引用[4]则详细说明了自定义规则的实现方式:OCLint提供了模板代码,其中包含许多以`Visit`开头的方法,这些方法会在遍历AST的相应节点时被调用。 因此,自定义编码规则的基本步骤是: 1. 创建一个规则类,继承自OCLint提供的基类(例如`oclint::Rule`)。 2. 在规则类中重写`Visit`方法,针对你关心的AST节点类型编写检查逻辑。 3. 在规则类中注册该规则(使用宏`OCLINT_REGISTER_RULE`)。 4. 将编译好的规则(动态库)放在指定目录,然后通过`-R`参数指定该目录运行OCLint。 下面是一个简化的示例,展示如何创建一个检查if语句后面是否总是有花括号的规则: 注意:以下代码为C++示例,因为OCLint是用C++编写的。 ```cpp #include "oclint/Rule.h" #include "oclint/RuleSet.h" class AlwaysUseBracesWithIfRule : public Rule { public: virtual const string name() const override { return "always use braces with if"; } virtual int priority() const override { return 3; // 优先级,1为最高,3为最低 } virtual void apply() override { // 这里会遍历AST,但是具体实现需要访问if语句节点 } // 我们更常用的是使用Visitor模式来遍历AST节点 bool VisitIfStmt(IfStmt *ifStmt) { // 检查if语句的then部分是否是复合语句(即花括号括起来的) if (!isa<CompoundStmt>(ifStmt->getThen())) { // 如果不是,则报告一个违规 addViolation(ifStmt, this, "if语句后必须使用花括号"); } return true; // 继续遍历 } }; // 注册规则 OCLINT_REGISTER_RULE(AlwaysUseBracesWithIfRule) ``` 以上代码只是一个框架,实际实现需要根据Clang AST的结构来编写。Clang AST的节点类型很多,需要熟悉相应的API。 另外,引用[4]提到,使用脚手架生成的规则模板有近2000行,这是因为模板中包含了所有可能的Visit方法,但我们只需要重写我们关心的节点即可。 为了简化规则编写,OCLint提供了规则脚手架生成工具,可以使用命令`oclint-skeleton`生成规则模板。 总结步骤: 1. 使用`oclint-skeleton`生成规则模板。 2. 修改模板,在相应的Visit方法中编写检查逻辑。 3. 编译规则(通常需要构建为动态库)。 4. 将规则动态库放在一个目录中,运行OCLint时通过`-R`参数指定该目录。 注意:OCLint自定义规则需要编译,因此需要配置相应的编译环境(如CMake、LLVM和Clang开发库等)。 如果你需要更具体的例子,可以参考OCLint官方提供的规则源码:https://github.com/oclint/oclint/tree/master/oclint-rules/rules 这样,你就可以为你的团队定制特定的编码规范了。 §§相关问题§§ 1. OCLint自定义规则需要哪些前置条件? 2. 如何调试OCLint自定义规则? 3. OCLint支持哪些语言的规则自定义? 4. 如何为自定义规则编写测试?</think>### OCLint 自定义编码规则详解 在 OCLint 中自定义编码规则需要以下步骤,核心原理是通过创建自定义规则类来访问代码的抽象语法树(AST),在特定节点触发检查逻辑[^4]: #### 步骤 1:创建规则模板 ```bash # 使用脚手架生成规则模板(约 2000 行基础代码) oclint-skeleton -t MyCustomRule > MyCustomRule.cpp ``` 生成的文件包含所有 AST 节点的回调方法模板(如 `VisitIfStmt`, `VisitCallExpr` 等)[^4]。 #### 步骤 2:实现规则逻辑 在生成的模板中重写关键方法(示例:禁止使用 `goto` 语句): ```cpp // MyCustomRule.cpp class MyCustomRule : public AbstractRule { public: virtual void VisitGotoStmt(GotoStmt *stmt) { // 检测到 goto 语句时触发违规 addViolation(stmt, this, "禁止使用 goto 语句"); } // 规则元数据 virtual const string name() const { return "禁用 goto"; } virtual int priority() const { return 1; } // 优先级 1-3 }; OCLINT_REGISTER_RULE(MyCustomRule) // 注册规则 ``` #### 步骤 3:编译规则 ```bash # 将规则编译成动态库 clang++ -shared MyCustomRule.cpp -o libMyRule.so \ -I /path/to/oclint/include \ -L /path/to/oclint/lib -loclintCore ``` #### 步骤 4:集成与测试 ```bash # 通过 -R 参数加载自定义规则 oclint -R /path/to/custom_rules/ -report-type html -o report.html source.c ``` 输出报告将包含自定义规则的检测结果: ``` Violation: 禁止使用 goto 语句 (规则: 禁用 goto) 位置: source.c:15:5 ``` #### 关键机制 1. **AST 访问器模式** 当 OCLint 解析代码时,遍历到 AST 节点(如 `IfStmt`, `ForStmt`)会自动调用对应的 `VisitXxx` 方法[^4]。 2. **违规报告** 通过 `addViolation()` 方法标记问题位置,支持添加详细说明。 3. **规则优先级** `priority()` 返回值决定严重程度(1=严重错误,3=建议性警告)。 #### 调试技巧 1. 使用 `oclint -debug` 输出 AST 结构 2. 在 Xcode 的 *Arguments Passed On Launch* 添加调试参数[^1] 3. 结合 `clang -Xclang -ast-dump` 查看完整 AST 节点类型 > 提示:官方规则库提供了 200+ 个参考实现:https://github.com/oclint/oclint/tree/master/oclint-rules/rules
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值