(* * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. *) module PointerOrd = struct type t = int let compare (i : int) (j : int) = i - j end module PointerMap = Map.Make (PointerOrd) let declMap = ref PointerMap.empty let stmtMap = ref PointerMap.empty let typeMap = ref PointerMap.empty let ivarToPropertyMap = ref PointerMap.empty let empty_v = Clang_ast_visit.empty_visitor (* This function is not thread-safe *) let visit_ast ?(visit_decl = empty_v) ?(visit_stmt = empty_v) ?(visit_type = empty_v) ?(visit_src_loc = empty_v) top_decl = Clang_ast_visit.decl_visitor := visit_decl ; Clang_ast_visit.stmt_visitor := visit_stmt ; Clang_ast_visit.type_visitor := visit_type ; Clang_ast_visit.source_location_visitor := visit_src_loc ; (* visit *) ignore (Clang_ast_v.validate_decl [] top_decl) let get_ptr_from_node node = match node with | `DeclNode decl -> let decl_info = Clang_ast_proj.get_decl_tuple decl in decl_info.Clang_ast_t.di_pointer | `StmtNode stmt -> let stmt_info, _ = Clang_ast_proj.get_stmt_tuple stmt in stmt_info.Clang_ast_t.si_pointer | `TypeNode c_type -> let type_info = Clang_ast_proj.get_type_tuple c_type in type_info.Clang_ast_t.ti_pointer let get_val_from_node node = match node with `DeclNode decl -> decl | `StmtNode stmt -> stmt | `TypeNode c_type -> c_type let add_node_to_cache node cache = let key = get_ptr_from_node node in let value = get_val_from_node node in cache := PointerMap.add key value !cache let process_decl _path decl = add_node_to_cache (`DeclNode decl) declMap ; match decl with | Clang_ast_t.ObjCPropertyDecl (_, _, obj_c_property_decl_info) -> ( match obj_c_property_decl_info.Clang_ast_t.opdi_ivar_decl with | Some decl_ref -> let ivar_pointer = decl_ref.Clang_ast_t.dr_decl_pointer in ivarToPropertyMap := PointerMap.add ivar_pointer decl !ivarToPropertyMap | None -> () ) | _ -> () let add_stmt_to_cache _path stmt = add_node_to_cache (`StmtNode stmt) stmtMap let add_type_to_cache _path c_type = add_node_to_cache (`TypeNode c_type) typeMap let previous_sloc = {Clang_ast_t.sl_file= None; sl_line= None; sl_column= None} let get_sloc current previous = match current with None -> previous | Some _ -> current let mutate_sloc sloc file line column = let open Clang_ast_t in sloc.sl_file <- file ; sloc.sl_line <- line ; sloc.sl_column <- column let reset_sloc sloc = mutate_sloc sloc None None None let complete_source_location _path source_loc = let open Clang_ast_t in let file = get_sloc source_loc.sl_file previous_sloc.sl_file in let line = get_sloc source_loc.sl_line previous_sloc.sl_line in let column = get_sloc source_loc.sl_column previous_sloc.sl_column in mutate_sloc source_loc file line column ; mutate_sloc previous_sloc file line column let reset_cache () = declMap := PointerMap.empty ; stmtMap := PointerMap.empty ; typeMap := PointerMap.empty ; ivarToPropertyMap := PointerMap.empty ; reset_sloc previous_sloc (* This function is not thread-safe *) let index_node_pointers top_decl = (* just in case *) reset_cache () ; (* populate cache *) visit_ast ~visit_decl:process_decl ~visit_stmt:add_stmt_to_cache ~visit_type:add_type_to_cache ~visit_src_loc:complete_source_location top_decl ; let result = (!declMap, !stmtMap, !typeMap, !ivarToPropertyMap) in reset_cache () ; result