@ -573,3 +573,59 @@ let is_synchronized_container callee_pname (access_exp : HilExp.AccessExpression
let is_initializer tenv proc_name =
Procname . is_constructor proc_name | | FbThreadSafety . is_custom_init tenv proc_name
let get_current_class_and_superclasses_satisfying_attr_check check tenv pname =
match pname with
| Procname . Java java_pname ->
let current_class = Procname . Java . get_class_type_name java_pname in
let satisfying_classes =
PatternMatch . Java . find_superclasses_with_attributes check tenv current_class
in
Some ( current_class , satisfying_classes )
| _ ->
None
module Litho = struct
let component_annots = [ " MountSpec " ; " LayoutSpec " ]
let section_annots = [ " DiffSectionSpec " ; " GroupSectionSpec " ]
let spec_annots = List . append component_annots section_annots
let get_class_annot pname tenv =
let helper annot =
let is_annotated ia = Annotations . ia_ends_with ia annot in
match get_current_class_and_superclasses_satisfying_attr_check is_annotated tenv pname with
| Some ( current_class , ( _ :: _ as classes ) ) ->
if List . mem ~ equal : Typ . Name . equal classes current_class then Some ( " current " , annot )
else Some ( " a super " , annot )
| _ ->
None
in
List . find_map ~ f : helper spec_annots
(* "ann" is typically a suffix of an annotation, so if ann is "LayoutSpec" the developer would have
written " @LayoutSpec " . qualifier is " this " or " a super " , the latter corresponding to
superclass . * )
let message ( qualifier , ann ) =
let mes1 =
if List . mem ~ equal : String . equal component_annots ann then
" Litho components are required to be thread safe because of multi-threaded layout. "
else if List . mem ~ equal : String . equal section_annots ann then
" Sections are required to be thread safe because changesets are calculated in the \
background . "
else (* should not get here *)
" "
in
(* This "round the houses" way of doing things, where developer writes annotation with @, we pass
around annotation without @ , then add it back here , is just because we use ia_ends_with and it
is not worth adding stuff to annotations . ml to make the code here simpler * )
Format . asprintf " @ \n %s Reporting because %sclass is annotated %a " mes1 qualifier
MarkupFormatter . pp_monospaced ( " @ " ^ ann )
end
let get_litho_explanation tenv pname =
Litho . get_class_annot pname tenv | > Option . map ~ f : Litho . message