[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 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

@ -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
in
let class_matcher =
let is_target_class =
let target = Typ.Name.Java.from_string clazz in
fun tname -> Typ.Name.equal tname target
in
if search_superclasses then fun tenv classname ->
let is_target_struct tname _ = is_target_class tname in
PatternMatch.supertype_exists tenv is_target_struct classname
else fun _ classname -> is_target_class classname
if search_superclasses then
let target = "class " ^ clazz in
let is_target tname _ = Typ.Name.to_string tname |> String.equal target in
fun tenv pname ->
Typ.Procname.get_class_type_name pname
|> Option.exists ~f:(PatternMatch.supertype_exists tenv is_target)
else fun _tenv pname ->
Typ.Procname.get_class_name pname |> Option.exists ~f:(String.equal clazz)
in
(fun tenv pn actuals ->
actuals_pred actuals
&&
match pn with
| Typ.Procname.Java java_pname ->
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 )
let mthd = Typ.Procname.get_method pn in
List.exists methods ~f:(method_matcher mthd) && class_matcher tenv pn )
|> Staged.stage

@ -20,103 +20,104 @@ end
type container_access = ContainerRead | ContainerWrite
let get_container_access =
let is_cpp_container_read =
let is_java_container_write =
let open MethodMatcher in
let array_methods =
["append"; "clear"; "delete"; "put"; "remove"; "removeAt"; "removeAtRange"; "setValueAt"]
in
[ { default with
classname= "android.support.v4.util.Pools$SimplePool"; methods= ["acquire"; "release"] }
; { default with
classname= "android.support.v4.util.SimpleArrayMap"
; methods= ["clear"; "ensureCapacity"; "put"; "putAll"; "remove"; "removeAt"; "setValueAt"] }
; {default with classname= "android.support.v4.util.SparseArrayCompat"; methods= array_methods}
; {default with classname= "android.util.SparseArray"; methods= array_methods}
; {default with classname= "java.util.List"; methods= ["add"; "addAll"; "clear"; "remove"; "set"]}
; {default with classname= "java.util.Map"; methods= ["clear"; "put"; "putAll"; "remove"]} ]
|> of_records
let is_java_container_read =
let open MethodMatcher in
let array_methods = ["clone"; "get"; "indexOfKey"; "indexOfValue"; "keyAt"; "size"; "valueAt"] in
[ { default with
classname= "android.support.v4.util.SimpleArrayMap"
; methods=
[ "containsKey"
; "containsValue"
; "get"
; "hashCode"
; "indexOfKey"
; "isEmpty"
; "keyAt"
; "size"
; "valueAt" ] }
; {default with classname= "android.support.v4.util.SparseArrayCompat"; methods= array_methods}
; {default with classname= "android.util.SparseArray"; methods= array_methods}
; { default with
classname= "java.util.List"
; methods=
[ "contains"
; "containsAll"
; "equals"
; "get"
; "hashCode"
; "indexOf"
; "isEmpty"
; "iterator"
; "lastIndexOf"
; "listIterator"
; "size"
; "toArray" ] }
; { default with
classname= "java.util.Map"
; methods=
[ "containsKey"
; "containsValue"
; "entrySet"
; "equals"
; "get"
; "hashCode"
; "isEmpty"
; "keySet"
; "size"
; "values" ] } ]
|> of_records
let is_cpp_container_read =
let is_container_operator pname_qualifiers =
match QualifiedCppName.extract_last pname_qualifiers with
| Some (last, _) ->
String.equal last "operator[]"
| None ->
false
QualifiedCppName.extract_last pname_qualifiers
|> Option.exists ~f:(fun (last, _) -> String.equal last "operator[]")
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 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
fun pn tenv ->
fun pname -> QualifiedCppName.Match.match_qualifiers matcher (Typ.Procname.get_qualifiers pname)
let get_container_access pn tenv =
match pn with
| Typ.Procname.Java java_pname ->
let typename = Typ.Name.Java.from_string (Typ.Procname.Java.get_class_name java_pname) in
let get_container_access_ typename =
match (Typ.Name.name typename, Typ.Procname.Java.get_method java_pname) with
| ( ("android.util.SparseArray" | "android.support.v4.util.SparseArrayCompat")
, ( "append"
| "clear"
| "delete"
| "put"
| "remove"
| "removeAt"
| "removeAtRange"
| "setValueAt" ) ) ->
Some ContainerWrite
| ( ("android.util.SparseArray" | "android.support.v4.util.SparseArrayCompat")
, ("clone" | "get" | "indexOfKey" | "indexOfValue" | "keyAt" | "size" | "valueAt") ) ->
Some ContainerRead
| ( "android.support.v4.util.SimpleArrayMap"
, ("clear" | "ensureCapacity" | "put" | "putAll" | "remove" | "removeAt" | "setValueAt")
) ->
Some ContainerWrite
| ( "android.support.v4.util.SimpleArrayMap"
, ( "containsKey"
| "containsValue"
| "get"
| "hashCode"
| "indexOfKey"
| "isEmpty"
| "keyAt"
| "size"
| "valueAt" ) ) ->
Some ContainerRead
| "android.support.v4.util.Pools$SimplePool", ("acquire" | "release") ->
| Typ.Procname.Java _ when is_java_container_write tenv pn [] ->
Some ContainerWrite
| "java.util.List", ("add" | "addAll" | "clear" | "remove" | "set") ->
Some ContainerWrite
| ( "java.util.List"
, ( "contains"
| "containsAll"
| "equals"
| "get"
| "hashCode"
| "indexOf"
| "isEmpty"
| "iterator"
| "lastIndexOf"
| "listIterator"
| "size"
| "toArray" ) ) ->
Some ContainerRead
| "java.util.Map", ("clear" | "put" | "putAll" | "remove") ->
Some ContainerWrite
| ( "java.util.Map"
, ( "containsKey"
| "containsValue"
| "entrySet"
| "equals"
| "get"
| "hashCode"
| "isEmpty"
| "keySet"
| "size"
| "values" ) ) ->
| Typ.Procname.Java _ when is_java_container_read tenv pn [] ->
Some ContainerRead
| _ ->
| Typ.Procname.Java _ ->
None
in
PatternMatch.supertype_find_map_opt tenv get_container_access_ typename
(* 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 _) as pname when is_cpp_container_write pname ->
| (Typ.Procname.ObjC_Cpp _ | C _) when is_cpp_container_write pn ->
Some ContainerWrite
| (Typ.Procname.ObjC_Cpp _ | C _) as pname when is_cpp_container_read pname ->
| (Typ.Procname.ObjC_Cpp _ | C _) when is_cpp_container_read pn ->
Some ContainerRead
| _ ->
None

Loading…
Cancel
Save