diff --git a/infer/src/IR/JavaClassName.ml b/infer/src/IR/JavaClassName.ml index 8735750c4..088c7100e 100644 --- a/infer/src/IR/JavaClassName.ml +++ b/infer/src/IR/JavaClassName.ml @@ -43,3 +43,7 @@ let classname {classname} = classname let is_external_via_config t = let package = package t in Option.exists ~f:Config.java_package_is_external package + + +let pp_with_verbosity ~verbose fmt t = + if verbose then pp fmt t else F.pp_print_string fmt (classname t) diff --git a/infer/src/IR/JavaClassName.mli b/infer/src/IR/JavaClassName.mli index f768ce8af..a096c948a 100644 --- a/infer/src/IR/JavaClassName.mli +++ b/infer/src/IR/JavaClassName.mli @@ -15,6 +15,9 @@ val to_string : t -> string val pp : Format.formatter -> t -> unit +val pp_with_verbosity : verbose:bool -> Format.formatter -> t -> unit +(** if [verbose] then print package if present, otherwise only print class *) + val package : t -> string option val classname : t -> string diff --git a/infer/src/IR/JavaSplitName.ml b/infer/src/IR/JavaSplitName.ml new file mode 100644 index 000000000..b6d28df62 --- /dev/null +++ b/infer/src/IR/JavaSplitName.ml @@ -0,0 +1,39 @@ +(* + * 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_string = make ~package:"java.lang" "String" + +let void = make "void" + +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 diff --git a/infer/src/IR/JavaSplitName.mli b/infer/src/IR/JavaSplitName.mli new file mode 100644 index 000000000..505889e42 --- /dev/null +++ b/infer/src/IR/JavaSplitName.mli @@ -0,0 +1,35 @@ +(* + * 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_string : t +(** [java.lang.String] type *) + +val void : t +(** Java [void] type *) + +val package : t -> string option + +val type_name : t -> string + +val pp_type_verbosity : verbose:bool -> F.formatter -> t -> unit diff --git a/infer/src/IR/Procname.ml b/infer/src/IR/Procname.ml index f97dab69c..d6818a6c9 100644 --- a/infer/src/IR/Procname.ml +++ b/infer/src/IR/Procname.ml @@ -8,6 +8,7 @@ open! IStd module Hashtbl = Caml.Hashtbl module F = Format +module L = Logging (** Level of verbosity of some to_string functions. *) type detail_level = Verbose | Non_verbose | Simple [@@deriving compare, equal] @@ -22,9 +23,9 @@ module Java = struct [@@deriving compare] (* TODO: use Mangled.t here *) - type java_type = Typ.Name.Java.Split.t [@@deriving compare, equal] + type java_type = JavaSplitName.t [@@deriving compare, equal] - let java_void = Typ.Name.Java.Split.make "void" + let java_void = JavaSplitName.void (** Type of java procedure names. *) type t = @@ -40,7 +41,7 @@ module Java = struct let pp_type_verbosity verbosity fmt java_type = - Typ.Name.Java.Split.pp_type_verbosity ~verbose:(is_verbose verbosity) fmt java_type + JavaSplitName.pp_type_verbosity ~verbose:(is_verbose verbosity) fmt java_type (** Given a list of types, it creates a unique string of types separated by commas *) @@ -56,8 +57,6 @@ module Java = struct pp_param_list verbosity fmt rest - let java_type_of_name class_name = Typ.Name.Java.Split.of_string (Typ.Name.name class_name) - (** It is the same as java_type_to_string_verbosity, but Java return types are optional because of constructors without type *) let pp_return_type verbosity fmt j = @@ -68,9 +67,17 @@ module Java = struct let get_class_type_name j = j.class_name - let get_simple_class_name j = Typ.Name.Java.Split.(j |> get_class_name |> of_string |> type_name) + let get_java_class_name_exn j = + match j.class_name with + | Typ.JavaClass java_class_name -> + java_class_name + | _ -> + L.die InternalError "Asked for java class name but got something else" + - let get_package j = Typ.Name.Java.Split.(j |> get_class_name |> of_string |> package) + let get_simple_class_name j = JavaClassName.classname (get_java_class_name_exn j) + + let get_package j = JavaClassName.package (get_java_class_name_exn j) let get_method j = j.method_name @@ -84,14 +91,15 @@ module Java = struct (** Prints a string of a java procname with the given level of verbosity *) let pp ?(withclass = false) verbosity fmt j = + let pp_class_name verbosity fmt j = + JavaClassName.pp_with_verbosity ~verbose:(is_verbose verbosity) fmt + (get_java_class_name_exn j) + in match verbosity with | Verbose | Non_verbose -> (* if verbose, then package.class.method(params): rtype, else rtype package.class.method(params) verbose is used for example to create unique filenames, non_verbose to create reports *) - let pp_class_name verbosity fmt j = - pp_type_verbosity verbosity fmt (Typ.Name.Java.split_typename j.class_name) - in let separator = match (j.return_type, verbosity) with None, _ -> "" | Some _, Verbose -> ":" | _ -> " " in @@ -104,9 +112,7 @@ module Java = struct | Simple -> (* methodname(...) or without ... if there are no parameters *) let pp_class_prefix ~withclass verbosity fmt j = - if withclass then - F.fprintf fmt "%a." (pp_type_verbosity verbosity) - (Typ.Name.Java.split_typename j.class_name) + if withclass then F.fprintf fmt "%a." (pp_class_name verbosity) j in let params = match j.parameters with [] -> "" | _ -> "..." in let pp_method_name ~withclass verbosity fmt j = @@ -197,7 +203,7 @@ module Java = struct (* FIXME this looks wrong due to the dot in the type name *) List.last parameters |> Option.exists ~f:(fun java_type -> - String.equal "java.lang.Object[]" (Typ.Name.Java.Split.type_name java_type) ) + String.equal "java.lang.Object[]" (JavaSplitName.type_name java_type) ) let is_external java_pname = @@ -715,7 +721,7 @@ let rec replace_parameters new_parameters procname = let parameter_of_name procname class_name = match procname with | Java _ -> - Parameter.JavaParameter (Java.java_type_of_name class_name) + Parameter.JavaParameter (JavaSplitName.of_string (Typ.Name.name class_name)) | _ -> Parameter.ClangParameter (Parameter.clang_param_of_name class_name) diff --git a/infer/src/IR/Procname.mli b/infer/src/IR/Procname.mli index 883c244c0..ec933fc7f 100644 --- a/infer/src/IR/Procname.mli +++ b/infer/src/IR/Procname.mli @@ -19,7 +19,7 @@ module Java : sig type t [@@deriving compare] - type java_type = Typ.Name.Java.Split.t [@@deriving compare, equal] + type java_type = JavaSplitName.t [@@deriving compare, equal] val constructor_method_name : string diff --git a/infer/src/IR/Typ.ml b/infer/src/IR/Typ.ml index 07842fb0c..1410f35f9 100644 --- a/infer/src/IR/Typ.ml +++ b/infer/src/IR/Typ.ml @@ -451,47 +451,6 @@ module Name = struct end 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} [@@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 of_java_class_name java_class_name = - let package = JavaClassName.package java_class_name in - let type_name = JavaClassName.classname java_class_name in - make ?package type_name - - - 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" - - let void = make "void" - - 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 - end - let from_string name_str = JavaClass (JavaClassName.from_string name_str) let is_class = function JavaClass _ -> true | _ -> false @@ -514,8 +473,6 @@ module Name = struct L.die InternalError "Tried to split a non-java class name into a java split type@." - let split_typename typename = Split.of_java_class_name (get_java_class_name_exn typename) - let is_anonymous_inner_class_name class_name = let java_class_name = get_java_class_name_exn class_name in let class_name_no_package = JavaClassName.classname java_class_name in diff --git a/infer/src/IR/Typ.mli b/infer/src/IR/Typ.mli index 7e2931914..abdaaea31 100644 --- a/infer/src/IR/Typ.mli +++ b/infer/src/IR/Typ.mli @@ -219,26 +219,6 @@ module Name : sig end module Java : sig - module Split : sig - type t [@@deriving compare, equal] - - val make : ?package:string -> string -> t - - val of_string : string -> t - - val java_lang_object : t - - val java_lang_string : t - - val void : t - - val package : t -> string option - - val type_name : t -> string - - val pp_type_verbosity : verbose:bool -> F.formatter -> t -> unit - end - val from_string : string -> t (** Create a typename from a Java classname in the form "package.class" *) @@ -250,8 +230,6 @@ module Name : sig val is_anonymous_inner_class_name : t -> bool - val split_typename : t -> Split.t - val java_lang_object : t val java_io_serializable : t diff --git a/infer/src/absint/PatternMatch.ml b/infer/src/absint/PatternMatch.ml index 3d7944ce5..84e76dac8 100644 --- a/infer/src/absint/PatternMatch.ml +++ b/infer/src/absint/PatternMatch.ml @@ -465,7 +465,7 @@ let rec find_superclasses_with_attributes check tenv tname = let is_override_of_java_lang_object_equals curr_pname = let is_only_param_of_object_type = function | [Procname.Parameter.JavaParameter param_type] - when Typ.Name.Java.Split.equal param_type Typ.Name.Java.Split.java_lang_object -> + when JavaSplitName.equal param_type JavaSplitName.java_lang_object -> true | _ -> false diff --git a/infer/src/biabduction/SymExec.ml b/infer/src/biabduction/SymExec.ml index 8a9f455b2..494032779 100644 --- a/infer/src/biabduction/SymExec.ml +++ b/infer/src/biabduction/SymExec.ml @@ -736,9 +736,7 @@ let call_constructor_url_update_args pname actual_params = Procname.Java (Procname.Java.make (Typ.Name.Java.from_string "java.net.URL") - None "" - [Typ.Name.Java.Split.java_lang_string] - Procname.Java.Non_Static) + None "" [JavaSplitName.java_lang_string] Procname.Java.Non_Static) in if Procname.equal url_pname pname then match actual_params with diff --git a/infer/src/java/JProcname.ml b/infer/src/java/JProcname.ml index 06e2c060e..62a9e3bda 100644 --- a/infer/src/java/JProcname.ml +++ b/infer/src/java/JProcname.ml @@ -68,7 +68,7 @@ module JNI = struct let rec to_java_type jni = - let make = Typ.Name.Java.Split.make in + let make = JavaSplitName.make in match jni with | Boolean -> make "bool" @@ -92,8 +92,8 @@ module JNI = struct make ~package:pkg cl | Array typ -> let java_type = to_java_type typ in - let typ_str = Typ.Name.Java.Split.type_name java_type in - make ?package:(Typ.Name.Java.Split.package java_type) (Printf.sprintf "%s[]" typ_str) + 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") diff --git a/infer/src/java/jTransType.ml b/infer/src/java/jTransType.ml index a3d928ee7..ec886fdb0 100644 --- a/infer/src/java/jTransType.ml +++ b/infer/src/java/jTransType.ml @@ -152,7 +152,7 @@ let rec string_of_type vt = let package_to_string = function [] -> None | p -> Some (String.concat ~sep:"." p) let cn_to_java_type cn = - Typ.Name.Java.Split.make + JavaSplitName.make ?package:(package_to_string (JBasics.cn_package cn)) (JBasics.cn_simple_name cn) @@ -160,11 +160,11 @@ let cn_to_java_type cn = let vt_to_java_type vt = match vt with | JBasics.TBasic bt -> - Typ.Name.Java.Split.make (string_of_basic_type bt) + JavaSplitName.make (string_of_basic_type bt) | JBasics.TObject ot -> ( match ot with | JBasics.TArray vt -> - Typ.Name.Java.Split.make (string_of_type vt ^ "[]") + JavaSplitName.make (string_of_type vt ^ "[]") | JBasics.TClass cn -> cn_to_java_type cn ) @@ -176,7 +176,7 @@ let method_signature_names ms = | None when String.equal method_name JConfig.constructor_name -> None | None -> - Some (Typ.Name.Java.Split.make JConfig.void) + Some (JavaSplitName.make JConfig.void) | Some vt -> Some (vt_to_java_type vt) in diff --git a/infer/src/nullsafe/ThirdPartyMethod.ml b/infer/src/nullsafe/ThirdPartyMethod.ml index f2c993ce7..4b03f2d79 100644 --- a/infer/src/nullsafe/ThirdPartyMethod.ml +++ b/infer/src/nullsafe/ThirdPartyMethod.ml @@ -49,8 +49,8 @@ let string_of_parsing_error = function let pp_unique_repr fmt signature = Sexp.pp fmt (sexp_of_unique_repr signature) let java_type_to_string java_type = - let package = Typ.Name.Java.Split.package java_type in - let type_name = Typ.Name.Java.Split.type_name java_type in + let package = JavaSplitName.package java_type in + let type_name = JavaSplitName.type_name java_type in match package with | None -> (* Primitive type *) diff --git a/infer/src/nullsafe/typeCheck.ml b/infer/src/nullsafe/typeCheck.ml index 194b03419..af81959b7 100644 --- a/infer/src/nullsafe/typeCheck.ml +++ b/infer/src/nullsafe/typeCheck.ml @@ -570,7 +570,7 @@ let do_map_put call_params callee_pname tenv loc node curr_pname curr_pdesc call instr_ref ~nullsafe_mode 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 = Typ.Name.Java.Split.java_lang_object in + let object_t = JavaSplitName.java_lang_object in let parameters = [object_t] in pname_put |> Procname.Java.replace_method_name "get" @@ -709,7 +709,7 @@ let rec check_condition_for_sil_prune tenv idenv calls_this find_canonical_dupli (DExp.Dretcall (DExp.Dconst (Const.Cfun (Procname.Java pname_java)), args, loc, call_flags)) -> let pname_java' = - let object_t = Typ.Name.Java.Split.java_lang_object in + let object_t = JavaSplitName.java_lang_object in pname_java |> Procname.Java.replace_method_name "get" |> Procname.Java.replace_return_type object_t diff --git a/infer/src/topl/ToplUtils.ml b/infer/src/topl/ToplUtils.ml index 67f3b5d0f..7e6c9a16e 100644 --- a/infer/src/topl/ToplUtils.ml +++ b/infer/src/topl/ToplUtils.ml @@ -18,8 +18,8 @@ let topl_class_typ = Typ.mk (Tstruct topl_class_name) let topl_call ret_id (ret_typ : Typ.desc) loc name arg_ts : Sil.instr = let e_fun = - let ret_typ = Some Typ.Name.Java.Split.void in - let args_typ = List.map arg_ts ~f:(fun _ -> Typ.Name.Java.Split.java_lang_object) in + let ret_typ = Some JavaSplitName.void in + let args_typ = List.map arg_ts ~f:(fun _ -> JavaSplitName.java_lang_object) in Exp.Const (Const.Cfun (Procname.Java diff --git a/infer/src/unit/JavaProfilerSamplesTest.ml b/infer/src/unit/JavaProfilerSamplesTest.ml index 20472475b..47e90fd1c 100644 --- a/infer/src/unit/JavaProfilerSamplesTest.ml +++ b/infer/src/unit/JavaProfilerSamplesTest.ml @@ -9,7 +9,7 @@ open! IStd open OUnit2 module T = JProcname.JNI.VISIBLE_FOR_TESTING_DO_NOT_USE_DIRECTLY -let mk_split (pkg, typ) = Typ.Name.Java.Split.make ?package:pkg typ +let mk_split (pkg, typ) = JavaSplitName.make ?package:pkg typ let test_jni_pp = let create_test input expected _ = @@ -130,10 +130,10 @@ 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:"" (Typ.Name.Java.Split.package expected) in - let exp_cl = Typ.Name.Java.Split.type_name expected in - let actual_pkg = Option.value ~default:"" (Typ.Name.Java.Split.package actual) in - let actual_cl = Typ.Name.Java.Split.type_name actual in + let exp_pkg = Option.value ~default:"" (JavaSplitName.package expected) in + let exp_cl = JavaSplitName.type_name expected in + let actual_pkg = Option.value ~default:"" (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