Summary: These pages are not referenced from anywhere and are stale, oops! We even linked to checker-bug-types from our footer on all pages... These pages are stale and replaced with auto-generated ones now. Reviewed By: skcho Differential Revision: D26544298 fbshipit-source-id: c3b7742b8master
parent
e8dc75f92a
commit
620f6f53ea
File diff suppressed because it is too large
Load Diff
@ -1,271 +0,0 @@
|
||||
---
|
||||
id: eradicate-warnings
|
||||
title: Eradicate warnings
|
||||
---
|
||||
|
||||
Below you will find a description of all the warnings reported by
|
||||
[Eradicate](/docs/eradicate).
|
||||
|
||||
## Eradicate null field access
|
||||
|
||||
A field access of the form x.field where x could be null.
|
||||
|
||||
Example:
|
||||
|
||||
```java
|
||||
class C {
|
||||
void foo(@Nullable C x) {
|
||||
x.field = 3;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Action: Make sure that x cannot be null by changing the code or changing
|
||||
annotations. If this cannot be done, the only choice is to use defensive
|
||||
programming: if (x != null) { ... x.field ... } else { ... you need to decide
|
||||
what to do when x is null ... } The general recommendation is to push null
|
||||
checks up the call chain as much as possible in order to detect the place where
|
||||
null values originate and deal with them at that point. When a null value is
|
||||
propagated down the call chain it is often difficult to determine its origin
|
||||
without global knowledge of what the program does. For example, a null value
|
||||
could originate in third party libraries which are not under your control, and
|
||||
the best place to check for null is typically immediately after calling these
|
||||
library functions.
|
||||
|
||||
## Eradicate null method call
|
||||
|
||||
A method call x.m(...) where x could be null.
|
||||
|
||||
Example:
|
||||
|
||||
```java
|
||||
class C {
|
||||
void foo(@Nullable C x) {
|
||||
String s = x.toString();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Action: Same as for Null field access.
|
||||
|
||||
## Eradicate field not nullable
|
||||
|
||||
An assignment x.f = v where v could be null and field f is not annotated with
|
||||
@Nullable.
|
||||
|
||||
Example:
|
||||
|
||||
```java
|
||||
class C {
|
||||
String f;
|
||||
|
||||
void foo(@Nullable String s) {
|
||||
f = s;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Action: The preferred action is to ensure that a null value is never stored in
|
||||
the field, by changing the code or changing annotations. If this cannot be done,
|
||||
add a @Nullable annotation to the field. This annotation might trigger more
|
||||
warnings in other code that uses the field, as that code must now deal with null
|
||||
values.
|
||||
|
||||
## Eradicate field not initialized
|
||||
|
||||
The constructor does not initialize a field f which is not annotated with
|
||||
@Nullable
|
||||
|
||||
Example:
|
||||
|
||||
```java
|
||||
class C {
|
||||
String f;
|
||||
|
||||
C () { // field f not initialized and not annotated @Nullable
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Action: The preferred action is to initialize the field with a value that is not
|
||||
null. If, by design, null is a valid value for the field, then it should be
|
||||
annotated with @Nullable.
|
||||
|
||||
## Eradicate parameter not nullable
|
||||
|
||||
Method call x.m(..., v, ...) where v can be null and the corresponding parameter
|
||||
in method m is not annotated with @Nullable
|
||||
|
||||
Example:
|
||||
|
||||
```java
|
||||
class C {
|
||||
void m(C x) {
|
||||
String s = x.toString()
|
||||
}
|
||||
|
||||
void test(@Nullable C x) {
|
||||
m(x);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Action: The preferred action is to ensure that a null value is never passed to
|
||||
the method, by changing the code or changing annotations. If this cannot be
|
||||
done, add a @Nullable annotation to the relevant parameter in the method
|
||||
declaration. This annotation might trigger more warnings in the implementation
|
||||
of method m, as that code must now deal with null values.
|
||||
|
||||
## Eradicate return not nullable
|
||||
|
||||
Method m can return null, but the method's return type is not annotated with
|
||||
@Nullable
|
||||
|
||||
Example:
|
||||
|
||||
```java
|
||||
class C {
|
||||
String m() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Action: The preferred action is to ensure that a null value is never returned by
|
||||
the method, by changing the code or changing annotations. If this cannot be
|
||||
done, add a @Nullable annotation to the the method declaration. This annotation
|
||||
might trigger more warnings in the callers of method m, as the callers must now
|
||||
deal with null values.
|
||||
|
||||
## Eradicate condition redundant
|
||||
|
||||
This report is inactive by default. Condition (x != null) or (x == null) when x
|
||||
cannot be null: the first condition is always true and the second is always
|
||||
false
|
||||
|
||||
Example:
|
||||
|
||||
```java
|
||||
class C {
|
||||
void m() {
|
||||
String s = new String("abc");
|
||||
if (s != null) {
|
||||
int n = s.length();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Action: Make sure that the annotations are correct, as the condition is
|
||||
considered redundant based on the existing annotations. In particular, check the
|
||||
annotation of any input parameters and fields of the current method, as well as
|
||||
the annotations of any method called directly by the current method, if
|
||||
relevant. If the annotations are correct, you can remove the redundant case.
|
||||
|
||||
## Eradicate return overannotated
|
||||
|
||||
This report is inactive by default. Method m is annotated with @Nullable but the
|
||||
method cannot return null
|
||||
|
||||
Example:
|
||||
|
||||
```java
|
||||
class C {
|
||||
@Nullable String m() {
|
||||
String s = new String("abc");
|
||||
return s;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Action: Make sure that the annotations are correct, as the return annotation is
|
||||
considered redundant based on the existing annotations. In particular, check the
|
||||
annotation of any input parameters and fields of the current method, as well as
|
||||
the annotations of any method called directly by the current method, if
|
||||
relevant. If the annotations are correct, you can remove the @Nullable
|
||||
annotation.
|
||||
|
||||
## Eradicate inconsistent subclass return annotation
|
||||
|
||||
The return type of the overridden method is annotated @Nullable, but the
|
||||
corresponding method in the superclass is not.
|
||||
|
||||
Action: choose a consistent annotation based on the desired invariant.
|
||||
|
||||
Example:
|
||||
|
||||
```java
|
||||
class A {
|
||||
String create() {
|
||||
return new String("abc");
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
@Nullable String create() { // Inconsistent @Nullable annotation.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
A consistent use of @Nullable on the return type across subtyping should prevent
|
||||
runtime issue like in:
|
||||
|
||||
```java
|
||||
class Main {
|
||||
|
||||
int foo(A a) {
|
||||
String s = a.create();
|
||||
return s.length();
|
||||
}
|
||||
|
||||
void main(String[] args) {
|
||||
A a = new B();
|
||||
foo(a);
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Inconsistent subclass parameter annotation
|
||||
|
||||
A parameter of the overridden method is missing a @Nullable annotation present in the superclass.
|
||||
|
||||
Action: choose a consistent annotation based on the desired invariant.
|
||||
|
||||
Example:
|
||||
|
||||
```java
|
||||
class A {
|
||||
|
||||
int len(@Nullable String s) {
|
||||
if (s != null) {
|
||||
return s.length();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
|
||||
int len(String s) { // @Nullable missing.
|
||||
return s.length();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
A consistent use of @Nullable on parameters across subtyping should prevent runtime issue like in:
|
||||
|
||||
```java
|
||||
public class Main {
|
||||
|
||||
String s;
|
||||
|
||||
int foo() {
|
||||
A a = new B();
|
||||
return a.len(s);
|
||||
}
|
||||
}
|
||||
```
|
@ -1,193 +0,0 @@
|
||||
---
|
||||
id: linters-bug-types
|
||||
title: Linters bug types
|
||||
---
|
||||
|
||||
Here is an overview of the linter checks we provide in Infer:
|
||||
|
||||
## Assign pointer warning
|
||||
|
||||
This check fires when a pointer to an Obj-C object is tagged with an `assign`
|
||||
property (similar to the `-Warc-unsafe-retained-assign` compiler flag). Not
|
||||
holding a strong reference to the object makes it easy to accidentally create
|
||||
and use a dangling pointer.
|
||||
|
||||
## Bad pointer comparison
|
||||
|
||||
Infer reports these warnings in Objective-C when a boxed primitive type such as
|
||||
`NSNumber *` is coerced to a boolean in a comparison. For example, consider the
|
||||
code
|
||||
|
||||
```objectivec
|
||||
void foo(NSNumber * n) {
|
||||
if (n) ...
|
||||
```
|
||||
|
||||
The branch in the above code will be taken when the pointer `n` is non-`nil`,
|
||||
but the programmer might have actually wanted the branch to be taken when the
|
||||
integer pointed to by `n` is nonzero (e.g., she may have meant to call an
|
||||
accessor like `[n intValue]` instead). Infer will ask the programmer explicitly
|
||||
compare `n` to `nil` or call an accessor to clarify her intention.
|
||||
|
||||
## C++ reference captured in Objective-C block
|
||||
|
||||
With this check, Infer detects C++ references captured in a block. Doing this is
|
||||
almost always wrong. The reason is that C++ references are not managed pointers
|
||||
(like ARC pointers) and so the referent is likely to be gone by the time the
|
||||
block gets executed. One solution is to do a local copy of the reference and
|
||||
pass that to the block. Example:
|
||||
|
||||
```c
|
||||
(int &) v;
|
||||
...
|
||||
const int copied_v = v;
|
||||
^{
|
||||
// use copied_v not v
|
||||
};
|
||||
```
|
||||
|
||||
## Direct atomic property access
|
||||
|
||||
This check warns you when you are accessing an atomic property directly with an
|
||||
ivar. This makes the atomic property not atomic anymore. So potentially you may
|
||||
get a race condition.
|
||||
|
||||
To fix the problem you need to access properties with their getter or setter.
|
||||
|
||||
## Global variable initialized with function or method call
|
||||
|
||||
This checker warns you when the initialization of global variable contain a
|
||||
method or function call. The warning wants to make you aware that some functions
|
||||
are expensive. As the global variables are initialized before main() is called,
|
||||
these initializations can slow down the start-up time of an app.
|
||||
|
||||
## Registered observer being deallocated
|
||||
|
||||
Objects register with a notification center to receive notifications. This check
|
||||
warns you when an object is registered as observer of a NSNotificationCenter but
|
||||
it is never unregistered. This is problematic as if the object is not
|
||||
unregistered the notification center can still send notification even after the
|
||||
object has been deallocated. In that case we would get a crash.
|
||||
|
||||
## Strong delegate warning
|
||||
|
||||
This check warns you when you have a property called delegate or variations
|
||||
thereof which is declared strong. The idea is that delegates should generally be
|
||||
weak, otherwise this may cause retain cycles.
|
||||
|
||||
## Unavailable api in supported ios sdk
|
||||
|
||||
This checks warns you when you are using an API (constant, method call, etc.)
|
||||
that is only defined in a version higher than the version that you support. To
|
||||
enable this check, pass to Infer the option
|
||||
`--iphoneos-target-sdk-version version`. Calling an undefined API will lead to a
|
||||
crash in the app. To fix this, you can choose a different API or use it inside
|
||||
an if, as in:
|
||||
|
||||
```objectivec
|
||||
if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)]) {
|
||||
font = [UIFont systemFontOfSize:size weight:0];
|
||||
}
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```objectivec
|
||||
if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_9_0) {
|
||||
font = [UIFont systemFontOfSize:size weight:0];
|
||||
}
|
||||
```
|
||||
|
||||
## Pointer To const Objective-C Class
|
||||
|
||||
In Objective-C, `const Class *` represents a mutable pointer pointing to an
|
||||
Objective-C class where the ivars cannot be changed. More useful is
|
||||
`Class *const` instead, meaning the destination of the pointer cannot be
|
||||
changed.
|
||||
|
||||
## Objective-C Weak Property has Custom Setter
|
||||
|
||||
This check warns you when you have a custom setter for a weak property. When
|
||||
compiled with Automatic Reference Counting (ARC, `-fobj-arc`) ARC may set the
|
||||
property to `nil` without invoking the setter, for example:
|
||||
|
||||
```objectivec
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface Employee : NSObject {
|
||||
NSString* _name;
|
||||
__weak Employee* _manager;
|
||||
}
|
||||
-(id)initWithName:(NSString*)name;
|
||||
@property(atomic, weak) Employee* manager;
|
||||
-(void)report;
|
||||
@end
|
||||
|
||||
@implementation Employee
|
||||
|
||||
-(id)initWithName:(NSString*)name {
|
||||
_name = name;
|
||||
return self;
|
||||
}
|
||||
|
||||
-(NSString*)description {
|
||||
return _name;
|
||||
}
|
||||
|
||||
-(void)report {
|
||||
NSLog(@"I work for %@", _manager);
|
||||
}
|
||||
|
||||
-(Employee*)manager {
|
||||
return _manager;
|
||||
}
|
||||
|
||||
// DON'T do this; ARC will not call this when setting _manager to nil.
|
||||
-(void)setManager:(Employee*)newManager {
|
||||
NSLog(@"Meet the new boss...");
|
||||
_manager = newManager;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
Employee* bob = [[Employee alloc] initWithName:@"Bob"];
|
||||
Employee* sue = [[Employee alloc] initWithName:@"Sue"];
|
||||
bob.manager = sue;
|
||||
[bob report];
|
||||
sue = nil;
|
||||
[bob report];
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
This prints:
|
||||
|
||||
```
|
||||
Meet the new boss...
|
||||
I work for Sue
|
||||
I work for (null)
|
||||
```
|
||||
|
||||
Note that the custom setter was only invoked once.
|
||||
|
||||
## Component factory function
|
||||
|
||||
[Doc in ComponentKit page](http://componentkit.org/docs/break-out-composites)
|
||||
|
||||
## Component initializer with side effects
|
||||
|
||||
[Doc in ComponentKit page](http://componentkit.org/docs/no-side-effects)
|
||||
|
||||
## Component with multiple factory methods
|
||||
|
||||
[Doc in ComponentKit page](http://componentkit.org/docs/avoid-overrides)
|
||||
|
||||
## Component with unconventional superclass
|
||||
|
||||
[Doc in ComponentKit page](http://componentkit.org/docs/never-subclass-components)
|
||||
|
||||
## Mutable local variable in component file
|
||||
|
||||
[Doc in ComponentKit page](http://componentkit.org/docs/avoid-local-variables)
|
File diff suppressed because it is too large
Load Diff
@ -1,271 +0,0 @@
|
||||
---
|
||||
id: eradicate-warnings
|
||||
title: Eradicate warnings
|
||||
---
|
||||
|
||||
Below you will find a description of all the warnings reported by
|
||||
[Eradicate](/docs/eradicate).
|
||||
|
||||
## Eradicate null field access
|
||||
|
||||
A field access of the form x.field where x could be null.
|
||||
|
||||
Example:
|
||||
|
||||
```java
|
||||
class C {
|
||||
void foo(@Nullable C x) {
|
||||
x.field = 3;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Action: Make sure that x cannot be null by changing the code or changing
|
||||
annotations. If this cannot be done, the only choice is to use defensive
|
||||
programming: if (x != null) { ... x.field ... } else { ... you need to decide
|
||||
what to do when x is null ... } The general recommendation is to push null
|
||||
checks up the call chain as much as possible in order to detect the place where
|
||||
null values originate and deal with them at that point. When a null value is
|
||||
propagated down the call chain it is often difficult to determine its origin
|
||||
without global knowledge of what the program does. For example, a null value
|
||||
could originate in third party libraries which are not under your control, and
|
||||
the best place to check for null is typically immediately after calling these
|
||||
library functions.
|
||||
|
||||
## Eradicate null method call
|
||||
|
||||
A method call x.m(...) where x could be null.
|
||||
|
||||
Example:
|
||||
|
||||
```java
|
||||
class C {
|
||||
void foo(@Nullable C x) {
|
||||
String s = x.toString();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Action: Same as for Null field access.
|
||||
|
||||
## Eradicate field not nullable
|
||||
|
||||
An assignment x.f = v where v could be null and field f is not annotated with
|
||||
@Nullable.
|
||||
|
||||
Example:
|
||||
|
||||
```java
|
||||
class C {
|
||||
String f;
|
||||
|
||||
void foo(@Nullable String s) {
|
||||
f = s;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Action: The preferred action is to ensure that a null value is never stored in
|
||||
the field, by changing the code or changing annotations. If this cannot be done,
|
||||
add a @Nullable annotation to the field. This annotation might trigger more
|
||||
warnings in other code that uses the field, as that code must now deal with null
|
||||
values.
|
||||
|
||||
## Eradicate field not initialized
|
||||
|
||||
The constructor does not initialize a field f which is not annotated with
|
||||
@Nullable
|
||||
|
||||
Example:
|
||||
|
||||
```java
|
||||
class C {
|
||||
String f;
|
||||
|
||||
C () { // field f not initialized and not annotated @Nullable
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Action: The preferred action is to initialize the field with a value that is not
|
||||
null. If, by design, null is a valid value for the field, then it should be
|
||||
annotated with @Nullable.
|
||||
|
||||
## Eradicate parameter not nullable
|
||||
|
||||
Method call x.m(..., v, ...) where v can be null and the corresponding parameter
|
||||
in method m is not annotated with @Nullable
|
||||
|
||||
Example:
|
||||
|
||||
```java
|
||||
class C {
|
||||
void m(C x) {
|
||||
String s = x.toString()
|
||||
}
|
||||
|
||||
void test(@Nullable C x) {
|
||||
m(x);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Action: The preferred action is to ensure that a null value is never passed to
|
||||
the method, by changing the code or changing annotations. If this cannot be
|
||||
done, add a @Nullable annotation to the relevant parameter in the method
|
||||
declaration. This annotation might trigger more warnings in the implementation
|
||||
of method m, as that code must now deal with null values.
|
||||
|
||||
## Eradicate return not nullable
|
||||
|
||||
Method m can return null, but the method's return type is not annotated with
|
||||
@Nullable
|
||||
|
||||
Example:
|
||||
|
||||
```java
|
||||
class C {
|
||||
String m() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Action: The preferred action is to ensure that a null value is never returned by
|
||||
the method, by changing the code or changing annotations. If this cannot be
|
||||
done, add a @Nullable annotation to the the method declaration. This annotation
|
||||
might trigger more warnings in the callers of method m, as the callers must now
|
||||
deal with null values.
|
||||
|
||||
## Eradicate condition redundant
|
||||
|
||||
This report is inactive by default. Condition (x != null) or (x == null) when x
|
||||
cannot be null: the first condition is always true and the second is always
|
||||
false
|
||||
|
||||
Example:
|
||||
|
||||
```java
|
||||
class C {
|
||||
void m() {
|
||||
String s = new String("abc");
|
||||
if (s != null) {
|
||||
int n = s.length();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Action: Make sure that the annotations are correct, as the condition is
|
||||
considered redundant based on the existing annotations. In particular, check the
|
||||
annotation of any input parameters and fields of the current method, as well as
|
||||
the annotations of any method called directly by the current method, if
|
||||
relevant. If the annotations are correct, you can remove the redundant case.
|
||||
|
||||
## Eradicate return overannotated
|
||||
|
||||
This report is inactive by default. Method m is annotated with @Nullable but the
|
||||
method cannot return null
|
||||
|
||||
Example:
|
||||
|
||||
```java
|
||||
class C {
|
||||
@Nullable String m() {
|
||||
String s = new String("abc");
|
||||
return s;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Action: Make sure that the annotations are correct, as the return annotation is
|
||||
considered redundant based on the existing annotations. In particular, check the
|
||||
annotation of any input parameters and fields of the current method, as well as
|
||||
the annotations of any method called directly by the current method, if
|
||||
relevant. If the annotations are correct, you can remove the @Nullable
|
||||
annotation.
|
||||
|
||||
## Eradicate inconsistent subclass return annotation
|
||||
|
||||
The return type of the overridden method is annotated @Nullable, but the
|
||||
corresponding method in the superclass is not.
|
||||
|
||||
Action: choose a consistent annotation based on the desired invariant.
|
||||
|
||||
Example:
|
||||
|
||||
```java
|
||||
class A {
|
||||
String create() {
|
||||
return new String("abc");
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
@Nullable String create() { // Inconsistent @Nullable annotation.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
A consistent use of @Nullable on the return type across subtyping should prevent
|
||||
runtime issue like in:
|
||||
|
||||
```java
|
||||
class Main {
|
||||
|
||||
int foo(A a) {
|
||||
String s = a.create();
|
||||
return s.length();
|
||||
}
|
||||
|
||||
void main(String[] args) {
|
||||
A a = new B();
|
||||
foo(a);
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Inconsistent subclass parameter annotation
|
||||
|
||||
A parameter of the overridden method is missing a @Nullable annotation present in the superclass.
|
||||
|
||||
Action: choose a consistent annotation based on the desired invariant.
|
||||
|
||||
Example:
|
||||
|
||||
```java
|
||||
class A {
|
||||
|
||||
int len(@Nullable String s) {
|
||||
if (s != null) {
|
||||
return s.length();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
|
||||
int len(String s) { // @Nullable missing.
|
||||
return s.length();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
A consistent use of @Nullable on parameters across subtyping should prevent runtime issue like in:
|
||||
|
||||
```java
|
||||
public class Main {
|
||||
|
||||
String s;
|
||||
|
||||
int foo() {
|
||||
A a = new B();
|
||||
return a.len(s);
|
||||
}
|
||||
}
|
||||
```
|
@ -1,193 +0,0 @@
|
||||
---
|
||||
id: linters-bug-types
|
||||
title: Linters bug types
|
||||
---
|
||||
|
||||
Here is an overview of the linter checks we provide in Infer:
|
||||
|
||||
## Assign pointer warning
|
||||
|
||||
This check fires when a pointer to an Obj-C object is tagged with an `assign`
|
||||
property (similar to the `-Warc-unsafe-retained-assign` compiler flag). Not
|
||||
holding a strong reference to the object makes it easy to accidentally create
|
||||
and use a dangling pointer.
|
||||
|
||||
## Bad pointer comparison
|
||||
|
||||
Infer reports these warnings in Objective-C when a boxed primitive type such as
|
||||
`NSNumber *` is coerced to a boolean in a comparison. For example, consider the
|
||||
code
|
||||
|
||||
```objectivec
|
||||
void foo(NSNumber * n) {
|
||||
if (n) ...
|
||||
```
|
||||
|
||||
The branch in the above code will be taken when the pointer `n` is non-`nil`,
|
||||
but the programmer might have actually wanted the branch to be taken when the
|
||||
integer pointed to by `n` is nonzero (e.g., she may have meant to call an
|
||||
accessor like `[n intValue]` instead). Infer will ask the programmer explicitly
|
||||
compare `n` to `nil` or call an accessor to clarify her intention.
|
||||
|
||||
## C++ reference captured in Objective-C block
|
||||
|
||||
With this check, Infer detects C++ references captured in a block. Doing this is
|
||||
almost always wrong. The reason is that C++ references are not managed pointers
|
||||
(like ARC pointers) and so the referent is likely to be gone by the time the
|
||||
block gets executed. One solution is to do a local copy of the reference and
|
||||
pass that to the block. Example:
|
||||
|
||||
```c
|
||||
(int &) v;
|
||||
...
|
||||
const int copied_v = v;
|
||||
^{
|
||||
// use copied_v not v
|
||||
};
|
||||
```
|
||||
|
||||
## Direct atomic property access
|
||||
|
||||
This check warns you when you are accessing an atomic property directly with an
|
||||
ivar. This makes the atomic property not atomic anymore. So potentially you may
|
||||
get a race condition.
|
||||
|
||||
To fix the problem you need to access properties with their getter or setter.
|
||||
|
||||
## Global variable initialized with function or method call
|
||||
|
||||
This checker warns you when the initialization of global variable contain a
|
||||
method or function call. The warning wants to make you aware that some functions
|
||||
are expensive. As the global variables are initialized before main() is called,
|
||||
these initializations can slow down the start-up time of an app.
|
||||
|
||||
## Registered observer being deallocated
|
||||
|
||||
Objects register with a notification center to receive notifications. This check
|
||||
warns you when an object is registered as observer of a NSNotificationCenter but
|
||||
it is never unregistered. This is problematic as if the object is not
|
||||
unregistered the notification center can still send notification even after the
|
||||
object has been deallocated. In that case we would get a crash.
|
||||
|
||||
## Strong delegate warning
|
||||
|
||||
This check warns you when you have a property called delegate or variations
|
||||
thereof which is declared strong. The idea is that delegates should generally be
|
||||
weak, otherwise this may cause retain cycles.
|
||||
|
||||
## Unavailable api in supported ios sdk
|
||||
|
||||
This checks warns you when you are using an API (constant, method call, etc.)
|
||||
that is only defined in a version higher than the version that you support. To
|
||||
enable this check, pass to Infer the option
|
||||
`--iphoneos-target-sdk-version version`. Calling an undefined API will lead to a
|
||||
crash in the app. To fix this, you can choose a different API or use it inside
|
||||
an if, as in:
|
||||
|
||||
```objectivec
|
||||
if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)]) {
|
||||
font = [UIFont systemFontOfSize:size weight:0];
|
||||
}
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```objectivec
|
||||
if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_9_0) {
|
||||
font = [UIFont systemFontOfSize:size weight:0];
|
||||
}
|
||||
```
|
||||
|
||||
## Pointer To const Objective-C Class
|
||||
|
||||
In Objective-C, `const Class *` represents a mutable pointer pointing to an
|
||||
Objective-C class where the ivars cannot be changed. More useful is
|
||||
`Class *const` instead, meaning the destination of the pointer cannot be
|
||||
changed.
|
||||
|
||||
## Objective-C Weak Property has Custom Setter
|
||||
|
||||
This check warns you when you have a custom setter for a weak property. When
|
||||
compiled with Automatic Reference Counting (ARC, `-fobj-arc`) ARC may set the
|
||||
property to `nil` without invoking the setter, for example:
|
||||
|
||||
```objectivec
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface Employee : NSObject {
|
||||
NSString* _name;
|
||||
__weak Employee* _manager;
|
||||
}
|
||||
-(id)initWithName:(NSString*)name;
|
||||
@property(atomic, weak) Employee* manager;
|
||||
-(void)report;
|
||||
@end
|
||||
|
||||
@implementation Employee
|
||||
|
||||
-(id)initWithName:(NSString*)name {
|
||||
_name = name;
|
||||
return self;
|
||||
}
|
||||
|
||||
-(NSString*)description {
|
||||
return _name;
|
||||
}
|
||||
|
||||
-(void)report {
|
||||
NSLog(@"I work for %@", _manager);
|
||||
}
|
||||
|
||||
-(Employee*)manager {
|
||||
return _manager;
|
||||
}
|
||||
|
||||
// DON'T do this; ARC will not call this when setting _manager to nil.
|
||||
-(void)setManager:(Employee*)newManager {
|
||||
NSLog(@"Meet the new boss...");
|
||||
_manager = newManager;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
Employee* bob = [[Employee alloc] initWithName:@"Bob"];
|
||||
Employee* sue = [[Employee alloc] initWithName:@"Sue"];
|
||||
bob.manager = sue;
|
||||
[bob report];
|
||||
sue = nil;
|
||||
[bob report];
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
This prints:
|
||||
|
||||
```
|
||||
Meet the new boss...
|
||||
I work for Sue
|
||||
I work for (null)
|
||||
```
|
||||
|
||||
Note that the custom setter was only invoked once.
|
||||
|
||||
## Component factory function
|
||||
|
||||
[Doc in ComponentKit page](http://componentkit.org/docs/break-out-composites)
|
||||
|
||||
## Component initializer with side effects
|
||||
|
||||
[Doc in ComponentKit page](http://componentkit.org/docs/no-side-effects)
|
||||
|
||||
## Component with multiple factory methods
|
||||
|
||||
[Doc in ComponentKit page](http://componentkit.org/docs/avoid-overrides)
|
||||
|
||||
## Component with unconventional superclass
|
||||
|
||||
[Doc in ComponentKit page](http://componentkit.org/docs/never-subclass-components)
|
||||
|
||||
## Mutable local variable in component file
|
||||
|
||||
[Doc in ComponentKit page](http://componentkit.org/docs/avoid-local-variables)
|
Loading…
Reference in new issue