[racerd] refactor method matching for all languages

Reviewed By: jeremydubreil

Differential Revision: D12907796

fbshipit-source-id: 764d2eef4
master
Nikos Gorogiannis 6 years ago committed by Facebook Github Bot
parent 646aa30797
commit 3b5262f185

@ -490,7 +490,7 @@ being the name of the struct, [None] means the parameter is of some other type.
val equal : t -> t -> bool val equal : t -> t -> bool
val get_class_type_name : t -> Name.t option [@@warning "-32"] val get_class_type_name : t -> Name.t option
val get_class_name : t -> string option val get_class_name : t -> string option

@ -16,27 +16,20 @@ let call_matches ?(search_superclasses = true) ?(method_prefix = false)
else fun current_method target_method -> String.equal current_method target_method else fun current_method target_method -> String.equal current_method target_method
in in
let class_matcher = let class_matcher =
let is_target_class = if search_superclasses then
let target = Typ.Name.Java.from_string clazz in let target = "class " ^ clazz in
fun tname -> Typ.Name.equal tname target let is_target tname _ = Typ.Name.to_string tname |> String.equal target in
in fun tenv pname ->
if search_superclasses then fun tenv classname -> Typ.Procname.get_class_type_name pname
let is_target_struct tname _ = is_target_class tname in |> Option.exists ~f:(PatternMatch.supertype_exists tenv is_target)
PatternMatch.supertype_exists tenv is_target_struct classname else fun _tenv pname ->
else fun _ classname -> is_target_class classname Typ.Procname.get_class_name pname |> Option.exists ~f:(String.equal clazz)
in in
(fun tenv pn actuals -> (fun tenv pn actuals ->
actuals_pred actuals actuals_pred actuals
&& &&
match pn with let mthd = Typ.Procname.get_method pn in
| Typ.Procname.Java java_pname -> List.exists methods ~f:(method_matcher mthd) && class_matcher tenv pn )
let mthd = Typ.Procname.Java.get_method java_pname in
List.exists methods ~f:(method_matcher mthd)
&&
let classname = Typ.Procname.Java.get_class_type_name java_pname in
class_matcher tenv classname
| _ ->
false )
|> Staged.stage |> Staged.stage

@ -20,106 +20,107 @@ end
type container_access = ContainerRead | ContainerWrite type container_access = ContainerRead | ContainerWrite
let get_container_access = let is_java_container_write =
let is_cpp_container_read = let open MethodMatcher in
let is_container_operator pname_qualifiers = let array_methods =
match QualifiedCppName.extract_last pname_qualifiers with ["append"; "clear"; "delete"; "put"; "remove"; "removeAt"; "removeAtRange"; "setValueAt"]
| Some (last, _) ->
String.equal last "operator[]"
| None ->
false
in
let matcher = QualifiedCppName.Match.of_fuzzy_qual_names ["std::map::find"] in
fun pname ->
let pname_qualifiers = Typ.Procname.get_qualifiers pname in
QualifiedCppName.Match.match_qualifiers matcher pname_qualifiers
|| is_container_operator pname_qualifiers
and is_cpp_container_write =
let matcher =
QualifiedCppName.Match.of_fuzzy_qual_names ["std::map::operator[]"; "std::map::erase"]
in
fun pname ->
QualifiedCppName.Match.match_qualifiers matcher (Typ.Procname.get_qualifiers pname)
in in
fun pn tenv -> [ { default with
match pn with classname= "android.support.v4.util.Pools$SimplePool"; methods= ["acquire"; "release"] }
| Typ.Procname.Java java_pname -> ; { default with
let typename = Typ.Name.Java.from_string (Typ.Procname.Java.get_class_name java_pname) in classname= "android.support.v4.util.SimpleArrayMap"
let get_container_access_ typename = ; methods= ["clear"; "ensureCapacity"; "put"; "putAll"; "remove"; "removeAt"; "setValueAt"] }
match (Typ.Name.name typename, Typ.Procname.Java.get_method java_pname) with ; {default with classname= "android.support.v4.util.SparseArrayCompat"; methods= array_methods}
| ( ("android.util.SparseArray" | "android.support.v4.util.SparseArrayCompat") ; {default with classname= "android.util.SparseArray"; methods= array_methods}
, ( "append" ; {default with classname= "java.util.List"; methods= ["add"; "addAll"; "clear"; "remove"; "set"]}
| "clear" ; {default with classname= "java.util.Map"; methods= ["clear"; "put"; "putAll"; "remove"]} ]
| "delete" |> of_records
| "put"
| "remove"
| "removeAt" let is_java_container_read =
| "removeAtRange" let open MethodMatcher in
| "setValueAt" ) ) -> let array_methods = ["clone"; "get"; "indexOfKey"; "indexOfValue"; "keyAt"; "size"; "valueAt"] in
Some ContainerWrite [ { default with
| ( ("android.util.SparseArray" | "android.support.v4.util.SparseArrayCompat") classname= "android.support.v4.util.SimpleArrayMap"
, ("clone" | "get" | "indexOfKey" | "indexOfValue" | "keyAt" | "size" | "valueAt") ) -> ; methods=
Some ContainerRead [ "containsKey"
| ( "android.support.v4.util.SimpleArrayMap" ; "containsValue"
, ("clear" | "ensureCapacity" | "put" | "putAll" | "remove" | "removeAt" | "setValueAt") ; "get"
) -> ; "hashCode"
Some ContainerWrite ; "indexOfKey"
| ( "android.support.v4.util.SimpleArrayMap" ; "isEmpty"
, ( "containsKey" ; "keyAt"
| "containsValue" ; "size"
| "get" ; "valueAt" ] }
| "hashCode" ; {default with classname= "android.support.v4.util.SparseArrayCompat"; methods= array_methods}
| "indexOfKey" ; {default with classname= "android.util.SparseArray"; methods= array_methods}
| "isEmpty" ; { default with
| "keyAt" classname= "java.util.List"
| "size" ; methods=
| "valueAt" ) ) -> [ "contains"
Some ContainerRead ; "containsAll"
| "android.support.v4.util.Pools$SimplePool", ("acquire" | "release") -> ; "equals"
Some ContainerWrite ; "get"
| "java.util.List", ("add" | "addAll" | "clear" | "remove" | "set") -> ; "hashCode"
Some ContainerWrite ; "indexOf"
| ( "java.util.List" ; "isEmpty"
, ( "contains" ; "iterator"
| "containsAll" ; "lastIndexOf"
| "equals" ; "listIterator"
| "get" ; "size"
| "hashCode" ; "toArray" ] }
| "indexOf" ; { default with
| "isEmpty" classname= "java.util.Map"
| "iterator" ; methods=
| "lastIndexOf" [ "containsKey"
| "listIterator" ; "containsValue"
| "size" ; "entrySet"
| "toArray" ) ) -> ; "equals"
Some ContainerRead ; "get"
| "java.util.Map", ("clear" | "put" | "putAll" | "remove") -> ; "hashCode"
Some ContainerWrite ; "isEmpty"
| ( "java.util.Map" ; "keySet"
, ( "containsKey" ; "size"
| "containsValue" ; "values" ] } ]
| "entrySet" |> of_records
| "equals"
| "get"
| "hashCode" let is_cpp_container_read =
| "isEmpty" let is_container_operator pname_qualifiers =
| "keySet" QualifiedCppName.extract_last pname_qualifiers
| "size" |> Option.exists ~f:(fun (last, _) -> String.equal last "operator[]")
| "values" ) ) -> in
Some ContainerRead let matcher = QualifiedCppName.Match.of_fuzzy_qual_names ["std::map::find"] in
| _ -> fun pname ->
None let pname_qualifiers = Typ.Procname.get_qualifiers pname in
in QualifiedCppName.Match.match_qualifiers matcher pname_qualifiers
PatternMatch.supertype_find_map_opt tenv get_container_access_ typename || is_container_operator pname_qualifiers
(* The following order matters: we want to check if pname is a container write
before we check if pname is a container read. This is due to a different
treatment between std::map::operator[] and all other operator[]. *) let is_cpp_container_write =
| (Typ.Procname.ObjC_Cpp _ | C _) as pname when is_cpp_container_write pname -> let matcher =
Some ContainerWrite QualifiedCppName.Match.of_fuzzy_qual_names ["std::map::operator[]"; "std::map::erase"]
| (Typ.Procname.ObjC_Cpp _ | C _) as pname when is_cpp_container_read pname -> in
Some ContainerRead fun pname -> QualifiedCppName.Match.match_qualifiers matcher (Typ.Procname.get_qualifiers pname)
| _ ->
None
let get_container_access pn tenv =
match pn with
| Typ.Procname.Java _ when is_java_container_write tenv pn [] ->
Some ContainerWrite
| Typ.Procname.Java _ when is_java_container_read tenv pn [] ->
Some ContainerRead
| Typ.Procname.Java _ ->
None
(* The following order matters: we want to check if pname is a container write
before we check if pname is a container read. This is due to a different
treatment between std::map::operator[] and all other operator[]. *)
| (Typ.Procname.ObjC_Cpp _ | C _) when is_cpp_container_write pn ->
Some ContainerWrite
| (Typ.Procname.ObjC_Cpp _ | C _) when is_cpp_container_read pn ->
Some ContainerRead
| _ ->
None
(** holds of procedure names which should not be analyzed in order to avoid known sources of (** holds of procedure names which should not be analyzed in order to avoid known sources of

Loading…
Cancel
Save