Reviewed By: dulmarod Differential Revision: D2564879 fb-gh-sync-id: 46e0a03master
parent
740f673451
commit
ae49cacee8
@ -0,0 +1,30 @@
|
|||||||
|
(*
|
||||||
|
* Copyright (c) 2015 - present Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*)
|
||||||
|
|
||||||
|
open CFrontend_utils
|
||||||
|
open General_utils
|
||||||
|
|
||||||
|
|
||||||
|
(* === Warnings on properties === *)
|
||||||
|
|
||||||
|
(* Strong Delegate Warning: a property with name delegate should not be declared strong *)
|
||||||
|
let checker_strong_delegate_warning pname ptype =
|
||||||
|
Printing.log_out "Checking for STRONG_DELEGATE property warning\n";
|
||||||
|
let delegate_regexp = Str.regexp_string_case_fold "delegate" in
|
||||||
|
let pname_contains_delegate = try
|
||||||
|
Str.search_forward delegate_regexp pname.Clang_ast_t.ni_name 0 >= 0
|
||||||
|
with Not_found -> false in
|
||||||
|
let condition = pname_contains_delegate
|
||||||
|
&& ObjcProperty_decl.is_strong_property ptype in
|
||||||
|
let warning_desc= {name = "STRONG_DELEGATE_WARNING";
|
||||||
|
description = "Property or ivar "^pname.Clang_ast_t.ni_name^" declared strong";
|
||||||
|
suggestion = "In general delegates should be declared weak or assign";
|
||||||
|
loc = string_of_int (ObjcProperty_decl.property_line ptype);
|
||||||
|
} in
|
||||||
|
(condition, warning_desc)
|
@ -0,0 +1,16 @@
|
|||||||
|
(*
|
||||||
|
* Copyright (c) 2015 - present Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*)
|
||||||
|
|
||||||
|
|
||||||
|
(* === Warnings on properties === *)
|
||||||
|
|
||||||
|
(* Strong Delegate Warning: a property with name delegate should not be declared strong *)
|
||||||
|
val checker_strong_delegate_warning : Clang_ast_t.named_decl_info ->
|
||||||
|
ObjcProperty_decl.property_type ->
|
||||||
|
(bool * CFrontend_utils.General_utils.warning_desc)
|
@ -0,0 +1,55 @@
|
|||||||
|
(*
|
||||||
|
* Copyright (c) 2015 - present Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*)
|
||||||
|
|
||||||
|
(* Module for warnings detected at translation time by the frontend
|
||||||
|
* To specify a checker define the following:
|
||||||
|
* - condition: a boolean condition when the warning should be flagged
|
||||||
|
* - description: a string describing the warning
|
||||||
|
* - loc: the location where is occurs
|
||||||
|
*)
|
||||||
|
|
||||||
|
open Utils
|
||||||
|
open CFrontend_utils
|
||||||
|
open General_utils
|
||||||
|
|
||||||
|
(* === Warnings on properties === *)
|
||||||
|
|
||||||
|
let property_checkers_list = [CFrontend_checkers.checker_strong_delegate_warning]
|
||||||
|
|
||||||
|
(* Add a frontend warning with a description desc at location loc to the errlog of a proc desc *)
|
||||||
|
let log_frontend_warning pdesc warn_desc =
|
||||||
|
let errlog = Cfg.Procdesc.get_err_log pdesc in
|
||||||
|
let err_desc =
|
||||||
|
Errdesc.explain_frontend_warning warn_desc.description warn_desc.suggestion
|
||||||
|
warn_desc.loc in
|
||||||
|
let exn = (Exceptions.Frontend_warning
|
||||||
|
(warn_desc.name, err_desc,
|
||||||
|
try assert false with Assert_failure x -> x)) in
|
||||||
|
Reporting.log_error_from_errlog errlog exn
|
||||||
|
|
||||||
|
(* Call all checkers on properties of class c *)
|
||||||
|
let check_for_property_errors cfg c =
|
||||||
|
let qual_setter setter_name =
|
||||||
|
let cname = CContext.get_curr_class_name c in
|
||||||
|
mk_procname_from_objc_method cname setter_name Procname.Instance_objc_method in
|
||||||
|
let do_one_property (pname, property) =
|
||||||
|
let (_, _, _, _, (setter_name, _), ndi) = property in
|
||||||
|
let qual_setter = qual_setter setter_name in
|
||||||
|
match Cfg.Procdesc.find_from_name cfg qual_setter with
|
||||||
|
| Some pdesc_setter -> (* Property warning will be added to the proc desc of the setter *)
|
||||||
|
Printing.log_out "Found setter for property %s\n" pname.Clang_ast_t.ni_name;
|
||||||
|
IList.iter (fun checker ->
|
||||||
|
let (condition, warning_desc) = checker pname property in
|
||||||
|
if condition then log_frontend_warning pdesc_setter warning_desc) property_checkers_list
|
||||||
|
| None ->
|
||||||
|
Printing.log_out "NO Setter Found for property %s\n" pname.Clang_ast_t.ni_name;
|
||||||
|
() in
|
||||||
|
let properties = ObjcProperty_decl.find_properties_class c in
|
||||||
|
Printing.log_out "Retrieved all properties of the class...\n";
|
||||||
|
IList.iter do_one_property properties
|
@ -0,0 +1,15 @@
|
|||||||
|
(*
|
||||||
|
* Copyright (c) 2015 - present Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*)
|
||||||
|
|
||||||
|
|
||||||
|
(* Module for warnings detected at translation time by the frontend *)
|
||||||
|
|
||||||
|
|
||||||
|
(* Checks for warnings on properties of class c *)
|
||||||
|
val check_for_property_errors : Cfg.cfg -> CContext.curr_class -> unit
|
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015 - present Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/NSObject.h>
|
||||||
|
|
||||||
|
@interface A : NSObject
|
||||||
|
- (void) bla;
|
||||||
|
|
||||||
|
@property (nonatomic,strong) id delegated;
|
||||||
|
|
||||||
|
@property (nonatomic,strong) id delegation;
|
||||||
|
|
||||||
|
@property (nonatomic,strong) id delegate;
|
||||||
|
|
||||||
|
@property (nonatomic,strong) id fileDelegate;
|
||||||
|
|
||||||
|
@property (nonatomic,strong) id delegateFile;
|
||||||
|
|
||||||
|
@property (nonatomic,strong) id OneDelegateFile;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation A {
|
||||||
|
BOOL _b;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) bla {
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015 - present Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package endtoend.objc;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static utils.matchers.ResultContainsExactly.containsExactly;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.ClassRule;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import utils.DebuggableTemporaryFolder;
|
||||||
|
import utils.InferException;
|
||||||
|
import utils.InferResults;
|
||||||
|
import utils.InferRunner;
|
||||||
|
|
||||||
|
public class StrongDelegateTest {
|
||||||
|
|
||||||
|
public static final String FILE =
|
||||||
|
"infer/tests/codetoanalyze/objc/warnings/strong_delegate.m";
|
||||||
|
|
||||||
|
private static ImmutableList<String> inferCmdFraction;
|
||||||
|
|
||||||
|
public static final String STRONG_DELEGATE_WARNING = "STRONG_DELEGATE_WARNING";
|
||||||
|
|
||||||
|
@ClassRule
|
||||||
|
public static DebuggableTemporaryFolder folder =
|
||||||
|
new DebuggableTemporaryFolder();
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void runInfer() throws InterruptedException, IOException {
|
||||||
|
inferCmdFraction = InferRunner.createObjCInferCommand(
|
||||||
|
folder,
|
||||||
|
FILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenInferRunsOnStrongDelegate()
|
||||||
|
throws InterruptedException, IOException, InferException {
|
||||||
|
InferResults inferResults = InferRunner.runInferObjC(inferCmdFraction);
|
||||||
|
assertThat(
|
||||||
|
"Results should contain a strong delegate warning",
|
||||||
|
inferResults,
|
||||||
|
containsExactly(
|
||||||
|
STRONG_DELEGATE_WARNING,
|
||||||
|
FILE,
|
||||||
|
new String[]{
|
||||||
|
"setDelegate:",
|
||||||
|
"setDelegateFile:",
|
||||||
|
"setDelegated:",
|
||||||
|
"setFileDelegate:",
|
||||||
|
"setOneDelegateFile:"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in new issue