[objc] Add methods of ObjC classes and ObjC protocols to the tenv

Reviewed By: jeremydubreil

Differential Revision: D7973463

fbshipit-source-id: 1916213
master
Dulma Churchill 7 years ago committed by Facebook Github Bot
parent 7e5381b7a9
commit 2ee4956c03

@ -30,6 +30,10 @@ let append_no_duplicates_annotations =
Staged.unstage (IList.append_no_duplicates ~cmp)
let append_no_duplicates_methods =
Staged.unstage (IList.append_no_duplicates ~cmp:Typ.Procname.compare)
let add_no_duplicates_fields field_tuple l =
let rec replace_field field_tuple l found =
match (field_tuple, l) with

@ -18,6 +18,9 @@ val add_no_duplicates_fields : Typ.Struct.field -> Typ.Struct.field list -> Typ.
val append_no_duplicates_fields :
Typ.Struct.field list -> Typ.Struct.field list -> Typ.Struct.field list
val append_no_duplicates_methods :
Typ.Procname.t list -> Typ.Procname.t list -> Typ.Procname.t list
val swap_elements_list : 'a list -> 'a list
val list_range : int -> int -> int list

@ -63,19 +63,21 @@ let get_base_class_name_from_category decl =
None
(* Add potential extra fields defined only in the category *)
(* Add potential extra fields and methods defined only in the category *)
(* to the corresponding class. Update the tenv accordingly.*)
let process_category qual_type_to_sil_type tenv class_name decl_info decl_list =
let class_tn_name = Typ.Name.Objc.from_qual_name class_name in
let decl_fields = CField_decl.get_fields qual_type_to_sil_type tenv class_tn_name decl_list in
let decl_methods = ObjcMethod_decl.get_methods class_tn_name decl_list in
let class_tn_desc = Typ.Tstruct class_tn_name in
let decl_key = Clang_ast_extend.DeclPtr decl_info.Clang_ast_t.di_pointer in
CAst_utils.update_sil_types_map decl_key class_tn_desc ;
( match Tenv.lookup tenv class_tn_name with
| Some ({fields} as struct_typ) ->
| Some ({fields; methods} as struct_typ) ->
let new_fields = CGeneral_utils.append_no_duplicates_fields decl_fields fields in
let new_methods = CGeneral_utils.append_no_duplicates_methods decl_methods methods in
ignore
(Tenv.mk_struct tenv ~default:struct_typ ~fields:new_fields ~statics:[] ~methods:[]
(Tenv.mk_struct tenv ~default:struct_typ ~fields:new_fields ~methods:new_methods
class_tn_name) ;
L.(debug Capture Verbose)
" Updating info for class '%a' in tenv@\n" QualifiedCppName.pp class_name

@ -91,52 +91,37 @@ let append_no_duplicates_typ_name =
(* Adds pairs (interface name, interface_type_info) to the global environment. *)
let add_class_to_tenv qual_type_to_sil_type tenv decl_info name_info decl_list ocidi =
let class_name = CAst_utils.get_qualified_name name_info in
L.(debug Capture Verbose) "ADDING: ObjCInterfaceDecl for '%a'@\n" QualifiedCppName.pp class_name ;
let interface_name = Typ.Name.Objc.from_qual_name class_name in
let interface_desc = Typ.Tstruct interface_name in
let decl_key = Clang_ast_extend.DeclPtr decl_info.Clang_ast_t.di_pointer in
CAst_utils.update_sil_types_map decl_key interface_desc ;
(* We don't need to add the methods of the superclass *)
let decl_supers, decl_fields =
create_supers_fields qual_type_to_sil_type tenv interface_name decl_list
ocidi.Clang_ast_t.otdi_super ocidi.Clang_ast_t.otdi_protocols
in
let fields_sc = CField_decl.fields_superclass tenv ocidi in
List.iter
~f:(fun (fn, ft, _) ->
L.(debug Capture Verbose) "----->SuperClass field: '%s' " (Typ.Fieldname.to_string fn) ;
L.(debug Capture Verbose) "type: '%s'@\n" (Typ.to_string ft) )
fields_sc ;
(*In case we found categories, or partial definition of this class earlier and they are already in the tenv *)
let fields, (supers: Typ.Name.t list) =
let fields, (supers: Typ.Name.t list), methods =
match Tenv.lookup tenv interface_name with
| Some {fields; supers} ->
| Some {fields; supers; methods} ->
( CGeneral_utils.append_no_duplicates_fields decl_fields fields
, append_no_duplicates_typ_name decl_supers supers )
, append_no_duplicates_typ_name decl_supers supers
, methods )
| _ ->
(decl_fields, decl_supers)
(decl_fields, decl_supers, [])
in
let fields = CGeneral_utils.append_no_duplicates_fields fields fields_sc in
let modelled_fields = CField_decl.modelled_field name_info in
let all_fields = CGeneral_utils.append_no_duplicates_fields modelled_fields fields in
L.(debug Capture Verbose) "Class %a field:@\n" QualifiedCppName.pp class_name ;
List.iter
~f:(fun (fn, _, _) ->
L.(debug Capture Verbose) "-----> field: '%s'@\n" (Typ.Fieldname.to_string fn) )
all_fields ;
let methods =
CGeneral_utils.append_no_duplicates_methods
(ObjcMethod_decl.get_methods interface_name decl_list)
methods
in
ignore
(Tenv.mk_struct tenv ~fields:all_fields ~supers ~methods:[] ~annots:Annot.Class.objc
(Tenv.mk_struct tenv ~fields:all_fields ~supers ~methods ~annots:Annot.Class.objc
interface_name) ;
L.(debug Capture Verbose)
" >>>Verifying that Typename '%s' is in tenv@\n"
(Typ.Name.to_string interface_name) ;
( match Tenv.lookup tenv interface_name with
| Some st ->
L.(debug Capture Verbose)
" >>>OK. Found typ='%a'@\n"
(Typ.Struct.pp Pp.text interface_name)
st
| None ->
L.(debug Capture Verbose) " >>>NOT Found!!@\n" ) ;
interface_desc
@ -162,12 +147,15 @@ let interface_impl_declaration qual_type_to_sil_type tenv decl =
match decl with
| ObjCImplementationDecl (decl_info, name_info, decl_list, _, idi) ->
let class_name = CAst_utils.get_qualified_name name_info in
let interface_name = Typ.Name.Objc.from_qual_name class_name in
L.(debug Capture Verbose)
"ADDING: ObjCImplementationDecl for class '%a'@\n" QualifiedCppName.pp class_name ;
let _ = add_class_decl qual_type_to_sil_type tenv idi in
let class_tn_name = Typ.Name.Objc.from_qual_name class_name in
let fields = CField_decl.get_fields qual_type_to_sil_type tenv class_tn_name decl_list in
CField_decl.add_missing_fields tenv class_name fields ;
let methods = ObjcMethod_decl.get_methods interface_name decl_list in
ObjcMethod_decl.add_missing_methods tenv class_tn_name methods ;
let decl_key = Clang_ast_extend.DeclPtr decl_info.Clang_ast_t.di_pointer in
let class_desc = Typ.Tstruct class_tn_name in
CAst_utils.update_sil_types_map decl_key class_desc ;

@ -0,0 +1,38 @@
(*
* Copyright (c) 2018 - 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.
*)
(* Given a list of declarations in an interface returns list of methods *)
open! IStd
let get_methods class_typename decl_list =
let open Clang_ast_t in
let get_method list_methods decl =
match decl with
| Clang_ast_t.ObjCMethodDecl (_, ndi, mdi) ->
let method_kind =
Typ.Procname.ObjC_Cpp.objc_method_kind_of_bool mdi.omdi_is_instance_method
in
let method_name =
Typ.Procname.ObjC_Cpp
(Typ.Procname.ObjC_Cpp.make class_typename ndi.ni_name method_kind Typ.NoTemplate)
in
method_name :: list_methods
| _ ->
list_methods
in
List.fold_left ~f:get_method decl_list ~init:[]
let add_missing_methods tenv class_tn_name missing_methods =
match Tenv.lookup tenv class_tn_name with
| Some ({methods} as struct_typ) ->
let new_methods = CGeneral_utils.append_no_duplicates_methods methods missing_methods in
ignore (Tenv.mk_struct tenv ~default:struct_typ ~methods:new_methods class_tn_name)
| _ ->
()

@ -0,0 +1,12 @@
(*
* Copyright (c) 2018 - 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.
*)
val get_methods : Typ.name -> Clang_ast_t.decl list -> Typ.Procname.t list
val add_missing_methods : Tenv.t -> Typ.name -> Typ.Procname.t list -> unit
Loading…
Cancel
Save