[java][procname] params are Typ.t

Summary:
Use `Typ.t` for parameter types in procnames, instead of `JavaSplitName.t`.  This allows more precise and usable types stored in procnames, as well as not using the string-based representation of `JavaSplitName` which meant parsing strings whenever one needed a `Typ.t`.

This also makes `JavaSplitName` dead code, so it is removed.

Reviewed By: skcho

Differential Revision: D20500423

fbshipit-source-id: a72728e3f
master
Nikos Gorogiannis 5 years ago committed by Facebook GitHub Bot
parent d718c04816
commit cf29bc7aa2

@ -1,41 +0,0 @@
(*
* 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.
*)
open! IStd
module F = Format
type t = {package: string option; type_name: string} [@@deriving compare, equal]
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_object_array = make ~package:"java.lang" "Object[]"
let java_lang_string = make ~package:"java.lang" "String"
let java_lang_string_array = make ~package:"java.lang" "String[]"
let pp_type_verbosity ~verbose fmt = function
| {package= Some package; type_name} when verbose ->
F.fprintf fmt "%s.%s" package type_name
| {type_name} ->
F.pp_print_string fmt type_name

@ -1,38 +0,0 @@
(*
* 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.
*)
open! IStd
module F = Format
(** Module for representing a Java type. *)
type t [@@deriving compare, equal]
val make : ?package:string -> string -> t
val of_string : string -> t
(** Given a package.type_name string, it looks for the latest dot and splits the string in two
(package, rest-of-type-name). If there is no dot symbol, assumes the whole string is a type
name. NB the RHS is not just a classname, eg it can be an array type. *)
val java_lang_object : t
(** [java.lang.Object] type *)
val java_lang_object_array : t
(** [java.lang.Object\[\]] type *)
val java_lang_string : t
(** [java.lang.String] type *)
val java_lang_string_array : t
(** [java.lang.String\[\]] type *)
val package : t -> string option
val type_name : t -> string
val pp_type_verbosity : verbose:bool -> F.formatter -> t -> unit

@ -22,13 +22,10 @@ module Java = struct
| Static (** in Java, procedures called with invokestatic *)
[@@deriving compare]
(* TODO: use Mangled.t here *)
type java_type = JavaSplitName.t [@@deriving compare, equal]
(** Type of java procedure names. *)
type t =
{ method_name: string
; parameters: java_type list
; parameters: Typ.t list
; class_name: Typ.Name.t
; return_type: Typ.t option (* option because constructors have no return type *)
; kind: kind }
@ -84,9 +81,7 @@ module Java = struct
F.pp_print_char fmt '.'
in
let pp_package_method_and_params fmt j =
let pp_param_list fmt params =
Pp.seq ~sep:"," (JavaSplitName.pp_type_verbosity ~verbose) fmt params
in
let pp_param_list fmt params = Pp.seq ~sep:"," (Typ.pp_java ~verbose) fmt params in
F.fprintf fmt "%a%s(%a)" pp_class_name_dot j j.method_name pp_param_list j.parameters
in
match verbosity with
@ -164,7 +159,11 @@ module Java = struct
(** Check if the proc name has the type of a java vararg. Note: currently only checks that the
last argument has type Object[]. *)
let is_vararg {parameters} =
List.last parameters |> Option.exists ~f:JavaSplitName.(equal java_lang_object_array)
match List.last parameters with
| Some {desc= Tptr ({desc= Tarray {elt}}, Pk_pointer)} ->
Typ.(equal pointer_to_java_lang_object elt)
| _ ->
false
let is_external java_pname =
@ -179,8 +178,7 @@ module Parameter = struct
type clang_parameter = Typ.Name.t option [@@deriving compare, equal]
(** Type for parameters in procnames, for java and clang. *)
type t = JavaParameter of Java.java_type | ClangParameter of clang_parameter
[@@deriving compare, equal]
type t = JavaParameter of Typ.t | ClangParameter of clang_parameter [@@deriving compare, equal]
let of_typ typ =
match typ.Typ.desc with Typ.Tptr ({desc= Tstruct name}, Pk_pointer) -> Some name | _ -> None
@ -695,7 +693,7 @@ let rec replace_parameters new_parameters procname =
let parameter_of_name procname class_name =
match procname with
| Java _ ->
Parameter.JavaParameter (JavaSplitName.of_string (Typ.Name.name class_name))
Parameter.JavaParameter Typ.(mk_ptr (mk_struct class_name))
| _ ->
Parameter.ClangParameter (Parameter.clang_param_of_name class_name)

@ -19,8 +19,6 @@ module Java : sig
type t [@@deriving compare]
type java_type = JavaSplitName.t [@@deriving compare, equal]
val constructor_method_name : string
val class_initializer_method_name : string
@ -28,7 +26,7 @@ module Java : sig
val replace_method_name : string -> t -> t
(** Replace the method name of an existing java procname. *)
val replace_parameters : java_type list -> t -> t
val replace_parameters : Typ.t list -> t -> t
(** Replace the parameters of a java procname. *)
val replace_return_type : Typ.t -> t -> t
@ -49,7 +47,7 @@ module Java : sig
val get_method : t -> string
(** Return the method name of a java procedure name. *)
val get_parameters : t -> java_type list
val get_parameters : t -> Typ.t list
(** Return the parameters of a java procedure name. *)
val get_return_typ : t -> Typ.t
@ -105,8 +103,7 @@ module Parameter : sig
type clang_parameter = Typ.Name.t option [@@deriving compare, equal]
(** Type for parameters in procnames, for java and clang. *)
type t = JavaParameter of Java.java_type | ClangParameter of clang_parameter
[@@deriving compare, equal]
type t = JavaParameter of Typ.t | ClangParameter of clang_parameter [@@deriving compare, equal]
val of_typ : Typ.t -> clang_parameter
end
@ -256,7 +253,7 @@ val make_java :
class_name:Typ.Name.t
-> return_type:Typ.t option
-> method_name:string
-> parameters:Java.java_type list
-> parameters:Typ.t list
-> kind:Java.kind
-> unit
-> t

@ -656,3 +656,8 @@ let rec is_java_type t =
is_java_type elt
| _ ->
false
let pointer_to_java_lang_object = mk_ptr (mk_struct Name.Java.java_lang_object)
let pointer_to_java_lang_string = mk_ptr (mk_struct Name.Java.java_lang_string)

@ -167,6 +167,10 @@ val double : t
val void_star : t
(** void* type *)
val pointer_to_java_lang_object : t
val pointer_to_java_lang_string : t
val get_ikind_opt : t -> ikind option
(** Get ikind if the type is integer. *)

@ -271,7 +271,7 @@ module Java = struct
let is_override_of_lang_object_equals curr_pname =
let is_only_param_of_object_type = function
| [Procname.Parameter.JavaParameter param_type]
when JavaSplitName.equal param_type JavaSplitName.java_lang_object ->
when Typ.equal param_type Typ.pointer_to_java_lang_object ->
true
| _ ->
false

@ -621,31 +621,32 @@ let resolve_and_analyze
(** recognize calls to the constructor java.net.URL and splits the argument string to be only the
protocol. *)
let call_constructor_url_update_args pname actual_params =
let call_constructor_url_update_args =
let url_pname =
Procname.make_java
~class_name:(Typ.Name.Java.from_string "java.net.URL")
~return_type:None ~method_name:Procname.Java.constructor_method_name
~parameters:[JavaSplitName.java_lang_string] ~kind:Procname.Java.Non_Static ()
~parameters:[Typ.pointer_to_java_lang_string] ~kind:Procname.Java.Non_Static ()
in
if Procname.equal url_pname pname then
match actual_params with
| [this; (Exp.Const (Const.Cstr s), atype)] -> (
let parts = Str.split (Str.regexp_string "://") s in
match parts with
| frst :: _ ->
if
String.equal frst "http" || String.equal frst "ftp" || String.equal frst "https"
|| String.equal frst "mailto" || String.equal frst "jar"
then [this; (Exp.Const (Const.Cstr frst), atype)]
else actual_params
| _ ->
actual_params )
| [this; (_, atype)] ->
[this; (Exp.Const (Const.Cstr "file"), atype)]
| _ ->
actual_params
else actual_params
fun pname actual_params ->
if Procname.equal url_pname pname then
match actual_params with
| [this; (Exp.Const (Const.Cstr s), atype)] -> (
let parts = Str.split (Str.regexp_string "://") s in
match parts with
| frst :: _ ->
if
String.equal frst "http" || String.equal frst "ftp" || String.equal frst "https"
|| String.equal frst "mailto" || String.equal frst "jar"
then [this; (Exp.Const (Const.Cstr frst), atype)]
else actual_params
| _ ->
actual_params )
| [this; (_, atype)] ->
[this; (Exp.Const (Const.Cstr "file"), atype)]
| _ ->
actual_params
else actual_params
let receiver_self receiver prop =

@ -402,8 +402,9 @@ let is_assume_true =
let is_java_main_method (pname : Procname.t) =
let pointer_to_array_of_java_lang_string = Typ.(mk_ptr (mk_array pointer_to_java_lang_string)) in
let check_main_args args =
match args with [arg] -> JavaSplitName.(equal java_lang_string_array arg) | _ -> false
match args with [arg] -> Typ.equal pointer_to_array_of_java_lang_string arg | _ -> false
in
match pname with
| C _ | Linters_dummy_method | Block _ | ObjC_Cpp _ | WithBlockParameters _ ->

@ -110,57 +110,8 @@ let object_type_to_string ot =
array_type_to_string vt
let string_of_basic_type = function
| `Bool ->
JConfig.boolean_st
| `Byte ->
JConfig.byte_st
| `Char ->
JConfig.char_st
| `Double ->
JConfig.double_st
| `Float ->
JConfig.float_st
| `Int ->
JConfig.int_st
| `Long ->
JConfig.long_st
| `Short ->
JConfig.short_st
let rec string_of_type vt =
match vt with
| JBasics.TBasic bt ->
string_of_basic_type bt
| JBasics.TObject ot -> (
match ot with
| JBasics.TArray vt ->
string_of_type vt ^ "[]"
| JBasics.TClass cn ->
JBasics.cn_name cn )
let package_to_string = function [] -> None | p -> Some (String.concat ~sep:"." p)
let cn_to_java_type cn =
JavaSplitName.make
?package:(package_to_string (JBasics.cn_package cn))
(JBasics.cn_simple_name cn)
let vt_to_java_type vt =
match vt with
| JBasics.TBasic bt ->
JavaSplitName.of_string (string_of_basic_type bt)
| JBasics.TObject ot -> (
match ot with
| JBasics.TArray vt ->
JavaSplitName.of_string (string_of_type vt ^ "[]")
| JBasics.TClass cn ->
cn_to_java_type cn )
let method_signature_names ms =
let method_name = JBasics.ms_name ms in
let return_type_name =
@ -172,7 +123,7 @@ let method_signature_names ms =
| Some vt ->
Some (get_named_type vt)
in
let args_types = List.map ~f:vt_to_java_type (JBasics.ms_args ms) in
let args_types = List.map ~f:get_named_type (JBasics.ms_args ms) in
(return_type_name, method_name, args_types)

@ -21,9 +21,7 @@ let unique_repr_of_signature ThirdPartyMethod.{class_name; method_name; params}
{class_name; method_name; param_types= List.map params ~f:(fun (param_type, _) -> param_type)}
let java_type_to_string java_type =
Pp.string_of_pp (JavaSplitName.pp_type_verbosity ~verbose:true) java_type
let java_type_to_string java_type = Pp.string_of_pp (Typ.pp_java ~verbose:true) java_type
let unique_repr_of_java_proc_name java_proc_name =
let class_name = Procname.Java.get_class_name java_proc_name in

@ -55,7 +55,7 @@ let get_special_method_modelled_nullability tenv proc_name =
Some (false, [])
(* valueOf() is a synthetic enum method that is never null *)
| "valueOf", [Procname.Parameter.JavaParameter param_type_name]
when JavaSplitName.equal param_type_name JavaSplitName.java_lang_string ->
when Typ.equal param_type_name Typ.pointer_to_java_lang_string ->
Some (false, [false])
| _ ->
None

@ -635,8 +635,7 @@ let do_map_put ({IntraproceduralAnalysis.proc_desc= curr_pdesc; tenv; _} as anal
find_canonical_duplicate typestate' =
(* Get the proc name for map.get() from map.put() *)
let pname_get_from_pname_put pname_put =
let object_t = JavaSplitName.java_lang_object in
let parameters = [object_t] in
let parameters = [object_typ] in
pname_put
|> Procname.Java.replace_method_name "get"
|> Procname.Java.replace_return_type object_typ

@ -67,37 +67,6 @@ module JNI = struct
Format.fprintf fmt "(%a)%a" (Pp.seq ~sep:"" pp) args pp ret_typ
let rec to_java_type jni =
let make = JavaSplitName.make in
match jni with
| Boolean ->
make "bool"
| Byte ->
make "byte"
| Char ->
make "char"
| Short ->
make "short"
| Int ->
make "int"
| Long ->
make "long"
| Float ->
make "float"
| Double ->
make "double"
| Void ->
make "void"
| FullyQualifiedClass (pkg, cl) ->
make ~package:pkg cl
| Array typ ->
let java_type = to_java_type typ in
let typ_str = JavaSplitName.type_name java_type in
make ?package:(JavaSplitName.package java_type) (Printf.sprintf "%s[]" typ_str)
| Method _ ->
L.(die UserError "Cannot express a method as a Procname.Java.java_type")
let rec to_typ jni =
match jni with
| Boolean ->
@ -279,8 +248,6 @@ module JNI = struct
let parse_method_str = parse_method_str
let to_java_type = to_java_type
let pp = pp
end
end
@ -289,7 +256,7 @@ let create_procname ~classname ~methodname:method_name ~signature ~use_signature
let signature = if use_signature then signature else JNI.void_method_with_no_arguments in
let class_name = Typ.Name.Java.from_string classname in
let args, return_type = JNI.parse_method_str signature in
let parameters = List.map ~f:JNI.to_java_type args in
let parameters = List.map ~f:JNI.to_typ args in
let return_type =
if
String.equal method_name Procname.Java.constructor_method_name

@ -33,8 +33,6 @@ module JNI : sig
val parse_method_str : string -> t list * t
val to_java_type : t -> Procname.Java.java_type
val pp : Format.formatter -> t -> unit
end
end

@ -19,7 +19,7 @@ let topl_class_typ = Typ.mk (Tstruct topl_class_name)
let topl_call ret_id (ret_typ : Typ.desc) loc method_name arg_ts : Sil.instr =
let e_fun =
let return_type = Some Typ.void in
let parameters = List.map arg_ts ~f:(fun _ -> JavaSplitName.java_lang_object) in
let parameters = List.map arg_ts ~f:(fun _ -> Typ.pointer_to_java_lang_object) in
Exp.Const
(Const.Cfun
(Procname.make_java ~class_name:topl_class_name ~return_type ~method_name ~parameters

@ -9,8 +9,6 @@ open! IStd
open OUnit2
module T = JProcname.JNI.VISIBLE_FOR_TESTING_DO_NOT_USE_DIRECTLY
let mk_split (pkg, typ) = JavaSplitName.make ?package:pkg typ
let test_jni_pp =
let create_test input expected _ =
let found = Format.asprintf "%a" T.pp input in
@ -126,37 +124,6 @@ let test_jni_parse_str_with_invalid_input =
name >:: create_test test_input expected_exception )
let test_jni_to_java_type_with_valid_input =
let create_test input expected _ =
let found = T.to_java_type input in
let pp_diff fmt (expected, actual) =
let exp_pkg = Option.value ~default:"<None>" (JavaSplitName.package expected) in
let exp_cl = JavaSplitName.type_name expected in
let actual_pkg = Option.value ~default:"<None>" (JavaSplitName.package actual) in
let actual_cl = JavaSplitName.type_name actual in
Format.fprintf fmt "Expected: '(%s, %s)', found: '(%s, %s)'" exp_pkg exp_cl actual_pkg
actual_cl
in
let cmp a b = Int.equal 0 (Procname.Java.compare_java_type a b) in
assert_equal ~cmp ~pp_diff expected found
in
[ ("test_jni_to_java_type_1", T.Boolean, mk_split (None, "bool"))
; ( "test_jni_to_java_type_2"
, T.FullyQualifiedClass ("java.lang", "String")
, mk_split (Some "java.lang", "String") ) ]
|> List.map ~f:(fun (name, test_input, expected_output) ->
name >:: create_test test_input expected_output )
let test_jni_to_java_type_with_invalid_input =
let run () = T.to_java_type (Method ([], Void)) in
let expected_exception =
Logging.InferUserError "Cannot express a method as a Procname.Java.java_type"
in
let do_assert _ = assert_raises expected_exception run in
"test_jni_to_java_type_with_method_should_fail" >:: do_assert
let test_from_json_string_with_valid_input =
let create_test input expected ~use_signature _ =
let found = JavaProfilerSamples.from_json_string input ~use_signature in
@ -183,19 +150,13 @@ let test_from_json_string_with_valid_input =
make_java
~class_name:(Typ.Name.Java.from_string "lll.mmm.Nnn")
~return_type:None ~method_name:Java.constructor_method_name
~parameters:
[ mk_split (Some "java.lang", "String")
; mk_split (None, "int[]")
; mk_split (None, "long") ]
~parameters:[Typ.pointer_to_java_lang_string; Typ.(mk_ptr (mk_array int)); Typ.long]
~kind:Java.Non_Static ())
; Procname.(
make_java
~class_name:(Typ.Name.Java.from_string "ggg.hhh.Iii")
~return_type:None ~method_name:Java.class_initializer_method_name
~parameters:
[ mk_split (Some "java.lang", "String")
; mk_split (None, "int[]")
; mk_split (None, "long") ]
~parameters:[Typ.pointer_to_java_lang_string; Typ.(mk_ptr (mk_array int)); Typ.long]
~kind:Java.Non_Static ()) ] )
; ( "label2"
, Procname.Set.of_list
@ -204,10 +165,7 @@ let test_from_json_string_with_valid_input =
~class_name:(Typ.Name.Java.from_string "ddd.eee.Fff")
~return_type:(Some Typ.(mk_ptr (mk_array (mk_ptr (mk_array java_char)))))
~method_name:"methodTwo"
~parameters:
[ mk_split (Some "java.lang", "String")
; mk_split (None, "int[]")
; mk_split (None, "long") ]
~parameters:[Typ.pointer_to_java_lang_string; Typ.(mk_ptr (mk_array int)); Typ.long]
~kind:Java.Non_Static ())
; Procname.(
make_java
@ -273,7 +231,6 @@ let test_from_json_string_with_invalid_input =
let tests =
"java_profiler_samples"
>::: (test_jni_to_java_type_with_invalid_input :: test_jni_parse_str_with_valid_input)
@ test_jni_parse_str_with_invalid_input @ test_jni_parse_method_str_with_invalid_input
@ test_jni_pp @ test_jni_to_java_type_with_valid_input
>::: test_jni_parse_str_with_valid_input @ test_jni_parse_str_with_invalid_input
@ test_jni_parse_method_str_with_invalid_input @ test_jni_pp
@ test_from_json_string_with_valid_input @ test_from_json_string_with_invalid_input

Loading…
Cancel
Save