[linters] Add a new linter UNAVAILABLE_CLASS_IN_SUPPORTED_IOS_SDK for checking unavailable classes in supported ios sdk

Reviewed By: akotulski

Differential Revision: D5381931

fbshipit-source-id: 13e36df
master
Dulma Churchill 7 years ago committed by Facebook Github Bot
parent bab3d81cb0
commit 7c384669eb

@ -223,6 +223,19 @@ DEFINE-CHECKER CXX_REFERENCE_CAPTURED_IN_OBJC_BLOCK = {
SET severity = "ERROR"; SET severity = "ERROR";
}; };
DEFINE-CHECKER UNAVAILABLE_CLASS_IN_SUPPORTED_IOS_SDK = {
SET report_when =
WHEN (class_unavailable_in_supported_ios_sdk())
HOLDS-IN-NODE ObjCMessageExpr;
SET message =
"The receiver %receiver_method_call% of %name% is not available in the required iOS SDK version
%iphoneos_target_sdk_version% (only available from version %class_available_ios_sdk%)";
SET name = "Unavailable API In Supported iOS SDK";
SET severity = "ERROR";
SET mode = "OFF";
};
DEFINE-CHECKER POINTER_TO_INTEGRAL_IMPLICIT_CAST = { DEFINE-CHECKER POINTER_TO_INTEGRAL_IMPLICIT_CAST = {
SET report_when = SET report_when =

@ -66,6 +66,27 @@ let available_ios_sdk an =
( "available_ios_sdk must be called with a DeclRefExpr or an ObjCMessageExpr, but got " ( "available_ios_sdk must be called with a DeclRefExpr or an ObjCMessageExpr, but got "
^ tag_name_of_node an ) ^ tag_name_of_node an )
let class_available_ios_sdk an =
match CPredicates.receiver_method_call an with
| Some decl -> (
match CPredicates.get_available_attr_ios_sdk (Decl decl) with
| Some version
-> version
| None
-> "" )
| None
-> failwith
( "class_available_ios_sdk must be called with ObjCMessageExpr, but got "
^ tag_name_of_node an )
let receiver_method_call an =
match CPredicates.receiver_method_call an with
| Some decl
-> Ctl_parser_types.ast_node_name (Ctl_parser_types.Decl decl)
| _
-> failwith
("receiver_method_call must be called with ObjCMessageExpr, but got " ^ tag_name_of_node an)
let ivar_name an = let ivar_name an =
let open Clang_ast_t in let open Clang_ast_t in
match an with match an with

@ -27,4 +27,8 @@ val iphoneos_target_sdk_version : Ctl_parser_types.ast_node -> string
val available_ios_sdk : Ctl_parser_types.ast_node -> string val available_ios_sdk : Ctl_parser_types.ast_node -> string
val class_available_ios_sdk : Ctl_parser_types.ast_node -> string
val receiver_method_call : Ctl_parser_types.ast_node -> string
val tag_name_of_node : Ctl_parser_types.ast_node -> string val tag_name_of_node : Ctl_parser_types.ast_node -> string

@ -104,10 +104,14 @@ let evaluate_place_holder ph an =
-> MF.monospaced_to_string (CFrontend_checkers.cxx_ref_captured_in_block an) -> MF.monospaced_to_string (CFrontend_checkers.cxx_ref_captured_in_block an)
| "%decl_ref_or_selector_name%" | "%decl_ref_or_selector_name%"
-> MF.monospaced_to_string (CFrontend_checkers.decl_ref_or_selector_name an) -> MF.monospaced_to_string (CFrontend_checkers.decl_ref_or_selector_name an)
| "%receiver_method_call%"
-> MF.monospaced_to_string (CFrontend_checkers.receiver_method_call an)
| "%iphoneos_target_sdk_version%" | "%iphoneos_target_sdk_version%"
-> MF.monospaced_to_string (CFrontend_checkers.iphoneos_target_sdk_version an) -> MF.monospaced_to_string (CFrontend_checkers.iphoneos_target_sdk_version an)
| "%available_ios_sdk%" | "%available_ios_sdk%"
-> MF.monospaced_to_string (CFrontend_checkers.available_ios_sdk an) -> MF.monospaced_to_string (CFrontend_checkers.available_ios_sdk an)
| "%class_available_ios_sdk%"
-> MF.monospaced_to_string (CFrontend_checkers.class_available_ios_sdk an)
| "%type%" | "%type%"
-> MF.monospaced_to_string (Ctl_parser_types.ast_node_type an) -> MF.monospaced_to_string (Ctl_parser_types.ast_node_type an)
| "%child_type%" | "%child_type%"

@ -14,6 +14,42 @@ module L = Logging
let parsed_type_map : Ctl_parser_types.abs_ctype String.Map.t ref = ref String.Map.empty let parsed_type_map : Ctl_parser_types.abs_ctype String.Map.t ref = ref String.Map.empty
let rec objc_class_of_pointer_type type_ptr =
match CAst_utils.get_type type_ptr with
| Some ObjCInterfaceType (_, decl_ptr)
-> CAst_utils.get_decl decl_ptr
| Some ObjCObjectPointerType (_, inner_qual_type)
-> objc_class_of_pointer_type inner_qual_type.qt_type_ptr
| Some AttributedType (type_info, _) -> (
match type_info.ti_desugared_type with
| Some type_ptr
-> objc_class_of_pointer_type type_ptr
| None
-> None )
| _
-> None
let receiver_method_call an =
match an with
| Ctl_parser_types.Stmt ObjCMessageExpr (_, args, _, obj_c_message_expr_info) -> (
match obj_c_message_expr_info.omei_receiver_kind with
| `Class qt
-> CAst_utils.get_decl_from_typ_ptr qt.qt_type_ptr
| `Instance -> (
match args with
| receiver :: _ -> (
match Clang_ast_proj.get_expr_tuple receiver with
| Some (_, _, expr_info)
-> objc_class_of_pointer_type expr_info.ei_qual_type.qt_type_ptr
| None
-> None )
| []
-> None )
| _
-> None )
| _
-> None
let get_available_attr_ios_sdk an = let get_available_attr_ios_sdk an =
let open Clang_ast_t in let open Clang_ast_t in
let rec get_available_attr attrs = let rec get_available_attr attrs =
@ -411,6 +447,13 @@ let decl_unavailable_in_supported_ios_sdk (cxt: CLintersContext.context) an =
| _ | _
-> false -> false
let class_unavailable_in_supported_ios_sdk (cxt: CLintersContext.context) an =
match receiver_method_call an with
| Some decl
-> decl_unavailable_in_supported_ios_sdk cxt (Ctl_parser_types.Decl decl)
| None
-> false
(* Check whether a type_ptr and a string denote the same type *) (* Check whether a type_ptr and a string denote the same type *)
let type_ptr_equal_type type_ptr type_str = let type_ptr_equal_type type_ptr type_str =
let pos_str lexbuf = let pos_str lexbuf =

@ -72,6 +72,9 @@ val pp_predicate : Format.formatter -> t -> unit
val decl_unavailable_in_supported_ios_sdk : val decl_unavailable_in_supported_ios_sdk :
CLintersContext.context -> Ctl_parser_types.ast_node -> bool CLintersContext.context -> Ctl_parser_types.ast_node -> bool
val class_unavailable_in_supported_ios_sdk :
CLintersContext.context -> Ctl_parser_types.ast_node -> bool
val has_type : Ctl_parser_types.ast_node -> ALVar.alexp -> bool val has_type : Ctl_parser_types.ast_node -> ALVar.alexp -> bool
val method_return_type : Ctl_parser_types.ast_node -> ALVar.alexp -> bool val method_return_type : Ctl_parser_types.ast_node -> ALVar.alexp -> bool
@ -87,3 +90,5 @@ val objc_method_has_nth_parameter_of_type :
Ctl_parser_types.ast_node -> ALVar.alexp -> ALVar.alexp -> bool Ctl_parser_types.ast_node -> ALVar.alexp -> ALVar.alexp -> bool
val using_namespace : Ctl_parser_types.ast_node -> ALVar.alexp -> bool val using_namespace : Ctl_parser_types.ast_node -> ALVar.alexp -> bool
val receiver_method_call : Ctl_parser_types.ast_node -> Clang_ast_t.decl option

@ -744,6 +744,8 @@ let rec eval_Atomic _pred_name args an lcxt =
-> CPredicates.declaration_ref_name an decl_name -> CPredicates.declaration_ref_name an decl_name
| "decl_unavailable_in_supported_ios_sdk", [], an | "decl_unavailable_in_supported_ios_sdk", [], an
-> CPredicates.decl_unavailable_in_supported_ios_sdk lcxt an -> CPredicates.decl_unavailable_in_supported_ios_sdk lcxt an
| "class_unavailable_in_supported_ios_sdk", [], an
-> CPredicates.class_unavailable_in_supported_ios_sdk lcxt an
| "has_cast_kind", [name], an | "has_cast_kind", [name], an
-> CPredicates.has_cast_kind an name -> CPredicates.has_cast_kind an name
| "has_type", [typ], an | "has_type", [typ], an

@ -4,6 +4,9 @@ codetoanalyze/objc/ioslints/unavailable_api_allowed_cases.m, Unavailable_api_all
codetoanalyze/objc/ioslints/unavailable_api_allowed_cases.m, Unavailable_api_allowed_cases_with_responds_to_selector_in_else:, 71, UNAVAILABLE_API_IN_SUPPORTED_IOS_SDK, [] codetoanalyze/objc/ioslints/unavailable_api_allowed_cases.m, Unavailable_api_allowed_cases_with_responds_to_selector_in_else:, 71, UNAVAILABLE_API_IN_SUPPORTED_IOS_SDK, []
codetoanalyze/objc/ioslints/unavailable_api_allowed_cases.m, Unavailable_api_allowed_cases_without_instances_responds_to_selector, 95, UNAVAILABLE_API_IN_SUPPORTED_IOS_SDK, [] codetoanalyze/objc/ioslints/unavailable_api_allowed_cases.m, Unavailable_api_allowed_cases_without_instances_responds_to_selector, 95, UNAVAILABLE_API_IN_SUPPORTED_IOS_SDK, []
codetoanalyze/objc/ioslints/unavailable_api_allowed_cases.m, Unavailable_api_allowed_cases_without_responds_to_selector:, 64, UNAVAILABLE_API_IN_SUPPORTED_IOS_SDK, [] codetoanalyze/objc/ioslints/unavailable_api_allowed_cases.m, Unavailable_api_allowed_cases_without_responds_to_selector:, 64, UNAVAILABLE_API_IN_SUPPORTED_IOS_SDK, []
codetoanalyze/objc/ioslints/unavailable_api_in_supported_ios_sdk.m, OpenURLOptionsFromSourceApplication, 26, UNAVAILABLE_API_IN_SUPPORTED_IOS_SDK, [] codetoanalyze/objc/ioslints/unavailable_api_in_supported_ios_sdk.m, OpenURLOptionsFromSourceApplication, 51, UNAVAILABLE_API_IN_SUPPORTED_IOS_SDK, []
codetoanalyze/objc/ioslints/unavailable_api_in_supported_ios_sdk.m, Unavailable_api_in_supported_ios_sdk_test:and:, 19, UNAVAILABLE_API_IN_SUPPORTED_IOS_SDK, [] codetoanalyze/objc/ioslints/unavailable_api_in_supported_ios_sdk.m, Unavailable_api_in_supported_ios_sdk_test:and:, 28, UNAVAILABLE_API_IN_SUPPORTED_IOS_SDK, []
codetoanalyze/objc/ioslints/unavailable_api_in_supported_ios_sdk.m, Unavailable_api_in_supported_ios_sdk_unsupported_class, 34, UNAVAILABLE_CLASS_IN_SUPPORTED_IOS_SDK, []
codetoanalyze/objc/ioslints/unavailable_api_in_supported_ios_sdk.m, Unavailable_api_in_supported_ios_sdk_unsupported_class, 34, UNAVAILABLE_CLASS_IN_SUPPORTED_IOS_SDK, []
codetoanalyze/objc/ioslints/unavailable_api_in_supported_ios_sdk.m, Unavailable_api_in_supported_ios_sdk_unsupported_class_with_attributes:, 44, UNAVAILABLE_CLASS_IN_SUPPORTED_IOS_SDK, []
codetoanalyze/objc/ioslints/unavailable_property_ios.m, FNFPlayerLayer_initWithConfigs:, 22, UNAVAILABLE_API_IN_SUPPORTED_IOS_SDK, [] codetoanalyze/objc/ioslints/unavailable_property_ios.m, FNFPlayerLayer_initWithConfigs:, 22, UNAVAILABLE_API_IN_SUPPORTED_IOS_SDK, []

@ -7,6 +7,15 @@
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
*/ */
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
NS_CLASS_AVAILABLE(10_12, 10_0)
@interface Unav_class : NSObject
- (void)m;
@end
@interface Unavailable_api_in_supported_ios_sdk : NSObject @interface Unavailable_api_in_supported_ios_sdk : NSObject
@ -18,6 +27,22 @@
NSDictionary* cacheData = NSDictionary* cacheData =
[NSKeyedUnarchiver unarchiveTopLevelObjectWithData:data error:nil]; [NSKeyedUnarchiver unarchiveTopLevelObjectWithData:data error:nil];
} }
// bug
- (void)unsupported_class {
AVPlayerLooper* looper =
[[AVPlayerLooper alloc] initWithPlayer:nil
templateItem:nil
timeRange:kCMTimeRangeInvalid];
if (!looper) {
NSLog(@"");
}
}
// bug
- (void)unsupported_class_with_attributes:(nonnull Unav_class*)c {
[c m];
}
@end @end
static NSDictionary* OpenURLOptionsFromSourceApplication( static NSDictionary* OpenURLOptionsFromSourceApplication(

Loading…
Cancel
Save