Skip to content

Commit 50c98db

Browse files
davidpichardiefacebook-github-bot
authored andcommitted
Storing class source file locations in Struct (Tenv) records
Summary: Java bytecode format does not record the declarations location for classes and fields. We set up a first infrastructure to recover this information. Currently we only track location for classes and only gives the first line of the corresponding source file. We will enhance this location with source file (baby) parsing in a next diff. Reviewed By: mityal Differential Revision: D20868187 fbshipit-source-id: d355475e9
1 parent 3ccacb1 commit 50c98db

File tree

11 files changed

+101
-22
lines changed

11 files changed

+101
-22
lines changed

infer/src/IR/Struct.ml

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,13 @@ type field = Fieldname.t * Typ.t * Annot.Item.t [@@deriving compare]
1212

1313
type fields = field list
1414

15-
type java_class_kind = Interface | AbstractClass | NormalClass
15+
type java_class_kind = Interface | AbstractClass | NormalClass [@@deriving equal]
16+
17+
type java_class_info =
18+
{ kind: java_class_kind (** class kind in Java *)
19+
; loc: Location.t option
20+
(** None should correspond to rare cases when it was impossible to fetch the location in
21+
source file *) }
1622

1723
(** Type for a structured value. *)
1824
type t =
@@ -23,7 +29,7 @@ type t =
2329
; methods: Procname.t list (** methods defined *)
2430
; exported_objc_methods: Procname.t list (** methods in ObjC interface, subset of [methods] *)
2531
; annots: Annot.Item.t (** annotations *)
26-
; java_class_kind: java_class_kind option (** class kind in Java *)
32+
; java_class_info: java_class_info option (** present if and only if the class is Java *)
2733
; dummy: bool (** dummy struct for class including static method *) }
2834

2935
type lookup = Typ.Name.t -> t option
@@ -60,7 +66,7 @@ let pp pe name f {fields; supers; methods; exported_objc_methods; annots} =
6066

6167

6268
let internal_mk_struct ?default ?fields ?statics ?methods ?exported_objc_methods ?supers ?annots
63-
?java_class_kind ?dummy () =
69+
?java_class_info ?dummy () =
6470
let default_ =
6571
{ fields= []
6672
; statics= []
@@ -69,14 +75,14 @@ let internal_mk_struct ?default ?fields ?statics ?methods ?exported_objc_methods
6975
; supers= []
7076
; subs= Typ.Name.Set.empty
7177
; annots= Annot.Item.empty
72-
; java_class_kind= None
78+
; java_class_info= None
7379
; dummy= false }
7480
in
7581
let mk_struct_ ?(default = default_) ?(fields = default.fields) ?(statics = default.statics)
7682
?(methods = default.methods) ?(exported_objc_methods = default.exported_objc_methods)
7783
?(supers = default.supers) ?(subs = default.subs) ?(annots = default.annots)
7884
?(dummy = default.dummy) () =
79-
{fields; statics; methods; exported_objc_methods; supers; subs; annots; java_class_kind; dummy}
85+
{fields; statics; methods; exported_objc_methods; supers; subs; annots; java_class_info; dummy}
8086
in
8187
mk_struct_ ?default ?fields ?statics ?methods ?exported_objc_methods ?supers ?annots ?dummy ()
8288

infer/src/IR/Struct.mli

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,24 @@ type field = Fieldname.t * Typ.t * Annot.Item.t [@@deriving compare]
1313

1414
type fields = field list
1515

16-
type java_class_kind = Interface | AbstractClass | NormalClass
16+
type java_class_kind = Interface | AbstractClass | NormalClass [@@deriving equal]
17+
18+
type java_class_info =
19+
{ kind: java_class_kind (** class kind in Java *)
20+
; loc: Location.t option
21+
(** None should correspond to rare cases when it was impossible to fetch the location in
22+
source file *) }
1723

1824
(** Type for a structured value. *)
19-
type t = private
25+
type t =
2026
{ fields: fields (** non-static fields *)
2127
; statics: fields (** static fields *)
22-
; supers: Typ.Name.t list (** supers *)
28+
; supers: Typ.Name.t list (** superclasses *)
2329
; subs: Typ.Name.Set.t (** subclasses, initialized after merging type environments *)
2430
; methods: Procname.t list (** methods defined *)
2531
; exported_objc_methods: Procname.t list (** methods in ObjC interface, subset of [methods] *)
2632
; annots: Annot.Item.t (** annotations *)
27-
; java_class_kind: java_class_kind option (** class kind in Java *)
33+
; java_class_info: java_class_info option (** present if and only if the class is Java *)
2834
; dummy: bool (** dummy struct for class including static method *) }
2935

3036
type lookup = Typ.Name.t -> t option
@@ -42,7 +48,7 @@ val internal_mk_struct :
4248
-> ?exported_objc_methods:Procname.t list
4349
-> ?supers:Typ.Name.t list
4450
-> ?annots:Annot.Item.t
45-
-> ?java_class_kind:java_class_kind
51+
-> ?java_class_info:java_class_info
4652
-> ?dummy:bool
4753
-> unit
4854
-> t

infer/src/IR/Tenv.ml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ let create () = TypenameHash.create 1000
3030

3131
(** Construct a struct type in a type environment *)
3232
let mk_struct tenv ?default ?fields ?statics ?methods ?exported_objc_methods ?supers ?annots
33-
?java_class_kind ?dummy name =
33+
?java_class_info ?dummy name =
3434
let struct_typ =
3535
Struct.internal_mk_struct ?default ?fields ?statics ?methods ?exported_objc_methods ?supers
36-
?annots ?java_class_kind ?dummy ()
36+
?annots ?java_class_info ?dummy ()
3737
in
3838
TypenameHash.replace tenv name struct_typ ;
3939
struct_typ
@@ -224,13 +224,15 @@ let get_summary_formals tenv ~get_summary ~get_formals =
224224
`NotFound
225225
| Some class_name -> (
226226
match lookup tenv class_name with
227-
| Some {Struct.java_class_kind= Some Interface; subs}
228-
when Int.equal (Typ.Name.Set.cardinal subs) 1 ->
227+
| Some {Struct.java_class_info= Some info; subs}
228+
when Struct.equal_java_class_kind info.kind Interface
229+
&& Int.equal (Typ.Name.Set.cardinal subs) 1 ->
229230
let unique_sub = Typ.Name.Set.choose subs in
230231
Logging.d_printfln_escaped "Found a unique sub-class %a" Typ.Name.pp unique_sub ;
231232
let sub_pname = Procname.replace_class pname unique_sub in
232233
get_summary_formals_aux sub_pname |> found_from_subclass sub_pname
233-
| Some {Struct.java_class_kind= Some AbstractClass; subs} ->
234+
| Some {Struct.java_class_info= Some info; subs}
235+
when Struct.equal_java_class_kind info.kind AbstractClass ->
234236
Option.value_map (Typ.Name.Set.min_elt_opt subs) ~default:`NotFound ~f:(fun sub ->
235237
Logging.d_printfln_escaped "Found an arbitrary sub-class %a" Typ.Name.pp sub ;
236238
let sub_pname = Procname.replace_class pname sub in

infer/src/IR/Tenv.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ val mk_struct :
4141
-> ?exported_objc_methods:Procname.t list
4242
-> ?supers:Typ.Name.t list
4343
-> ?annots:Annot.Item.t
44-
-> ?java_class_kind:Struct.java_class_kind
44+
-> ?java_class_info:Struct.java_class_info
4545
-> ?dummy:bool
4646
-> Typ.Name.t
4747
-> Struct.t

infer/src/checkers/NullabilityPreanalysis.ml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,9 @@ let add_nonnull_to_fields fields tenv =
7878
match Typ.name typ with
7979
| Some typ_name -> (
8080
match Tenv.lookup tenv typ_name with
81-
| Some {fields; statics; supers; methods; annots} ->
81+
| Some ({fields} as struct_typ) ->
8282
let fields_with_annot = List.map ~f:(add_nonnull_to_selected_field field) fields in
83-
ignore
84-
(Tenv.mk_struct tenv ~fields:fields_with_annot ~statics ~supers ~methods ~annots
85-
typ_name)
83+
ignore (Tenv.mk_struct tenv ~default:struct_typ ~fields:fields_with_annot typ_name)
8684
| None ->
8785
() )
8886
| None ->

infer/src/java/jClasspath.ml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,13 +199,28 @@ type callee_status = Translated | Missing of JBasics.class_name * JBasics.method
199199

200200
type classmap = JCode.jcode Javalib.interface_or_class JBasics.ClassMap.t
201201

202+
(** We store for each classname the location of its declaration. This map is filled during
203+
JFrontend.compute_source_icfg and then it is used in JTransType.get_class_struct_typ before we
204+
lose access to JClasspath.program. At the end, the information seats in each Struct.t (stored in
205+
Tenv.t) *)
206+
type java_location_map = Location.t JBasics.ClassMap.t
207+
202208
type program =
203209
{ classpath_channel: Javalib.class_path
204210
; mutable classmap: classmap
211+
; mutable java_location_map: java_location_map
205212
; callees: callee_status Procname.Hash.t }
206213

207214
let get_classmap program = program.classmap
208215

216+
let set_java_location program cn loc =
217+
program.java_location_map <- JBasics.ClassMap.add cn loc program.java_location_map
218+
219+
220+
let get_java_location program cn =
221+
try Some (JBasics.ClassMap.find cn program.java_location_map) with Caml.Not_found -> None
222+
223+
209224
let mem_classmap cn program = JBasics.ClassMap.mem cn program.classmap
210225

211226
let get_classpath_channel program = program.classpath_channel
@@ -258,6 +273,7 @@ let load_program ~classpath classes =
258273
let program =
259274
{ classpath_channel= Javalib.class_path classpath
260275
; classmap= JBasics.ClassMap.empty
276+
; java_location_map= JBasics.ClassMap.empty
261277
; callees= Procname.Hash.create 128 }
262278
in
263279
JBasics.ClassSet.iter (fun cn -> ignore (lookup_node cn program)) classes ;

infer/src/java/jClasspath.mli

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ type program
2626

2727
val get_classmap : program -> classmap
2828

29+
val set_java_location : program -> JBasics.class_name -> Location.t -> unit
30+
31+
val get_java_location : program -> JBasics.class_name -> Location.t option
32+
2933
val mem_classmap : JBasics.class_name -> program -> bool
3034

3135
val cleanup : program -> unit

infer/src/java/jFrontend.ml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ let create_icfg source_file program tenv icfg cn node =
163163

164164

165165
(* returns true for the set of classes that are selected to be translated in the given
166-
progam *)
166+
program *)
167167
let should_capture program package_opt source_basename node =
168168
let classname = Javalib.get_name node in
169169
let match_package pkg cn =
@@ -194,6 +194,19 @@ let compute_source_icfg program tenv source_basename package_opt source_file =
194194
let select test procedure cn node =
195195
if test node then try procedure cn node with Bir.Subroutine -> ()
196196
in
197+
let set_java_location cn _node =
198+
let cn_name = JBasics.cn_name cn in
199+
let loc = JSourceFileInfo.class_name_location source_file cn_name in
200+
L.debug Capture Verbose "set_java_location %s with location %a@." cn_name Location.pp_file_pos
201+
loc ;
202+
JClasspath.set_java_location program cn loc
203+
in
204+
(* we must set the java location for all classes in the source file before translation *)
205+
let () =
206+
JBasics.ClassMap.iter
207+
(select (should_capture program package_opt source_basename) set_java_location)
208+
(JClasspath.get_classmap program)
209+
in
197210
let () =
198211
JBasics.ClassMap.iter
199212
(select

infer/src/java/jSourceFileInfo.ml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
(*
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*)
7+
8+
open! IStd
9+
10+
(** this is a naive/temporary implementation in a near diff, we will 1) parse the source file to
11+
collect location datas for all class names 2) cache the result for later uses but we may have to
12+
adapt a litle some signatures *)
13+
let class_name_location file _cn : Location.t = {line= 0; col= 0; file}

infer/src/java/jSourceFileInfo.mli

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
(*
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*)
7+
8+
open! IStd
9+
10+
val class_name_location : SourceFile.t -> string -> Location.t
11+
(** [class_name_location source class_name] searches in file [source] the declaration location for
12+
class name [class_name] *)

0 commit comments

Comments
 (0)