From fccf66968f7cb1308a477214820bf941f84c7c60 Mon Sep 17 00:00:00 2001 From: Mitya Lyubarskiy Date: Fri, 24 Apr 2020 09:36:55 -0700 Subject: [PATCH] [nullsafe] A helper function to extract outer class. Summary: To be used in the next diff. Reviewed By: artempyanykh Differential Revision: D21228077 fbshipit-source-id: f4220f953 --- infer/src/IR/JavaClassName.ml | 4 ++++ infer/src/IR/JavaClassName.mli | 4 ++++ infer/src/unit/JavaClassNameTests.ml | 16 +++++++++++++++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/infer/src/IR/JavaClassName.ml b/infer/src/IR/JavaClassName.ml index 240dd4903..1c4428f66 100644 --- a/infer/src/IR/JavaClassName.ml +++ b/infer/src/IR/JavaClassName.ml @@ -63,6 +63,10 @@ let is_int s = with Failure _ -> false +let get_outer_class_name {package; classname} = + String.rsplit2 classname ~on:'$' |> Option.map ~f:(fun (outer, _) -> {package; classname= outer}) + + (* Strips $ suffixes from the class name, and return how many were stripped *) let strip_anonymous_suffixes_if_present classname = let rec strip_recursively classname nesting_level = diff --git a/infer/src/IR/JavaClassName.mli b/infer/src/IR/JavaClassName.mli index 2edba0f7f..1bf993f69 100644 --- a/infer/src/IR/JavaClassName.mli +++ b/infer/src/IR/JavaClassName.mli @@ -31,6 +31,10 @@ val classname : t -> string val is_external_via_config : t -> bool (** Considered external based on config flags. *) +val get_outer_class_name : t -> t option +(** If this is an inner class, return the closest outer, e.g. A$B for A$B$C. None if the class is + outermost *) + val is_anonymous_inner_class_name : t -> bool (** True if it is either "classic" anonymous Java class: https://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html, or a synthetic Java diff --git a/infer/src/unit/JavaClassNameTests.ml b/infer/src/unit/JavaClassNameTests.ml index 5e3aeee2c..f0252444c 100644 --- a/infer/src/unit/JavaClassNameTests.ml +++ b/infer/src/unit/JavaClassNameTests.ml @@ -105,4 +105,18 @@ let test_anonymous = ~expected_classname:"SomeClass$NestedClass$AgainNestedClass" -let tests = "JavaClassNameTests" >::: [test_from_string; test_anonymous] +let test_outer = + "test_outer" + >:: fun _ -> + get_outer_class_name (make ~package:(Some "some.package") ~classname:"SomeClass") |> assert_none ; + get_outer_class_name (make ~package:(Some "some.package") ~classname:"SomeClass$NestedClass") + |> assert_some + |> assert_equal_to ~expected_package:(Some "some.package") ~expected_classname:"SomeClass" ; + get_outer_class_name + (make ~package:(Some "some.package") ~classname:"SomeClass$NestedClass$AnotherNested") + |> assert_some + |> assert_equal_to ~expected_package:(Some "some.package") + ~expected_classname:"SomeClass$NestedClass" + + +let tests = "JavaClassNameTests" >::: [test_from_string; test_anonymous; test_outer]