You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

172 lines
7.1 KiB

(*
* 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! Utils
open CFrontend_utils
(* List of checkers on properties *)
let property_checkers_list = [CFrontend_checkers.strong_delegate_warning;
CFrontend_checkers.assign_pointer_warning;]
(* Invocation of checker belonging to property_checker_list *)
let checkers_for_property decl checker context =
checker context decl
(* List of checkers on ivar access *)
let ivar_access_checker_list = [CFrontend_checkers.direct_atomic_property_access_warning]
(* Invocation of checker belonging to ivar_access_checker_list *)
let checkers_for_ivar stmt checker context =
checker context stmt
(* List of checkers for captured vars in objc blocks *)
let captured_vars_checker_list = [CFrontend_checkers.captured_cxx_ref_in_objc_block_warning]
(* Invocation of checker belonging to captured_vars_checker_list *)
let checkers_for_capture_vars stmt checker context =
checker context stmt
(* List of checkers on ObjCProtocol decls *)
let objc_protocol_checker_list = [CFrontend_checkers.checker_NSNotificationCenter]
(* Invocation of checker belonging to objc_protocol_checker_list *)
let checkers_for_objc_protocol decl checker context =
checker context decl
(* List of checkers running on ObjCImpl decls *)
let objc_impl_checker_list = [CFrontend_checkers.checker_NSNotificationCenter;
ComponentKit.component_with_multiple_factory_methods_advice;
ComponentKit.component_with_unconventional_superclass_advice]
(* Invocation of checker belonging to objc_impl_checker_list *)
let checkers_for_objc_impl decl checker context =
checker context decl
let call_expr_checker_list = [ComponentKit.component_initializer_with_side_effects_advice]
(* Invocation of checker belonging to call_expr_checker_list *)
let checkers_for_call_expr stmt checker context =
checker context stmt
(* List of checkers on variables *)
let var_checker_list = [CFrontend_checkers.global_var_init_with_calls_warning;
ComponentKit.mutable_local_vars_advice]
(* Invocation of checker belonging to var_checker_list *)
let checker_for_var dec checker context =
checker context dec
(* List of checkers on if-statement *)
let if_stmt_checker_list = [CFrontend_checkers.bad_pointer_comparison_warning]
(* Invocation of checker belonging to if_stmt_checker_list *)
let checker_for_if_stmt cond checker context =
checker context cond
let function_decl_checker_list = [ComponentKit.component_factory_function_advice]
let checker_for_function_decl decl checker context =
checker context decl
let get_err_log translation_unit_context method_decl_opt =
let procname = match method_decl_opt with
| Some method_decl -> General_utils.procname_of_decl translation_unit_context method_decl
| None -> Procname.Linters_dummy_method in
LintIssues.get_err_log procname
(* Add a frontend warning with a description desc at location loc to the errlog of a proc desc *)
let log_frontend_issue translation_unit_context method_decl_opt key issue_desc =
let issue = issue_desc.CIssue.issue in
let loc = issue_desc.CIssue.loc in
let errlog = get_err_log translation_unit_context method_decl_opt in
let err_desc = Errdesc.explain_frontend_warning issue_desc.CIssue.description
issue_desc.CIssue.suggestion loc in
let name = CIssue.to_string issue in
let exn = Exceptions.Frontend_warning (name, err_desc, __POS__) in
let trace = [ Errlog.make_trace_element 0 issue_desc.CIssue.loc "" [] ] in
let err_kind = CIssue.severity_of_issue issue in
let method_name = Ast_utils.full_name_of_decl_opt method_decl_opt in
let key = Hashtbl.hash (key ^ method_name) in
Reporting.log_issue_from_errlog err_kind errlog exn ~loc ~ltr:trace
~node_id:(0, key)
(* General invocation function for checkers
Takes
1. f a particular way to apply a checker, it's a partial function
2. context
3. the list of checkers to be applied *)
let invoke_set_of_checkers f context key checkers =
IList.iter (fun checker ->
match f checker context with
| Some issue_desc ->
log_frontend_issue context.CLintersContext.translation_unit_context
context.CLintersContext.current_method key issue_desc
| None -> ()) checkers
let run_frontend_checkers_on_stmt context instr =
let open Clang_ast_t in
match instr with
| ObjCIvarRefExpr _ ->
let call_checker_for_ivar = checkers_for_ivar instr in
let key = Ast_utils.generate_key_stmt instr in
invoke_set_of_checkers
call_checker_for_ivar context key ivar_access_checker_list;
context
| BlockExpr _ ->
let call_captured_vars_checker = checkers_for_capture_vars instr in
let key = Ast_utils.generate_key_stmt instr in
invoke_set_of_checkers call_captured_vars_checker context key
captured_vars_checker_list;
context
| IfStmt _ | ConditionalOperator _ | ForStmt _ | WhileStmt _ ->
let call_checker = checker_for_if_stmt instr in
let key = Ast_utils.generate_key_stmt instr in
invoke_set_of_checkers call_checker context key if_stmt_checker_list;
context
| CallExpr (_, called_func_stmt :: _, _) ->
let call_checker = checkers_for_call_expr called_func_stmt in
let key = Ast_utils.generate_key_stmt called_func_stmt in
invoke_set_of_checkers call_checker context key call_expr_checker_list;
context
| ObjCAtSynchronizedStmt _ ->
{ context with CLintersContext.in_synchronized_block = true }
| _ -> context
let run_frontend_checkers_on_decl (context: CLintersContext.context) dec =
let open Clang_ast_t in
match dec with
| ObjCImplementationDecl _ ->
let call_objc_impl_checker = checkers_for_objc_impl dec in
let key = Ast_utils.generate_key_decl dec in
let context' = {context with current_objc_impl = Some dec} in
invoke_set_of_checkers call_objc_impl_checker context' key objc_impl_checker_list;
context'
| ObjCProtocolDecl _ ->
let call_objc_protocol_checker = checkers_for_objc_protocol dec in
let key = Ast_utils.generate_key_decl dec in
invoke_set_of_checkers call_objc_protocol_checker context key objc_protocol_checker_list;
context
| VarDecl _ ->
let call_var_checker = checker_for_var dec in
let key = Ast_utils.generate_key_decl dec in
invoke_set_of_checkers call_var_checker context key var_checker_list;
context
| FunctionDecl _ ->
let call_function_decl_checker = checker_for_function_decl dec in
let key = Ast_utils.generate_key_decl dec in
invoke_set_of_checkers call_function_decl_checker context key function_decl_checker_list;
context
| ObjCPropertyDecl _ ->
let call_property_checker = checkers_for_property dec in
let key = Ast_utils.generate_key_decl dec in
invoke_set_of_checkers call_property_checker context key property_checkers_list;
context
| _ -> context