Java split name as an abstract type

Reviewed By: sblackshear

Differential Revision: D7291611

fbshipit-source-id: 0c15ecd
master
Mehdi Bouaziz 7 years ago committed by Facebook Github Bot
parent e85c3690fa
commit 2f57b094e9

@ -388,6 +388,33 @@ module Name = struct
end end
module Java = struct module Java = struct
module Split = struct
(** e.g. {type_name="int"; package=None} for primitive types
* or {type_name="PrintWriter"; package=Some "java.io"} for objects.
*)
type t = {package: string option; type_name: string}
let make ?package type_name = {type_name; package}
(** Given a package.class_name string, it looks for the latest dot and split the string
in two (package, class_name) *)
let of_string package_classname =
match String.rsplit2 package_classname ~on:'.' with
| Some (package, type_name) ->
{type_name; package= Some package}
| None ->
{type_name= package_classname; package= None}
let package {package} = package
let type_name {type_name} = type_name
let java_lang_object = make ~package:"java.lang" "Object"
let java_lang_string = make ~package:"java.lang" "String"
end
let from_string name_str = JavaClass (Mangled.from_string name_str) let from_string name_str = JavaClass (Mangled.from_string name_str)
let from_package_class package_name class_name = let from_package_class package_name class_name =
@ -403,29 +430,19 @@ module Name = struct
let java_lang_cloneable = from_string "java.lang.Cloneable" let java_lang_cloneable = from_string "java.lang.Cloneable"
(** Given a package.class_name string, it looks for the latest dot and split the string let split_typename typename = Split.of_string (name typename)
in two (package, class_name) *)
let split_classname package_classname =
match String.rsplit2 package_classname ~on:'.' with
| Some (x, y) ->
(Some x, y)
| None ->
(None, package_classname)
let split_typename typename = split_classname (name typename)
let get_outer_class class_name = let get_outer_class class_name =
let package_name, class_name_no_package = split_typename class_name in let {Split.package; type_name} = split_typename class_name in
match String.rsplit2 ~on:'$' class_name_no_package with match String.rsplit2 ~on:'$' type_name with
| Some (parent_class, _) -> | Some (parent_class, _) ->
Some (from_package_class (Option.value ~default:"" package_name) parent_class) Some (from_package_class (Option.value ~default:"" package) parent_class)
| None -> | None ->
None None
let is_anonymous_inner_class_name class_name = let is_anonymous_inner_class_name class_name =
let class_name_no_package = snd (split_typename class_name) in let class_name_no_package = Split.type_name (split_typename class_name) in
match String.rsplit2 class_name_no_package ~on:'$' with match String.rsplit2 class_name_no_package ~on:'$' with
| Some (_, s) -> | Some (_, s) ->
let is_int = let is_int =
@ -440,7 +457,7 @@ module Name = struct
let is_external_classname name_string = let is_external_classname name_string =
let package, _ = split_classname name_string in let {Split.package} = Split.of_string name_string in
Option.exists ~f:Config.java_package_is_external package Option.exists ~f:Config.java_package_is_external package
@ -541,10 +558,9 @@ module Procname = struct
[@@deriving compare] [@@deriving compare]
(* TODO: use Mangled.t here *) (* TODO: use Mangled.t here *)
type java_type = string option * string type java_type = Name.Java.Split.t =
{package: string option; type_name: string}
(* compare in inverse order *) [@@deriving compare]
let compare_java_type (p1, c1) (p2, c2) = [%compare : string * string option] (c1, p1) (c2, p2)
(** Type of java procedure names. *) (** Type of java procedure names. *)
type t = type t =
@ -562,10 +578,10 @@ module Procname = struct
(** A type is a pair (package, type_name) that is translated in a string package.type_name *) (** A type is a pair (package, type_name) that is translated in a string package.type_name *)
let type_to_string_verbosity p verbosity = let type_to_string_verbosity p verbosity =
match p with match p with
| None, typ -> | {package= Some package; type_name} when is_verbose verbosity ->
typ package ^ "." ^ type_name
| Some p, cls -> | {type_name} ->
if is_verbose verbosity then p ^ "." ^ cls else cls type_name
(** Given a list of types, it creates a unique string of types separated by commas *) (** Given a list of types, it creates a unique string of types separated by commas *)
@ -589,9 +605,9 @@ module Procname = struct
let get_class_type_name j = j.class_name let get_class_type_name j = j.class_name
let get_simple_class_name j = snd (Name.Java.split_classname (get_class_name j)) let get_simple_class_name j = Name.Java.Split.(j |> get_class_name |> of_string |> type_name)
let get_package j = fst (Name.Java.split_classname (get_class_name j)) let get_package j = Name.Java.Split.(j |> get_class_name |> of_string |> package)
let get_method j = j.method_name let get_method j = j.method_name
@ -707,7 +723,7 @@ module Procname = struct
(** 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 is_vararg {parameters} = let is_vararg {parameters} =
match List.last parameters with Some (_, "java.lang.Object[]") -> true | _ -> false match List.last parameters with Some {type_name= "java.lang.Object[]"} -> true | _ -> false
let is_external java_pname = let is_external java_pname =

@ -153,6 +153,20 @@ module Name : sig
end end
module Java : sig module Java : sig
module Split : sig
type t
val make : ?package:string -> string -> t
val of_string : string -> t
(** Given a package.class_name string, look for the latest dot and split the string
in two (package, class_name). *)
val java_lang_object : t
val java_lang_string : t
end
val from_string : string -> t val from_string : string -> t
(** Create a typename from a Java classname in the form "package.class" *) (** Create a typename from a Java classname in the form "package.class" *)
@ -168,10 +182,6 @@ module Name : sig
val is_external : t -> bool val is_external : t -> bool
(** return true if the typename is in the .inferconfig list of external classes *) (** return true if the typename is in the .inferconfig list of external classes *)
val split_classname : string -> string option * string
(** Given a package.class_name string, look for the latest dot and split the string
in two (package, class_name). *)
val get_outer_class : t -> t option val get_outer_class : t -> t option
(** Given an inner classname like C$Inner1$Inner2, return Some C$Inner1. If the class is not an (** Given an inner classname like C$Inner1$Inner2, return Some C$Inner1. If the class is not an
inner class, return None *) inner class, return None *)
@ -279,8 +289,7 @@ module Procname : sig
type t [@@deriving compare] type t [@@deriving compare]
(** e.g. ("", "int") for primitive types or ("java.io", "PrintWriter") for objects *) type java_type = Name.Java.Split.t
type java_type = string option * string
val make : Name.t -> java_type option -> string -> java_type list -> kind -> t val make : Name.t -> java_type option -> string -> java_type list -> kind -> t
(** Create a Java procedure name from its (** Create a Java procedure name from its

@ -612,7 +612,7 @@ let resolve_java_pname tenv prop args pname_java call_flags : Typ.Procname.Java.
~f:(fun accu (arg_exp, _) name -> ~f:(fun accu (arg_exp, _) name ->
match resolve_typename prop arg_exp with match resolve_typename prop arg_exp with
| Some class_name -> | Some class_name ->
Typ.Name.Java.split_classname (Typ.Name.name class_name) :: accu Typ.Name.Java.Split.of_string (Typ.Name.name class_name) :: accu
| None -> | None ->
name :: accu ) name :: accu )
~init:[] args ~init:[] args
@ -695,7 +695,7 @@ let call_constructor_url_update_args pname actual_params =
Typ.Procname.Java Typ.Procname.Java
(Typ.Procname.Java.make (Typ.Procname.Java.make
(Typ.Name.Java.from_string "java.net.URL") (Typ.Name.Java.from_string "java.net.URL")
None "<init>" [(Some "java.lang", "String")] Typ.Procname.Java.Non_Static) None "<init>" [Typ.Name.Java.Split.java_lang_string] Typ.Procname.Java.Non_Static)
in in
if Typ.Procname.equal url_pname pname then if Typ.Procname.equal url_pname pname then
match actual_params with match actual_params with

@ -705,7 +705,7 @@ let typecheck_instr tenv ext calls_this checks (node: Procdesc.Node.t) idenv get
let do_map_put typestate' = let do_map_put typestate' =
(* Get the proc name for map.get() from map.put() *) (* Get the proc name for map.get() from map.put() *)
let pname_get_from_pname_put pname_put = let pname_get_from_pname_put pname_put =
let object_t = (Some "java.lang", "Object") in let object_t = Typ.Name.Java.Split.java_lang_object in
let parameters = [object_t] in let parameters = [object_t] in
pname_put |> Typ.Procname.Java.replace_method_name "get" pname_put |> Typ.Procname.Java.replace_method_name "get"
|> Typ.Procname.Java.replace_return_type object_t |> Typ.Procname.Java.replace_return_type object_t
@ -904,7 +904,7 @@ let typecheck_instr tenv ext calls_this checks (node: Procdesc.Node.t) idenv get
DExp.Dretcall DExp.Dretcall
(DExp.Dconst Const.Cfun Typ.Procname.Java pname_java, args, loc, call_flags) -> (DExp.Dconst Const.Cfun Typ.Procname.Java pname_java, args, loc, call_flags) ->
let pname_java' = let pname_java' =
let object_t = (Some "java.lang", "Object") in let object_t = Typ.Name.Java.Split.java_lang_object in
pname_java |> Typ.Procname.Java.replace_method_name "get" pname_java |> Typ.Procname.Java.replace_method_name "get"
|> Typ.Procname.Java.replace_return_type object_t |> Typ.Procname.Java.replace_return_type object_t
in in

@ -182,16 +182,20 @@ let rec string_of_type vt =
let package_to_string = function [] -> None | p -> Some (String.concat ~sep:"." p) let package_to_string = function [] -> None | p -> Some (String.concat ~sep:"." p)
let cn_to_java_type cn = (package_to_string (JBasics.cn_package cn), JBasics.cn_simple_name cn) let cn_to_java_type cn =
Typ.Name.Java.Split.make
?package:(package_to_string (JBasics.cn_package cn))
(JBasics.cn_simple_name cn)
let vt_to_java_type vt = let vt_to_java_type vt =
match vt with match vt with
| JBasics.TBasic bt -> | JBasics.TBasic bt ->
(None, string_of_basic_type bt) Typ.Name.Java.Split.make (string_of_basic_type bt)
| JBasics.TObject ot -> | JBasics.TObject ot ->
match ot with match ot with
| JBasics.TArray vt -> | JBasics.TArray vt ->
(None, string_of_type vt ^ "[]") Typ.Name.Java.Split.make (string_of_type vt ^ "[]")
| JBasics.TClass cn -> | JBasics.TClass cn ->
cn_to_java_type cn cn_to_java_type cn
@ -201,7 +205,7 @@ let method_signature_names ms =
match JBasics.ms_rtype ms with match JBasics.ms_rtype ms with
| None -> | None ->
if String.equal (JBasics.ms_name ms) JConfig.constructor_name then None if String.equal (JBasics.ms_name ms) JConfig.constructor_name then None
else Some (None, JConfig.void) else Some (Typ.Name.Java.Split.make JConfig.void)
| Some vt -> | Some vt ->
Some (vt_to_java_type vt) Some (vt_to_java_type vt)
in in

Loading…
Cancel
Save