@ -23,9 +23,9 @@ type method_kind =
(* java_signature extends base_signature with a classname and a package *)
(* java_signature extends base_signature with a classname and a package *)
type java_signature = {
type java_signature = {
class name: java_type ;
class _ name: java_type ;
return type: java_type option ; (* option because constructors have no return type *)
return _ type: java_type option ; (* option because constructors have no return type *)
method name: string ;
method _ name: string ;
parameters : java_type list ;
parameters : java_type list ;
kind : method_kind
kind : method_kind
}
}
@ -51,25 +51,29 @@ type c_method_signature = {
}
}
type t =
type t =
| JAVA of java_signature
| Java_method of java_signature
| C_FUNCTION of string * ( string option ) (* it is a pair ( plain, mangled optional ) *)
| STATIC of string * ( string option ) (* it is a pair ( plain name, filename optional ) *)
(* a pair ( plain, mangled optional ) for standard C function *)
| C_METHOD of c_method_signature
| C_function of string * ( string option )
| OBJC_BLOCK of string
(* structure with class name and method name for methods in Objective C and C++ *)
| ObjC_Cpp_method of c_method_signature
| ObjC_block of string
(* Defines the level of verbosity of some to_string functions *)
(* Defines the level of verbosity of some to_string functions *)
type detail_level =
type detail_level =
| VERBOSE
| V erbose
| N ON_VERBOSE
| N on_verbose
| S IMPLE
| S imple
let empty = O BJC_BLOCK " "
let empty = O bjC_block " "
let is_verbose v =
let is_verbose v =
match v with
match v with
| V ERBOSE -> true
| V erbose -> true
| _ -> false
| _ -> false
type proc_name = t
type proc_name = t
@ -103,7 +107,7 @@ let rec java_param_list_to_string inputList verbosity =
(* * It is the same as java_type_to_string, but Java return types are optional because of constructors without type *)
(* * It is the same as java_type_to_string, but Java return types are optional because of constructors without type *)
let java_return_type_to_string j verbosity =
let java_return_type_to_string j verbosity =
match j . return type with
match j . return _ type with
| None -> " "
| None -> " "
| Some typ ->
| Some typ ->
java_type_to_string typ verbosity
java_type_to_string typ verbosity
@ -127,11 +131,11 @@ let java_return_type_compare jr1 jr2 =
| Some jt1 , Some jt2 -> java_type_compare jt1 jt2
| Some jt1 , Some jt2 -> java_type_compare jt1 jt2
(* * Compare java signatures. *)
(* * Compare java signatures. *)
let java_sig_compare js1 j s2 =
let java_sig_compare ( js1 : j ava_signature) ( j s2 : java_signature ) =
string_compare js1 . method name js2 . method name
string_compare js1 . method _ name js2 . method _ name
| > next java_type_list_compare js1 . parameters js2 . parameters
| > next java_type_list_compare js1 . parameters js2 . parameters
| > next java_type_compare js1 . class name js2 . class name
| > next java_type_compare js1 . class _ name js2 . class _ name
| > next java_return_type_compare js1 . return type js2 . return type
| > next java_return_type_compare js1 . return _ type js2 . return _ type
| > next method_kind_compare js1 . kind js2 . kind
| > next method_kind_compare js1 . kind js2 . kind
let c_function_mangled_compare mangled1 mangled2 =
let c_function_mangled_compare mangled1 mangled2 =
@ -148,33 +152,28 @@ let c_meth_sig_compare osig1 osig2 =
| > next string_compare osig1 . class_name osig2 . class_name
| > next string_compare osig1 . class_name osig2 . class_name
| > next c_function_mangled_compare osig1 . mangled osig2 . mangled
| > next c_function_mangled_compare osig1 . mangled osig2 . mangled
(* * Given a package.classname string, it looks for the latest dot and split the string in two ( package, classname ) *)
(* * Given a package.class_name string, it looks for the latest dot and split the string
in two ( package , class_name ) * )
let split_classname package_classname =
let split_classname package_classname =
string_split_character package_classname '.'
string_split_character package_classname '.'
let from_string_c_fun ( s : string ) = C_ FUNCTION ( s , None )
let from_string_c_fun ( s : string ) = C_ function ( s , None )
let mangled_c_fun ( plain : string ) ( mangled : string ) = C_FUNCTION ( plain , Some mangled )
let mangled_c_fun ( plain : string ) ( mangled : string ) = C_function ( plain , Some mangled )
(* * Create a static procedure name from a plain name and source file *)
let mangled_static ( plain : string ) ( source_file : DB . source_file ) =
let mangled =
if ! Config . long_static_proc_names then Some ( DB . source_file_encoding source_file )
else None in STATIC ( plain , mangled )
(* * Creates a java procname, given classname, return type, method name and its parameters *)
(* * Creates a java procname, given classname, return type, method name and its parameters *)
let mangled_java class_name ret_type method_name params _ kind =
let mangled_java class_name ret_type method_name params _ kind =
J AVA {
Java_method {
class name = class_name ;
class_name = class_name ;
return type = ret_type ;
return_type = ret_type ;
method name = method_name ;
method _ name = method_name ;
parameters = params ;
parameters = params ;
kind = _ kind
kind = _ kind
}
}
(* * Create an objc procedure name from a class_name and method_name. *)
(* * Create an objc procedure name from a class_name and method_name. *)
let mangled_c_method class_name method_name mangled =
let mangled_c_method class_name method_name mangled =
C_METHOD {
ObjC_Cpp_method {
class_name = class_name ;
class_name = class_name ;
method_name = method_name ;
method_name = method_name ;
mangled = mangled ;
mangled = mangled ;
@ -182,37 +181,37 @@ let mangled_c_method class_name method_name mangled =
(* * Create an objc procedure name from a class_name and method_name. *)
(* * Create an objc procedure name from a class_name and method_name. *)
let mangled_objc_block name =
let mangled_objc_block name =
O BJC_BLOCK name
O bjC_block name
let is_java = function
let is_java = function
| J AVA _ -> true
| J ava_method _ -> true
| _ -> false
| _ -> false
let is_c_method = function
let is_c_method = function
| C_METHOD _ -> true
| ObjC_Cpp_method _ -> true
| _ -> false
| _ -> false
(* * Replace package and classname of a java procname. *)
(* * Replace package and classname of a java procname. *)
let java_replace_class p package_classname =
let java_replace_class p package_classname =
match p with
match p with
| J AVA j -> JAVA { j with class name = ( split_classname package_classname ) }
| J ava_method j -> Java_method { j with class_ name = ( split_classname package_classname ) }
| _ -> assert false
| _ -> assert false
(* * Replace the class name of an objc procedure name. *)
(* * Replace the class name of an objc procedure name. *)
let c_method_replace_class t class_name =
let c_method_replace_class t class_name =
match t with
match t with
| C_METHOD osig -> C_METHOD { osig with class_name = class_name }
| ObjC_Cpp_method osig -> ObjC_Cpp_method { osig with class_name = class_name }
| _ -> assert false
| _ -> assert false
(* * Get the class name of a Objective-C/C++ procedure name. *)
(* * Get the class name of a Objective-C/C++ procedure name. *)
let c_get_class t =
let c_get_class t =
match t with
match t with
| C_METHOD osig -> osig . class_name
| ObjC_Cpp_method osig -> osig . class_name
| _ -> assert false
| _ -> assert false
(* * Return the package.classname of a java procname. *)
(* * Return the package.classname of a java procname. *)
let java_get_class = function
let java_get_class = function
| J AVA j -> java_type_to_string j . classname VERBOSE
| J ava_method j -> java_type_to_string j . class_name Verbose
| _ -> assert false
| _ -> assert false
(* * Return path components of a java class name *)
(* * Return path components of a java class name *)
@ -221,80 +220,82 @@ let java_get_class_components proc_name =
(* * Return the class name of a java procedure name. *)
(* * Return the class name of a java procedure name. *)
let java_get_simple_class = function
let java_get_simple_class = function
| J AVA j -> snd j . class name
| J ava_method j -> snd j . class _ name
| _ -> assert false
| _ -> assert false
(* * Return the package of a java procname. *)
(* * Return the package of a java procname. *)
let java_get_package = function
let java_get_package = function
| J AVA j -> fst j . class name
| J ava_method j -> fst j . class _ name
| _ -> assert false
| _ -> assert false
(* * Return the method of a java procname. *)
(* * Return the method of a java procname. *)
let java_get_method = function
let java_get_method = function
| J AVA j -> j . method name
| J ava_method j -> j . method _ name
| _ -> assert false
| _ -> assert false
(* * Replace the method of a java procname. *)
(* * Replace the method of a java procname. *)
let java_replace_method p mname = match p with
let java_replace_method p mname = match p with
| J AVA p -> JAVA { p with method name = mname }
| J ava_method p -> Java_method { p with method_ name = mname }
| _ -> assert false
| _ -> assert false
(* * Replace the return type of a java procname. *)
(* * Replace the return type of a java procname. *)
let java_replace_return_type p ret_type = match p with
let java_replace_return_type p ret_type = match p with
| J AVA p -> JAVA { p with return type = Some ret_type }
| J ava_method p -> Java_method { p with return_ type = Some ret_type }
| _ -> assert false
| _ -> assert false
(* * Return the method of a objc/c++ procname. *)
(* * Return the method of a objc/c++ procname. *)
let c_get_method = function
let c_get_method = function
| C_METHOD name -> name . method_name
| ObjC_Cpp_method name -> name . method_name
| C_ FUNCTION ( name , _ ) -> name
| C_ function ( name , _ ) -> name
| O BJC_BLOCK name -> name
| O bjC_block name -> name
| _ -> assert false
| _ -> assert false
(* * Return the return type of a java procname. *)
(* * Return the return type of a java procname. *)
let java_get_return_type = function
let java_get_return_type = function
| J AVA j -> java_return_type_to_string j VERBOSE
| J ava_method j -> java_return_type_to_string j Verbose
| _ -> assert false
| _ -> assert false
(* * Return the parameters of a java procname. *)
(* * Return the parameters of a java procname. *)
let java_get_parameters = function
let java_get_parameters = function
| J AVA j -> IList . map ( fun param -> java_type_to_string param V ERBOSE ) j . parameters
| J ava_method j -> IList . map ( fun param -> java_type_to_string param V erbose ) j . parameters
| _ -> assert false
| _ -> assert false
(* * Return true if the java procedure is static *)
(* * Return true if the java procedure is static *)
let java_is_static = function
let java_is_static = function
| J AVA j -> j . kind = Static
| J ava_method j -> j . kind = Static
| _ -> assert false
| _ -> assert false
(* * Prints a string of a java procname with the given level of verbosity *)
(* * Prints a string of a java procname with the given level of verbosity *)
let java_to_string ? ( withclass = false ) j verbosity =
let java_to_string ? ( withclass = false ) j verbosity =
match verbosity with
match verbosity with
| V ERBOSE | NON_VERBOSE ->
| V erbose | Non_verbose ->
(* if verbose, then package.class.method ( params ) : rtype,
(* if verbose, then package.class.method ( params ) : rtype,
else rtype package . class . method ( params )
else rtype package . class . method ( params )
verbose is used for example to create unique filenames , non_verbose to create reports * )
verbose is used for example to create unique filenames , non_verbose to create reports * )
let return_type = java_return_type_to_string j verbosity in
let return_type = java_return_type_to_string j verbosity in
let params = java_param_list_to_string j . parameters verbosity in
let params = java_param_list_to_string j . parameters verbosity in
let class name = java_type_to_string j . class name verbosity in
let class _ name = java_type_to_string j . class _ name verbosity in
let separator =
let separator =
match j . return type, verbosity with
match j . return _ type, verbosity with
| ( None , _ ) -> " "
| ( None , _ ) -> " "
| ( Some _ , V ERBOSE ) -> " : "
| ( Some _ , V erbose ) -> " : "
| _ -> " " in
| _ -> " " in
let output = class name ^ " . " ^ j . method name ^ " ( " ^ params ^ " ) " in
let output = class _ name ^ " . " ^ j . method _ name ^ " ( " ^ params ^ " ) " in
if verbosity = V ERBOSE then output ^ separator ^ return_type
if verbosity = V erbose then output ^ separator ^ return_type
else return_type ^ separator ^ output
else return_type ^ separator ^ output
| S IMPLE -> (* methodname ( ... ) or without ... if there are no parameters *)
| S imple -> (* methodname ( ... ) or without ... if there are no parameters *)
let cls_prefix =
let cls_prefix =
if withclass then
if withclass then
java_type_to_string j . class name verbosity ^ " . "
java_type_to_string j . class _ name verbosity ^ " . "
else " " in
else " " in
let params =
let params =
match j . parameters with
match j . parameters with
| [] -> " "
| [] -> " "
| _ -> " ... " in
| _ -> " ... " in
let methodname = if j . methodname = " <init> " then java_get_simple_class ( JAVA j ) else j . methodname in
let method_name =
cls_prefix ^ methodname ^ " ( " ^ params ^ " ) "
if j . method_name = " <init> " then java_get_simple_class ( Java_method j )
else j . method_name in
cls_prefix ^ method_name ^ " ( " ^ params ^ " ) "
(* * Check if the class name is for an anonymous inner class. *)
(* * Check if the class name is for an anonymous inner class. *)
let is_anonymous_inner_class_name class_name =
let is_anonymous_inner_class_name class_name =
@ -307,34 +308,34 @@ let is_anonymous_inner_class_name class_name =
(* * Check if the procedure belongs to an anonymous inner class. *)
(* * Check if the procedure belongs to an anonymous inner class. *)
let java_is_anonymous_inner_class = function
let java_is_anonymous_inner_class = function
| J AVA j -> is_anonymous_inner_class_name ( snd j . class name)
| J ava_method j -> is_anonymous_inner_class_name ( snd j . class _ name)
| _ -> false
| _ -> false
(* * Check if the last parameter is a hidden inner class, and remove it if present.
(* * Check if the last parameter is a hidden inner class, and remove it if present.
This is used in private constructors , where a proxy constructor is generated
This is used in private constructors , where a proxy constructor is generated
with an extra parameter and calls the normal constructor . * )
with an extra parameter and calls the normal constructor . * )
let java_remove_hidden_inner_class_parameter = function
let java_remove_hidden_inner_class_parameter = function
| J AVA js ->
| J ava_method js ->
( match IList . rev js . parameters with
( match IList . rev js . parameters with
| ( so , s ) :: par' ->
| ( so , s ) :: par' ->
if is_anonymous_inner_class_name s
if is_anonymous_inner_class_name s
then Some ( J AVA { js with parameters = IList . rev par' } )
then Some ( J ava_method { js with parameters = IList . rev par' } )
else None
else None
| [] -> None )
| [] -> None )
| _ -> None
| _ -> None
(* * Check if the procedure name is an anonymous inner class constructor. *)
(* * Check if the procedure name is an anonymous inner class constructor. *)
let java_is_anonymous_inner_class_constructor = function
let java_is_anonymous_inner_class_constructor = function
| J AVA js ->
| J ava_method js ->
let _ , name = js . class name in
let _ , name = js . class _ name in
is_anonymous_inner_class_name name
is_anonymous_inner_class_name name
| _ -> false
| _ -> false
(* * Check if the procedure name is an acess method ( e.g. access$100 used to
(* * Check if the procedure name is an acess method ( e.g. access$100 used to
access private members from a nested class . * )
access private members from a nested class . * )
let java_is_access_method = function
let java_is_access_method = function
| J AVA js ->
| J ava_method js ->
( match string_split_character js . method name '$' with
( match string_split_character js . method _ name '$' with
| Some " access " , s ->
| Some " access " , s ->
let is_int =
let is_int =
try ignore ( int_of_string s ) ; true with Failure _ -> false in
try ignore ( int_of_string s ) ; true with Failure _ -> false in
@ -345,7 +346,7 @@ let java_is_access_method = function
(* * Check if the proc name has the type of a java vararg.
(* * Check if the proc name has the type of a java vararg.
Note : currently only checks that the last argument has type Object [] . * )
Note : currently only checks that the last argument has type Object [] . * )
let java_is_vararg = function
let java_is_vararg = function
| J AVA js ->
| J ava_method js ->
begin
begin
match ( IList . rev js . parameters ) with
match ( IList . rev js . parameters ) with
| ( _ , " java.lang.Object[] " ) :: _ -> true
| ( _ , " java.lang.Object[] " ) :: _ -> true
@ -355,30 +356,30 @@ let java_is_vararg = function
(* * [is_constructor pname] returns true if [pname] is a constructor *)
(* * [is_constructor pname] returns true if [pname] is a constructor *)
let is_constructor = function
let is_constructor = function
| J AVA js -> js . method name = " <init> "
| J ava_method js -> js . method _ name = " <init> "
| C_METHOD name ->
| ObjC_Cpp_method name ->
( name . method_name = " new " ) | | Utils . string_is_prefix " init " name . method_name
( name . method_name = " new " ) | | Utils . string_is_prefix " init " name . method_name
| _ -> false
| _ -> false
let java_is_close = function
let java_is_close = function
| J AVA js -> js . method name = " close "
| J ava_method js -> js . method _ name = " close "
| _ -> false
| _ -> false
(* * [is_class_initializer pname] returns true if [pname] is a class initializer *)
(* * [is_class_initializer pname] returns true if [pname] is a class initializer *)
let is_class_initializer = function
let is_class_initializer = function
| J AVA js -> js . method name = " <clinit> "
| J ava_method js -> js . method _ name = " <clinit> "
| _ -> false
| _ -> false
(* * [is_infer_undefined pn] returns true if [pn] is a special Infer undefined proc *)
(* * [is_infer_undefined pn] returns true if [pn] is a special Infer undefined proc *)
let is_infer_undefined pn = match pn with
let is_infer_undefined pn = match pn with
| J AVA j ->
| J ava_method j ->
let regexp = Str . regexp " com.facebook.infer.models.InferUndefined " in
let regexp = Str . regexp " com.facebook.infer.models.InferUndefined " in
Str . string_match regexp ( java_get_class pn ) 0
Str . string_match regexp ( java_get_class pn ) 0
| _ ->
| _ ->
(* TODO: add cases for obj-c, c, c++ *)
(* TODO: add cases for obj-c, c, c++ *)
false
false
(* * to_string for C_ FUNCTION and STATIC types *)
(* * to_string for C_ function type *)
let to_readable_string ( c1 , c2 ) verbose =
let to_readable_string ( c1 , c2 ) verbose =
let plain = c1 in
let plain = c1 in
if verbose then
if verbose then
@ -390,9 +391,9 @@ let to_readable_string (c1, c2) verbose =
let c_method_to_string osig detail_level =
let c_method_to_string osig detail_level =
match detail_level with
match detail_level with
| S IMPLE -> osig . method_name
| S imple -> osig . method_name
| N ON_VERBOSE -> osig . class_name ^ " _ " ^ osig . method_name
| N on_verbose -> osig . class_name ^ " _ " ^ osig . method_name
| V ERBOSE ->
| V erbose ->
let m_str = match osig . mangled with
let m_str = match osig . mangled with
| None -> " "
| None -> " "
| Some s -> " { " ^ s ^ " } " in
| Some s -> " { " ^ s ^ " } " in
@ -401,29 +402,28 @@ let c_method_to_string osig detail_level =
(* * Very verbose representation of an existing Procname.t *)
(* * Very verbose representation of an existing Procname.t *)
let to_unique_id pn =
let to_unique_id pn =
match pn with
match pn with
| JAVA j -> java_to_string j VERBOSE
| Java_method j -> java_to_string j Verbose
| C_FUNCTION ( c1 , c2 ) -> to_readable_string ( c1 , c2 ) true
| C_function ( c1 , c2 ) -> to_readable_string ( c1 , c2 ) true
| STATIC ( s1 , s2 ) -> to_readable_string ( s1 , s2 ) true
| ObjC_Cpp_method osig -> c_method_to_string osig Verbose
| C_METHOD osig -> c_method_to_string osig VERBOSE
| ObjC_block name -> name
| OBJC_BLOCK name -> name
(* * Convert a proc name to a string for the user to see *)
(* * Convert a proc name to a string for the user to see *)
let to_string p =
let to_string p =
match p with
match p with
| J AVA j -> ( java_to_string j NON_VERBOSE )
| J ava_method j -> ( java_to_string j Non_verbose )
| C_ FUNCTION ( c1 , c2 ) | STATIC ( c1 , c2 ) ->
| C_ function ( c1 , c2 ) ->
to_readable_string ( c1 , c2 ) false
to_readable_string ( c1 , c2 ) false
| C_METHOD osig -> c_method_to_string osig NON_VERBOSE
| ObjC_Cpp_method osig -> c_method_to_string osig Non_verbose
| O BJC_BLOCK name -> name
| O bjC_block name -> name
(* * Convenient representation of a procname for external tools ( e.g. eclipse plugin ) *)
(* * Convenient representation of a procname for external tools ( e.g. eclipse plugin ) *)
let to_simplified_string ? ( withclass = false ) p =
let to_simplified_string ? ( withclass = false ) p =
match p with
match p with
| J AVA j -> ( java_to_string ~ withclass j S IMPLE )
| J ava_method j -> ( java_to_string ~ withclass j S imple )
| C_ FUNCTION ( c1 , c2 ) | STATIC ( c1 , c2 ) ->
| C_ function ( c1 , c2 ) ->
to_readable_string ( c1 , c2 ) false ^ " () "
to_readable_string ( c1 , c2 ) false ^ " () "
| C_METHOD osig -> c_method_to_string osig SIMPLE
| ObjC_Cpp_method osig -> c_method_to_string osig Simple
| O BJC_BLOCK name -> " block "
| O bjC_block name -> " block "
(* * Convert a proc name to a filename *)
(* * Convert a proc name to a filename *)
let to_filename ( pn : proc_name ) =
let to_filename ( pn : proc_name ) =
@ -441,26 +441,20 @@ let pp f pn =
(* * Compare function for Procname.t types *)
(* * Compare function for Procname.t types *)
(* These rules create an ordered set of procnames grouped with the following priority ( lowest to highest ) : *)
(* These rules create an ordered set of procnames grouped with the following priority ( lowest to highest ) : *)
(* JAVA, C_FUNCTION, STATIC, OBJC *)
let compare pn1 pn2 = match pn1 , pn2 with
let compare pn1 pn2 = match pn1 , pn2 with
| JAVA j1 , JAVA j2 -> java_sig_compare j1 j2
| Java_method j1 , Java_method j2 -> java_sig_compare j1 j2
| JAVA _ , _ -> - 1
| Java_method _ , _ -> - 1
| _ , JAVA _ -> 1
| _ , Java_method _ -> 1
| C_FUNCTION ( c1 , c2 ) , C_FUNCTION ( c3 , c4 ) -> (* Compare C_FUNCTION types *)
| C_function ( c1 , c2 ) , C_function ( c3 , c4 ) -> (* Compare C_function types *)
let n = string_compare c1 c3 in
string_compare c1 c3
if n < > 0 then n else mangled_compare c2 c4
| > next mangled_compare c2 c4
| C_FUNCTION _ , _ -> - 1
| C_function _ , _ -> - 1
| _ , C_FUNCTION _ -> 1
| _ , C_function _ -> 1
| STATIC ( c1 , c2 ) , STATIC ( c3 , c4 ) -> (* Compare STATIC types *)
| ObjC_block s1 , ObjC_block s2 -> (* Compare ObjC_block types *)
let n = string_compare c1 c3 in
if n < > 0 then n else mangled_compare c2 c4
| STATIC _ , _ -> - 1
| _ , STATIC _ -> 1
| OBJC_BLOCK s1 , OBJC_BLOCK s2 -> (* Compare OBJC_BLOCK types *)
string_compare s1 s2
string_compare s1 s2
| O BJC_BLOCK _ , _ -> - 1
| ObjC_block _ , _ -> - 1
| _ , O BJC_BLOCK _ -> 1
| _ , ObjC_block _ -> 1
| C_METHOD osig1 , C_METHOD osig2 -> c_meth_sig_compare osig1 osig2
| ObjC_Cpp_method osig1 , ObjC_Cpp_method osig2 -> c_meth_sig_compare osig1 osig2
let equal pn1 pn2 =
let equal pn1 pn2 =
compare pn1 pn2 = 0
compare pn1 pn2 = 0