Introduction
依赖 OCLint 0.13 版本,共计71条rule。
字段说明:
- Since:规则生效版本
- Name:规则名称
Rule Index
Basic
BitwiseOperatorInConditional
Since: 0.6
Name: bitwise operator in conditional
检查条件语句中的位操作。虽然在一些情况下是故意编写的,但是位操作被认为太”巧妙”了。太巧妙的代码不太容易被理解。
规则定义文件: oclint-rules/rules/basic/BitwiseOperatorInConditionalRule.cpp
示例:
void example(int a, int b)
{
if (a | b)
{
}
if (a & b)
{
}
}
BrokenNullCheck
Since: 0.7
Name: broken null check
错误的 null 检查会导致程序 crash。
规则定义文件: oclint-rules/rules/basic/BrokenNullCheckRule.cpp
示例:
void m(A *a, B *b)
{
if (a != NULL || a->bar(b))
{
}
if (a == NULL && a->bar(b))
{
}
}
BrokenNilCheck
Since: 0.7
Name: broken nil check
Objective-C 中判空操作,在有些情况下会返回预期相反的结果。
规则定义文件: oclint-rules/rules/basic/BrokenNullCheckRule.cpp
示例:
+ (void)compare:(A *)obj1 withOther:(A *)obj2
{
if (obj1 || [obj1 isEqualTo:obj2])
{
}
if (!obj1 && ![obj1 isEqualTo:obj2])
{
}
}
BrokenOddnessCheck
Since: 0.6
Name: broken oddness check
使用 x % 2 == 1 进行奇数检查,如果是负数会不正常,应该使用 x & 1 == 1 或者 x % 2 != 0 这种方式。
规则定义文件: oclint-rules/rules/basic/BrokenOddnessCheckRule.cpp
示例:
void example()
{
if (x % 2 == 1) // violation
{
}
if (foo() % 2 == 1) // violation
{
}
}
CollapsibleIfStatements
Since: 0.6
Name: collapsible if statements
两个连续if语句可以合并为一个,以提高代码的简洁和可读性。
规则定义文件: oclint-rules/rules/basic/CollapsibleIfStatementsRule.cpp
示例:
void example(bool x, bool y)
{
if (x) // these two if statements can be
{
if (y) // combined to if (x && y)
{
foo();
}
}
}
ConstantConditionalOperator
Since: 0.6
Name: constant conditional operator
条件运算符的条件永远为真或永远为假是令人困惑的。
规则定义文件: oclint-rules/rules/basic/ConstantConditionalOperatorRule.cpp
示例:
void example()
{
int a = 1 == 1 ? 1 : 0; // 1 == 1 is actually always true
}
ConstantIfExpression
Since: 0.2
Name: constant if expression
if条件语句永远为真或永远为假是令人困惑的
规则定义文件: oclint-rules/rules/basic/ConstantIfExpressionRule.cpp
示例:
void example()
{
if (true) // always true
{
foo();
}
if (1 == 0) // always false
{
bar();
}
}
DeadCode
Since: 0.4
Name: dead code
return、break、continue 和 throw 语句之后的代码是不可达的,永远不会执行。
规则定义文件: oclint-rules/rules/basic/DeadCodeRule.cpp
示例:
void example(id collection)
{
for (id it in collection)
{
continue;
int i1; // dead code
}
return;
int i2; // dead code
}
DoubleNegative
Since: 0.6
Name: double negative
使用双重否定没有意义,它总是正向的。
规则定义文件: oclint-rules/rules/basic/DoubleNegativeRule.cpp
示例:
void example()
{
int b1 = !!1;
int b2 = ~~1;
}
ForLoopShouldBeWhileLoop
Since: 0.6
Name: for loop should be while loop
在某些情况下,可以将一些 for 循环简化为 while 循环,以使代码更简洁。
规则定义文件: oclint-rules/rules/basic/ForLoopShouldBeWhileLoopRule.cpp
示例:
void example(int a)
{
for (; a < 100;)
{
foo(a);
}
}
GotoStatement
Since: 0.6
Name: goto statement
goto 语句不利于逻辑连贯性。
规则定义文件: oclint-rules/rules/basic/GotoStatementRule.cpp
示例:
void example()
{
A:
a();
goto A; // Considered Harmful
}
References:
Edsger Dijkstra (March 1968). “Go To Statement Considered Harmful”. Communications of the ACM (PDF) 11 (3): 147–148. doi:10.1145/362929.362947.
JumbledIncrementer
Since: 0.7
Name: jumbled incrementer
混乱的增量通常是输入手误,如果是故意这样做的,那么这样的代码会让读者感到非常困惑。
规则定义文件: oclint-rules/rules/basic/JumbledIncrementerRule.cpp
示例:
void aMethod(int a) {
for (int i = 0; i < a; i++) {
for (int j = 0; j < a; i++) { // references both 'i' and 'j'
}
}
}
MisplacedNullCheck
Since: 0.7
Name: misplaced null check
空指针检查放在错误的位置,空指针检查应该放在最前面。在C和c++中,向空指针发送消息可能会导致程序崩溃。当空指针检查放错位置时,要么检查无效,要么检查不正确。
规则定义文件: oclint-rules/rules/basic/MisplacedNullCheckRule.cpp
示例:
void m(A *a, B *b)
{
if (a->bar(b) && a != NULL) // violation
{
}
if (a->bar(b) || !a) // violation
{
}
}
MisplacedNilCheck
Since: 0.7
Name: misplaced nil check
空指针检查在 Objective-C 中,向空指针发送消息是没有任何作用的,但是代码读者可能会对放错位置的空指针检查操作感到困惑。
规则定义文件: oclint-rules/rules/basic/MisplacedNullCheckRule.cpp
示例:
+ (void)compare:(A *)obj1 withOther:(A *)obj2
{
if ([obj1 isEqualTo:obj2] && obj1)
{
}
if (![obj1 isEqualTo:obj2] || obj1 == nil)
{
}
}
MultipleUnaryOperator
Since: 0.6
Name: multiple unary operator
连续多重运算符不易理解,应该简化。
规则定义文件: oclint-rules/rules/basic/MultipleUnaryOperatorRule.cpp
示例:
void example()
{
int b = -(+(!(~1)));
}
ReturnFromFinallyBlock
Since: 0.6
Name: return from finally block
不建议在finally块中return。
规则定义文件: oclint-rules/rules/basic/ReturnFromFinallyBlockRule.cpp
示例:
void example()
{
@try
{
foo();
}
@catch(id ex)
{
bar();
}
@finally
{
return; // this can discard exceptions.
}
}
ThrowExceptionFromFinallyBlock
Since: 0.6
Name: throw exception from finally block
在finally块中抛出异常可能会掩盖其他异常或代码缺陷。
规则定义文件: oclint-rules/rules/basic/ThrowExceptionFromFinallyBlockRule.cpp
示例:
void example()
{
@try {;}
@catch(id ex) {;}
@finally {
id ex1;
@throw ex1; // this throws an exception
NSException *ex2 = [NSException new];
[ex2 raise]; // this throws an exception, too
}
}
Cocoa
MissingHashMethod
Since: 0.8
Name: missing hash method
当重写 isEqual 方法时,也必须重写 hash 方法
规则定义文件: oclint-rules/rules/cocoa/ObjCVerifyIsEqualHashRule.cpp
示例:
@implementation BaseObject
- (BOOL)isEqual:(id)obj {
return YES;
}
/*
- (int)hash is missing; If you override isEqual you must override hash too.
*/
@end
MissingCallToBaseMethod
Since: 0.8
Name: missing call to base method
当使用 __attribute__((annotate("oclint:enforce[must call super]")))
注解时一个方法时, 他的所有实现(包括他自己和子类)都必须调用超类的实现方法。
规则定义文件: oclint-rules/rules/cocoa/ObjCVerifyMustCallSuperRule.cpp
示例:
@interface UIView (OCLintStaticChecks)
- (void)layoutSubviews __attribute__((annotate("oclint:enforce[base method]")));
@end
@interface CustomView : UIView
@end
@implementation CustomView
- (void)layoutSubviews {
// [super layoutSubviews]; is enforced here
}
@end
CallingProhibitedMethod
Since: 0.10.1
Name: calling prohibited method
当一个方式使用__attribute__((annotate("oclint:enforce[prohibited method]")))
注解时, 它的所有用法都将被禁止。
规则定义文件: oclint-rules/rules/cocoa/ObjCVerifyProhibitedCallRule.cpp
示例:
@interface A : NSObject
- (void)foo __attribute__((annotate("oclint:enforce[prohibited method]")));
@end
@implementation A
- (void)foo {
}
- (void)bar {
[self foo]; // calling method `foo` is prohibited.
}
@end
CallingProtectedMethod
Since: 0.8
Name: calling protected method
在 Objective-C 中虽然没有 protected 这个作用范围概念。但在设计的角度,我们有时候希望一个方法只被它自己或者它的子类调用。下面示例中这个方法可以模仿 protected,在有人调用保护方法的时候给出一个警告。
规则定义文件: oclint-rules/rules/cocoa/ObjCVerifyProtectedMethodRule.cpp
示例:
@interface A : NSObject
- (void)foo __attribute__((annotate("oclint:enforce[protected method]")));
@end
@interface B : NSObject
@property (strong, nonatomic) A* a;
@end
@implementation B
- (void)bar {
[self.a foo]; // calling protected method foo from outside A and its subclasses
}
@end
MissingAbstractMethodImplementation
Since: 0.8
Name: missing abstract method implementation
由于 Objective-C 的 runtime 特性,决策尽可能推迟到运行时,所以抽象方法可以被声明,但是没有被实现,该规则用来验证子类是否正确实现抽象方法。
规则定义文件: oclint-rules/rules/cocoa/ObjCVerifySubclassMustImplementRule.cpp
示例:
@interface Parent
- (void)anAbstractMethod __attribute__((annotate("oclint:enforce[abstract method]")));
@end
@interface Child : Parent
@end
@implementation Child
/*
// Child, as a subclass of Parent, must implement anAbstractMethod
- (void)anAbstractMethod {}
*/
@end
Convention
AvoidBranchingStatementAsLastInLoop
Since: 0.7
Name: avoid branching statement as last in loop
在循环中使用分支语句作为最后一个语句是非常令人困惑的,并且可能很大程度上会忘记一些东西从而导致bug。
规则定义文件: oclint-rules/rules/convention/AvoidBranchingStatementAsLastInLoopRule.cpp
示例:
void example()
{
for (int i = 0; i < 10; i++)
{
if (foo(i))
{
continue;
}
break; // this break is confusing
}
}
ProblematicBaseClassDestructor
Since: 0.10.2
Name: base class destructor should be virtual or protected
基类的析构函数需要是 public、virtual 或者 protected、nonvirtual。
规则定义文件: oclint-rules/rules/convention/BaseClassDestructorShouldBeVirtualOrProtectedRule.cpp
示例:
class Base
{
public:
~Base(); // this should be either protected or virtual
}
class C : public Base
{
virtual ~C();
}
References:
Sutter & Alexandrescu (November 2004). “C++ Coding Standards: 101 Rules, Guidelines, and Best Practices”. Addison-Wesley Professional
UnnecessaryDefaultStatement
Since: 0.8
Name: unnecessary default statement in covered switch statement
当 switch 语句覆盖所有可能的情况时,不需要 default 标签,应该删除它。如果 switch 语句没有完全覆盖所有情况,SwitchStatementsShouldHaveDefault 规则将检测出这种情况。
规则定义文件: oclint-rules/rules/convention/CoveredSwitchStatementsDontNeedDefaultRule.cpp
示例:
typedef enum {
value1 = 0,
value2 = 1
} eValues;
void aMethod(eValues a)
{
switch(a)
{
case value1:
break;
case value2:
break;
default: // this break is obsolete because all
break; // values of variable a are already covered.
}
}
MisplacedDefaultLabel
Since: 0.6
Name: ill-placed default label in switch statement
switch 语句中 default 标签不要乱放位置,应该放在最后一个分支位置。
规则定义文件: oclint-rules/rules/convention/DefaultLabelNotLastInSwitchStatementRule.cpp
示例:
void example(int a)
{
switch (a) {
case 1:
break;
default: // the default case should be last
break;
case 2:
break;
}
}
DestructorOfVirtualClass
Since: 0.8
Name: destructor of virtual class
虚拟类的析构函数必须是虚拟的。
规则定义文件: oclint-rules/rules/convention/DestructorOfVirtualClassRule.cpp
示例:
class Base { // class Base should have a virtual destructor ~Base()
public: virtual void f();
};
class Child : public Base {
public: ~Child(); // destructor ~Child() should be virtual
};
InvertedLogic
Since: 0.4
Name: inverted logic
颠倒的逻辑不易理解,做逻辑判断的时候,最好先做 true 判断,再做 false 判断。
规则定义文件: oclint-rules/rules/convention/InvertedLogicRule.cpp
示例:
int example(int a)
{
int i;
if (a != 0) // if (a == 0)
{ // {
i = 1; // i = 0;
} // }
else // else
{ // {
i = 0; // i = 1;
} // }
return !i ? -1 : 1; // return i ? 1 : -1;
}
MissingBreakInSwitchStatement
Since: 0.6
Name: missing break in switch statement
switch 语句中缺失了 break,很大可能引发bug。
规则定义文件: oclint-rules/rules/convention/MissingBreakInSwitchStatementRule.cpp
示例:
void example(int a)
{
switch (a) {
case 1:
break;
case 2:
// do something
default:
break;
}
}
NonCaseLabelInSwitchStatement
Since: 0.6
Name: non case label in switch statement
当 label 成为 switch 语句的一部分时,这是非常令人困惑的。
规则定义文件: oclint-rules/rules/convention/NonCaseLabelInSwitchStatementRule.cpp
示例:
void example(int a)
{
switch (a) {
case 1:
break;
label1: // label in a switch statement in really confusing
break;
default:
break;
}
}
AssignIvarOutsideAccessors
Since: 0.8
Name: ivar assignment outside accessors or init
此规则禁止在 getter、setter 和 init 方法之外赋值 ivar。
规则定义文件: oclint-rules/rules/convention/ObjCAssignIvarOutsideAccessorsRule.cpp
示例:
@interface Foo : NSObject
{
int _bar;
}
@property (assign, nonatomic) int bar;
@end
@implementation Foo
@synthesize bar = _bar;
- (void)doSomething {
_bar = 3; // access _bar outside its getter, setter or init
}
@end
ParameterReassignment
Since: 0.6
Name: parameter reassignment
在大多数情况下,请不要对参数从新赋值直接使用,如果参数是指针,对指针重新赋值是可以的。
规则定义文件: oclint-rules/rules/convention/ParameterReassignmentRule.cpp
示例:
void example(int a)
{
if (a < 0)
{
a = 0; // reassign parameter a to 0
}
}
PreferEarlyExit
Since: 0.8
Name: prefer early exits and continue
做更早的逻辑退出判断,这样就不用记住所有的条件,更容易理解代码。
规则定义文件: oclint-rules/rules/convention/PreferEarlyExitRule.cpp
示例:
int *doSomething(int a) {
if (!foo(a) && bar(a) && doOtherThing(a)) {
// ... some really long code ....
}
return 0;
}
// is preferred as
int *doSomething(int a) {
if (foo(a)) {
return 0;
}
if (!bar(a)) {
return 0;
}
if (!doOtherThing(a)) {
return 0;
}
// ... some long code ....
}
MissingDefaultStatement
Since: 0.6
Name: missing default in switch statements
switch 语句应该有一个 default 语句。
规则定义文件: oclint-rules/rules/convention/SwitchStatementsShouldHaveDefaultRule.cpp
示例:
void example(int a)
{
switch (a) {
case 1:
break;
case 2:
break;
// should have a default
}
}
TooFewBranchesInSwitchStatement
Since: 0.6
Name: too few branches in switch statement
为了提高代码可读性,当一个 switch 只包含几个分支时,最好使用 if 语句代替。
规则定义文件: oclint-rules/rules/convention/TooFewBranchesInSwitchStatementRule.cpp
示例:
void example(int a)
{
switch (a) {
case 1:
break;
default:
break;
} // Better to use an if statement and check if variable a equals 1.
}
Thresholds:
- MINIMUM_CASES_IN_SWITCH
switch语句中case语句计数的报告阈值,默认值为3。
Design
AvoidDefaultArgumentsOnVirtualMethods
Since: 0.10.1
Name: avoid default arguments on virtual methods
避免给虚函数设置默认参数,给虚函数设置默认参数会破坏多样性和引起不必要的层次结构复杂性。
规则定义文件: oclint-rules/rules/design/AvoidDefaultArgumentsOnVirtualMethodsRule.cpp
示例:
class Foo
{
public:
virtual ~Foo();
virtual void a(int b = 3);
// ...
};
class Bar : public Foo
{
public:
void a(int b);
// ...
};
Bar *bar = new Bar;
Foo *foo = bar;
foo->a(); // default of 3
bar->a(); // compile time error!
AvoidPrivateStaticMembers
Since: 0.10.1
Name: avoid private static members
避免使用私有静态成员,静态成员很容易破换封装性。
规则定义文件: oclint-rules/rules/design/AvoidPrivateStaticMembersRule.cpp
示例:
class Foo
{
static int a; // static field
};
class Bar
{
static int b(); // static method
}
Empty
EmptyCatchStatement
Since: 0.6
Name: empty catch statement
捕捉了异常,但任何处理都没做。
规则定义文件: oclint-rules/rules/empty/EmptyCatchStatementRule.cpp
示例:
void example()
{
try
{
int* m= new int[1000];
}
catch(...) // empty catch statement, this swallows an exception
{
}
}
EmptyDoWhileStatement
Since: 0.6
Name: empty do/while statement
do-while 语句内不执行任何操作。
规则定义文件: oclint-rules/rules/empty/EmptyDoWhileStatementRule.cpp
示例:
void example()
{
do
{ // empty do-while statement
} while(1);
}
EmptyElseBlock
Since: 0.6
Name: empty else block
else 语句不执行任何操作。
规则定义文件: oclint-rules/rules/empty/EmptyElseBlockRule.cpp
示例:
int example(int a)
{
if (1)
{
return a + 1;
}
else // empty else statement, can be safely removed
{
}
}
EmptyFinallyStatement
Since: 0.6
Name: empty finally statement
finally 语句不执行任何操作。
规则定义文件: oclint-rules/rules/empty/EmptyFinallyStatementRule.cpp
示例:
void example()
{
Foo *foo;
@try
{
[foo bar];
}
@catch(NSException *e)
{
NSLog(@"Exception occurred: %@", [e description]);
}
@finally // empty finally statement, probably forget to clean up?
{
}
}
EmptyForStatement
Since: 0.6
Name: empty for statement
for 语句不执行任何操作。
规则定义文件: oclint-rules/rules/empty/EmptyForStatementRule.cpp
示例:
void example(NSArray *array)
{
for (;;) // empty for statement
{
}
for (id it in array) // empty for-each statement
{
}
}
EmptyIfStatement
Since: 0.2
Name: empty if statement
做了条件判断但是没做任何操作。
规则定义文件: oclint-rules/rules/empty/EmptyIfStatementRule.cpp
示例:
void example(int a)
{
if (a == 1) // empty if statement
{
}
}
EmptySwitchStatement
Since: 0.6
Name: empty switch statement
switch 语句不执行任何操作。
规则定义文件: oclint-rules/rules/empty/EmptySwitchStatementRule.cpp
示例:
void example(int i)
{
switch (i) // empty switch statement
{
}
}
EmptyTryStatement
Since: 0.6
Name: empty try statement
try 语句为空
规则定义文件: oclint-rules/rules/empty/EmptyTryStatementRule.cpp
示例:
void example()
{
try // but this try statement is empty
{
}
catch(...)
{
cout << "Exception is caught!";
}
}
EmptyWhileStatement
Since: 0.6
Name: empty while statement
while 语句不执行任何操作。
规则定义文件: oclint-rules/rules/empty/EmptyWhileStatementRule.cpp
示例:
void example(int a)
{
while(a--) // empty while statement
{
}
}
Migration
UseBoxedExpression
Since: 0.7
Name: use boxed expression
使用字面量语法代替箱式表达式
规则定义文件: oclint-rules/rules/migration/ObjCBoxedExpressionsRule.cpp
示例:
void aMethod()
{
NSNumber *fortyTwo = [NSNumber numberWithInt:(43 - 1)];
// NSNumber *fortyTwo = @(43 - 1);
NSString *env = [NSString stringWithUTF8String:getenv("PATH")];
// NSString *env = @(getenv("PATH"));
}
UseContainerLiteral
Since: 0.7
Name: use container literal
使用字面量语法创建数组和字典
规则定义文件: oclint-rules/rules/migration/ObjCContainerLiteralsRule.cpp
示例:
void aMethod()
{
NSArray *a = [NSArray arrayWithObjects:@1, @2, @3, nil];
// NSArray *a = @[ @1, @2, @3 ];
NSDictionary *d = [NSDictionary dictionaryWithObjects:@[@2,@4] forKeys:@[@1,@3]];
// NSDictionary *d = @{ @1 : @2, @3 : @4 };
}
UseNumberLiteral
Since: 0.7
Name: use number literal
使用字面量语法创建 NSNumber
规则定义文件: oclint-rules/rules/migration/ObjCNSNumberLiteralsRule.cpp
示例:
void aMethod()
{
NSNumber *fortyTwo = [NSNumber numberWithInt:42];
// NSNumber *fortyTwo = @42;
NSNumber *yesBool = [NSNumber numberWithBool:YES];
// NSNumber *yesBool = @YES;
}
UseObjectSubscripting
Since: 0.7
Name: use object subscripting
使用字面量语法获取数组指定索引对象或者获取字典指定key的value
规则定义文件: oclint-rules/rules/migration/ObjCObjectSubscriptingRule.cpp
示例:
void aMethod(NSArray *a, NSDictionary *d)
{
id item = [a objectAtIndex:0];
// id item = a[0];
id item = [d objectForKey:@1];
// id item = d[@1];
}
Naming
LongVariableName
Since: 0.7
Name: long variable name
变量名称太长
规则定义文件: oclint-rules/rules/naming/LongVariableNameRule.cpp
示例:
void aMethod()
{
int reallyReallyLongIntegerName;
}
Thresholds:
- LONG_VARIABLE_NAME
长变量名报告阈值,默认值为20。
ShortVariableName
Since: 0.7
Name: short variable name
变量名称太短
规则定义文件: oclint-rules/rules/naming/ShortVariableNameRule.cpp
示例:
void aMethod(int i) // i is short
{
int ii; // ii is short
}
Thresholds:
- SHORT_VARIABLE_NAME
短变量名称报告阈值,默认值为3。
Redundant
RedundantConditionalOperator
Since: 0.6
Name: redundant conditional operator
此规则检测三种类型的冗余条件运算符:
- true 表达式和f alse 表达式分别返回 true/false 和 false/true;
- true 表达式和 false 表达式是相同的常数;
- true 表达式和 false 表达式是同一个变量表达式;
应该加以简化。
规则定义文件: oclint-rules/rules/redundant/RedundantConditionalOperatorRule.cpp
示例:
void example(int a, int b, int c)
{
bool b1 = a > b ? true : false; // true/false: bool b1 = a > b;
bool b2 = a > b ? false : true; // false/true: bool b2 = !(a > b);
int i1 = a > b ? 1 : 1; // same constant: int i1 = 1;
float f1 = a > b ? 1.0 : 1.00; // equally constant: float f1 = 1.0;
int i2 = a > b ? c : c; // same variable: int i2 = c;
}
RedundantIfStatement
Since: 0.4
Name: redundant if statement
不必要的 if 语句
规则定义文件: oclint-rules/rules/redundant/RedundantIfStatementRule.cpp
示例:
bool example(int a, int b)
{
if (a == b) // this if statement is redundant
{
return true;
}
else
{
return false;
} // the entire method can be simplified to return a == b;
}
RedundantLocalVariable
Since: 0.4
Name: redundant local variable
变量声明之后立即返回该变量,变量声明可以省略,直接尾调返回
规则定义文件: oclint-rules/rules/redundant/RedundantLocalVariableRule.cpp
示例:
int example(int a)
{
int b = a * 2;
return b; // variable b is returned immediately after its declaration,
} // can be simplified to return a * 2;
RedundantNilCheck
Since: 0.7
Name: redundant nil check
在Objective-C中,像foo != nil && [foo bar]这样的 c/c++风格的null检查是多余的,因为在这种情况下,向nil对象发送消息只会返回false。
规则定义文件: oclint-rules/rules/redundant/RedundantNilCheckRule.cpp
示例:
+ (void)compare:(A *)obj1 withOther:(A *)obj2
{
if (obj1 && [obj1 isEqualTo:obj2]) // if ([obj1 isEqualTo:obj2]) is okay
{
}
}
UnnecessaryElseStatement
Since: 0.6
Name: unnecessary else statement
如果一个 if 语句块以一个 return 语句结束,或者 if 语句块中的所有分支都以 return 语句结束,那么 else 语句就没有必要了,else 语句中的代码可以在不位于块中的情况下运行。
规则定义文件: oclint-rules/rules/redundant/UnnecessaryElseStatementRule.cpp
示例:
bool example(int a)
{
if (a == 1) // if (a == 1)
{ // {
cout << "a is 1."; // cout << "a is 1.";
return true; // return true;
} // }
else //
{ //
cout << "a is not 1." // cout << "a is not 1."
} //
}
UnnecessaryNullCheckForDealloc
Since: 0.8
Name: unnecessary null check for dealloc
不必要的判空检查,在 dealloc 中 char* p = 0; delete p;
是有效的。
规则定义文件: oclint-rules/rules/redundant/UnnecessaryNullCheckForCXXDeallocRule.cpp
示例:
void m(char* c) {
if (c != nullptr) { // and be simplified to delete c;
delete c;
}
}
UselessParentheses
Since: 0.6
Name: useless parentheses
无用的括号。
规则定义文件: oclint-rules/rules/redundant/UselessParenthesesRule.cpp
示例:
int example(int a)
{
int y = (a + 1); // int y = a + 1;
if ((y > 0)) // if (y > 0)
{
return a;
}
return (0); // return 0;
}
Size
HighCyclomaticComplexity
Since: 0.4
Name: high cyclomatic complexity
圈复杂度由程序源代码中线性无关路径的数量决定。换句话说,方法的圈复杂度是由决策点的数量来度量的,比如 if、while 和 for 语句的数量,以及方法条目的数量。
圈复杂度的作者 McCabe 通过实验得出结论,复杂度在 3 到 7 之间的方法结构会非常好。他还建议圈复杂度为 10 是一个合理的上限。
规则定义文件: oclint-rules/rules/size/CyclomaticComplexityRule.cpp
示例:
void example(int a, int b, int c) // 1
{
if (a == b) // 2
{
if (b == c) // 3
{
}
else if (a == c) // 3
{
}
else
{
}
}
for (int i = 0; i < c; i++) // 4
{
}
switch(c)
{
case 1: // 5
break;
case 2: // 6
break;
default: // 7
break;
}
}
Thresholds:
- CYCLOMATIC_COMPLEXITY
圈复杂度报告阈值,默认值为10。
Suppress:
__attribute__((annotate("oclint:suppress[high cyclomatic complexity]")))
References:
McCabe (December 1976). “A Complexity Measure”. IEEE Transactions on Software Engineering: 308–320
LongClass
Since: 0.6
Name: long class
类代码行数过多
规则定义文件: oclint-rules/rules/size/LongClassRule.cpp
示例:
class Foo
{
void bar()
{
// 1001 lines of code
}
}
Thresholds:
- LONG_CLASS
类大小报告阈值,默认值为1000。
LongLine
Since: 0.6
Name: long line
单行代码太长,影响可读性,应该折行
规则定义文件: oclint-rules/rules/size/LongLineRule.cpp
示例:
void example()
{
int a012345678901234567890123456789...1234567890123456789012345678901234567890123456789;
}
Thresholds:
- LONG_LINE
长行报告阈值,默认值为100。
LongMethod
Since: 0.4
Name: long method
单个方法中代码行数太多
规则定义文件: oclint-rules/rules/size/LongMethodRule.cpp
示例:
void example()
{
cout << "hello world";
cout << "hello world";
// repeat 48 times
}
Thresholds:
- LONG_METHOD
长方法报告阈值,默认值为50。
HighNcssMethod
Since: 0.6
Name: high ncss method
该规则通过计算非注释源语句(NCSS)来计算方法的行数。NCSS 只考虑实际语句,即忽略空语句、空块、右括号或右括号后的分号。与此同时,被分成多行的语句只贡献一个计数。
规则定义文件: oclint-rules/rules/size/NcssMethodCountRule.cpp
示例:
void example() // 1
{
if (1) // 2
{
}
else // 3
{
}
}
Thresholds:
- NCSS_METHOD
高NCSS方法报告阈值,默认值为30。
Suppress:
__attribute__((annotate("oclint:suppress[high ncss method]")))
DeepNestedBlock
Since: 0.6
Name: deep nested block
块或复合语句嵌套深度太大。
规则定义文件: oclint-rules/rules/size/NestedBlockDepthRule.cpp
示例:
if (1)
{ // 1
{ // 2
{ // 3
}
}
}
Thresholds:
- NESTED_BLOCK_DEPTH
块或复合语句的深度报告阈值,默认值为5。
HighNPathComplexity
Since: 0.4
Name: high npath complexity
NPath 复杂度由该方法的执行路径数量决定。与圈复杂度相比,NPath复杂度有两个突出特点:一是区分了不同类型的控制流结构;其次,它考虑流图中各种类型的非循环路径。
基于作者在AT&T贝尔实验室的研究,建立了一种 NPath 阈值为 200 的方法。
规则定义文件: oclint-rules/rules/size/NPathComplexityRule.cpp
示例:
void example()
{
// complicated code that is hard to understand
}
Thresholds:
- NPATH_COMPLEXITY
NPath复杂度报告阈值,默认值为200。
Suppress:
__attribute__((annotate("oclint:suppress[high npath complexity]")))
References:
Brian A. Nejmeh (1988). “NPATH: a measure of execution path complexity and its applications”. Communications of the ACM 31 (2) p. 188-200
TooManyFields
Since: 0.7
Name: too many fields
字段太多的类表示它做的事情太多,缺乏适当的抽象,可以将其重新设计得字段更少。
规则定义文件: oclint-rules/rules/size/TooManyFieldsRule.cpp
示例:
class c
{
int a, b;
int c;
// ...
int l;
int m, n;
// ...
int x, y, z;
void m() {}
};
Thresholds:
- TOO_MANY_FIELDS
对于太多字段的报告阈值,默认值为20。
TooManyMethods
Since: 0.7
Name: too many methods
方法太多的类表示它做的事情太多,很难阅读和理解,它通常包含复杂的代码,应该重构。
规则定义文件: oclint-rules/rules/size/TooManyMethodsRule.cpp
示例:
class c
{
int a();
int b();
int c();
// ...
int l();
int m();
int n();
// ...
int x();
int y();
int z();
int aa();
int ab();
int ac();
int ad();
int ae();
};
Thresholds:
- TOO_MANY_METHODS
对于太多方法的报告阈值,默认值为30。
TooManyParameters
Since: 0.7
Name: too many parameters
参数太多的方法很难理解和维护,需要重构。比如用方法替换参数、引入参数对象或保存整个对象。
规则定义文件: oclint-rules/rules/size/TooManyParametersRule.cpp
示例:
void example(int a, int b, int c, int d, int e, int f,
int g, int h, int i, int j, int k, int l)
{
}
Thresholds:
- TOO_MANY_PARAMETERS
对于太多参数的报告阈值,默认值为10。
References:
Fowler, Martin (1999). Refactoring: Improving the design of existing code. Addison Wesley.
Unused
UnusedLocalVariable
Since: 0.4
Name: unused local variable
声明但未使用的局部变量。
规则定义文件: oclint-rules/rules/unused/UnusedLocalVariableRule.cpp
示例:
int example(int a)
{
int i; // variable i is declared, but not used
return 0;
}
消除:
__attribute__((annotate("oclint:suppress[unused local variable]")))
UnusedMethodParameter
Since: 0.4
Name: unused method parameter
方法中未使用的参数。
规则定义文件: oclint-rules/rules/unused/UnusedMethodParameterRule.cpp
示例:
int example(int a) // parameter a is not used
{
return 0;
}
消除:
__attribute__((annotate("oclint:suppress[unused method parameter]")))