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