diff --git a/unit/java_bytecode/java_bytecode_parser/java_bytecode_parse_lambda_method_table.cpp b/unit/java_bytecode/java_bytecode_parser/java_bytecode_parse_lambda_method_table.cpp index d1484f098a3..ea132076074 100644 --- a/unit/java_bytecode/java_bytecode_parser/java_bytecode_parse_lambda_method_table.cpp +++ b/unit/java_bytecode/java_bytecode_parser/java_bytecode_parse_lambda_method_table.cpp @@ -7,6 +7,7 @@ \*******************************************************************/ #include +#include #include #include @@ -21,915 +22,1001 @@ typedef java_bytecode_parse_treet::classt::lambda_method_handlet lambda_method_handlet; +void run_test_with_compilers( + const std::function &test_with_compiler) +{ + test_with_compiler("openjdk_8"); + test_with_compiler("eclipse"); + test_with_compiler("oracle_8"); + test_with_compiler("oracle_9"); +} + SCENARIO( "lambda_method_handle_map with static lambdas", "[core][java_bytecode][java_bytecode_parse_lambda_method_handle]") { - null_message_handlert message_handler; - GIVEN("A class with a static lambda variables") - { - java_bytecode_parse_treet parse_tree; - java_bytecode_parse( - "./java_bytecode/java_bytecode_parser/lambda_examples/" - "StaticLambdas.class", - parse_tree, - message_handler); - WHEN("Parsing that class") + // NOLINTNEXTLINE(whitespace/braces) + run_test_with_compilers([](const std::string &compiler) { + null_message_handlert message_handler; + GIVEN( + "A class with a static lambda variables from " + compiler + " compiler.") { - REQUIRE(parse_tree.loading_successful); - const java_bytecode_parse_treet::classt parsed_class = - parse_tree.parsed_class; - REQUIRE(parsed_class.attribute_bootstrapmethods_read); - REQUIRE(parsed_class.lambda_method_handle_map.size() == 12); - - // Simple lambdas - THEN( - "There should be an entry for the lambda that has no parameters or " - "returns and the method it references should have an appropriate " - "descriptor") - { - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, "()V"); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == "()V"); - } - - // Parameter lambdas - THEN( - "There should be an entry for the lambda that takes parameters and the " - "method it references should have an appropriate descriptor") - { - std::string descriptor = "(ILjava/lang/Object;LDummyGeneric;)V"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - } - THEN( - "There should be an entry for the lambda that takes array parameters " - "and the method it references should have an appropriate descriptor") - { - std::string descriptor = "([I[Ljava/lang/Object;[LDummyGeneric;)V"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - } - - // Return lambdas - THEN( - "There should be an entry for the lambda that returns a primitive and " - "the method it references should have an appropriate descriptor") - { - std::string descriptor = "()I"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - } - THEN( - "There should be an entry for the lambda that returns a reference type " - "and the method it references should have an appropriate descriptor") - { - std::string descriptor = "()Ljava/lang/Object;"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - } - THEN( - "There should be an entry for the lambda that returns a specialised " - "generic type and the method it references should have an appropriate " - "descriptor") - { - std::string descriptor = "()LDummyGeneric;"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - } - - // Array returning lambdas - THEN( - "There should be an entry for the lambda that returns an array of " - "primitives and the method it references should have an appropriate " - "descriptor") - { - std::string descriptor = "()[I"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - } - THEN( - "There should be an entry for the lambda that returns an array of " - "reference types and the method it references should have an " - "appropriate descriptor") - { - std::string descriptor = "()[Ljava/lang/Object;"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - } - THEN( - "There should be an entry for the lambda that returns an array of " - "specialised generic types and the method it references should have an " - "appropriate descriptor") - { - std::string descriptor = "()[LDummyGeneric;"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - } - - // Capturing lamdbas - THEN( - "There should be an entry for the lambda that returns a primitive and " - "the method it references should have an appropriate descriptor") - { - std::string descriptor = "()I"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor, 1); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - - const typet primitive_type = java_int_type(); - - fieldref_exprt fieldref{ - primitive_type, "staticPrimitive", "java::StaticLambdas"}; - - std::vector - expected_instructions{{"getstatic", {fieldref}}, {"ireturn", {}}}; - - require_parse_tree::require_instructions_match_expectation( - expected_instructions, lambda_method.instructions); - } - THEN( - "There should be an entry for the lambda that returns a reference type " - "and the method it references should have an appropriate descriptor") - { - std::string descriptor = "()Ljava/lang/Object;"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor, 1); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - - const reference_typet dummy_generic_reference_type = - java_reference_type(symbol_typet{"java::java.lang.Object"}); - - fieldref_exprt fieldref{dummy_generic_reference_type, - "staticReference", - "java::StaticLambdas"}; - - std::vector - expected_instructions{{"getstatic", {fieldref}}, {"areturn", {}}}; - - require_parse_tree::require_instructions_match_expectation( - expected_instructions, lambda_method.instructions); - } - THEN( - "There should be an entry for the lambda that returns a specialised " - "generic type and the method it references should have an appropriate " - "descriptor") - { - std::string descriptor = "()LDummyGeneric;"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor, 1); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const java_bytecode_parse_treet::methodt &lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - - const reference_typet dummy_generic_reference_type = - java_reference_type(symbol_typet{"java::DummyGeneric"}); - - fieldref_exprt fieldref{dummy_generic_reference_type, - "staticSpecalisedGeneric", - "java::StaticLambdas"}; - - std::vector - expected_instructions{{"getstatic", {fieldref}}, {"areturn", {}}}; - - require_parse_tree::require_instructions_match_expectation( - expected_instructions, lambda_method.instructions); + java_bytecode_parse_treet parse_tree; + java_bytecode_parse( + "./java_bytecode/java_bytecode_parser/lambda_examples/" + compiler + + "_classes/StaticLambdas.class", + parse_tree, + message_handler); + WHEN("Parsing that class") + { + REQUIRE(parse_tree.loading_successful); + const java_bytecode_parse_treet::classt parsed_class = + parse_tree.parsed_class; + REQUIRE(parsed_class.attribute_bootstrapmethods_read); + REQUIRE(parsed_class.lambda_method_handle_map.size() == 12); + + // Simple lambdas + THEN( + "There should be an entry for the lambda that has no parameters or " + "returns and the method it references should have an appropriate " + "descriptor") + { + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, "()V"); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == "()V"); + } + + // Parameter lambdas + THEN( + "There should be an entry for the lambda that takes parameters and " + "the " + "method it references should have an appropriate descriptor") + { + std::string descriptor = "(ILjava/lang/Object;LDummyGeneric;)V"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that takes array " + "parameters " + "and the method it references should have an appropriate " + "descriptor") + { + std::string descriptor = "([I[Ljava/lang/Object;[LDummyGeneric;)V"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + + // Return lambdas + THEN( + "There should be an entry for the lambda that returns a primitive " + "and " + "the method it references should have an appropriate descriptor") + { + std::string descriptor = "()I"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that returns a reference " + "type " + "and the method it references should have an appropriate " + "descriptor") + { + std::string descriptor = "()Ljava/lang/Object;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that returns a " + "specialised " + "generic type and the method it references should have an " + "appropriate " + "descriptor") + { + std::string descriptor = "()LDummyGeneric;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + + // Array returning lambdas + THEN( + "There should be an entry for the lambda that returns an array of " + "primitives and the method it references should have an " + "appropriate " + "descriptor") + { + std::string descriptor = "()[I"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that returns an array of " + "reference types and the method it references should have an " + "appropriate descriptor") + { + std::string descriptor = "()[Ljava/lang/Object;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that returns an array of " + "specialised generic types and the method it references should " + "have an " + "appropriate descriptor") + { + std::string descriptor = "()[LDummyGeneric;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + + // Capturing lamdbas + THEN( + "There should be an entry for the lambda that returns a primitive " + "and " + "the method it references should have an appropriate descriptor") + { + std::string descriptor = "()I"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor, 1); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + + const typet primitive_type = java_int_type(); + + fieldref_exprt fieldref{// NOLINT(whitespace/braces) + primitive_type, + "staticPrimitive", + "java::StaticLambdas"}; + + std::vector + expected_instructions{{"getstatic", {fieldref}}, {"ireturn", {}}}; + + require_parse_tree::require_instructions_match_expectation( + expected_instructions, lambda_method.instructions); + } + THEN( + "There should be an entry for the lambda that returns a reference " + "type " + "and the method it references should have an appropriate " + "descriptor") + { + std::string descriptor = "()Ljava/lang/Object;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor, 1); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + + const reference_typet dummy_generic_reference_type = + java_reference_type(symbol_typet{"java::java.lang.Object"}); + + fieldref_exprt fieldref{dummy_generic_reference_type, + "staticReference", + "java::StaticLambdas"}; + + std::vector + expected_instructions{{"getstatic", {fieldref}}, {"areturn", {}}}; + + require_parse_tree::require_instructions_match_expectation( + expected_instructions, lambda_method.instructions); + } + THEN( + "There should be an entry for the lambda that returns a " + "specialised " + "generic type and the method it references should have an " + "appropriate " + "descriptor") + { + std::string descriptor = "()LDummyGeneric;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor, 1); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const java_bytecode_parse_treet::methodt &lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + + const reference_typet dummy_generic_reference_type = + java_reference_type(symbol_typet{"java::DummyGeneric"}); + + fieldref_exprt fieldref{dummy_generic_reference_type, + "staticSpecalisedGeneric", + "java::StaticLambdas"}; + + std::vector + expected_instructions{{"getstatic", {fieldref}}, {"areturn", {}}}; + + require_parse_tree::require_instructions_match_expectation( + expected_instructions, lambda_method.instructions); + } } } - } + }); } SCENARIO( "lambda_method_handle_map with local lambdas", "[core][java_bytecode][java_bytecode_parse_lambda_method_handle]") { - null_message_handlert message_handler; - GIVEN("A method with local lambdas") - { - java_bytecode_parse_treet parse_tree; - java_bytecode_parse( - "./java_bytecode/java_bytecode_parser/lambda_examples/" - "LocalLambdas.class", - parse_tree, - message_handler); - WHEN("Parsing that class") - { - REQUIRE(parse_tree.loading_successful); - const java_bytecode_parse_treet::classt parsed_class = - parse_tree.parsed_class; - REQUIRE(parsed_class.attribute_bootstrapmethods_read); - REQUIRE(parsed_class.lambda_method_handle_map.size() == 12); - - // Simple lambdas - THEN( - "There should be an entry for the lambda that has no parameters or " - "returns and the method it references should have an appropriate " - "descriptor") - { - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, "()V"); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == "()V"); - } - - // Parameter lambdas - THEN( - "There should be an entry for the lambda that takes parameters and the " - "method it references should have an appropriate descriptor") - { - std::string descriptor = "(ILjava/lang/Object;LDummyGeneric;)V"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - } - THEN( - "There should be an entry for the lambda that takes array parameters " - "and the method it references should have an appropriate descriptor") - { - std::string descriptor = "([I[Ljava/lang/Object;[LDummyGeneric;)V"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - } - - // Return lambdas - THEN( - "There should be an entry for the lambda that returns a primitive and " - "the method it references should have an appropriate descriptor") - { - std::string descriptor = "()I"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - } - THEN( - "There should be an entry for the lambda that returns a reference type " - "and the method it references should have an appropriate descriptor") - { - std::string descriptor = "()Ljava/lang/Object;"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - } - THEN( - "There should be an entry for the lambda that returns a specialised " - "generic type and the method it references should have an appropriate " - "descriptor") - { - std::string descriptor = "()LDummyGeneric;"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - } - - // Array returning lambdas - THEN( - "There should be an entry for the lambda that returns an array of " - "primitives and the method it references should have an appropriate " - "descriptor") - { - std::string descriptor = "()[I"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - } - THEN( - "There should be an entry for the lambda that returns an array of " - "reference types and the method it references should have an " - "appropriate descriptor") - { - std::string descriptor = "()[Ljava/lang/Object;"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - } - THEN( - "There should be an entry for the lambda that returns an array of " - "specialised generic types and the method it references should have an " - "appropriate descriptor") - { - std::string descriptor = "()[LDummyGeneric;"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - } - - // Capturing lamdbas - THEN( - "There should be an entry for the lambda that returns a primitive " - "local variable and the method it references should have an " - "appropriate descriptor") - { - std::string descriptor = "()I"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor, 1); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - // Note here the descriptor of the implementation is different - the - // implementation requries the input to be passed in - REQUIRE(id2string(lambda_method.descriptor) == "(I)I"); - - std::vector - expected_instructions{{"iload_0", {}}, {"ireturn", {}}}; - - require_parse_tree::require_instructions_match_expectation( - expected_instructions, lambda_method.instructions); - } - THEN( - "There should be an entry for the lambda that returns a reference type " - "local variable and the method it references should have an " - "appropriate descriptor") - { - // Since it is a local variable, the corresponding method takes the - // captured variable as an input - std::string descriptor = "()Ljava/lang/Object;"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor, 1); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE( - id2string(lambda_method.descriptor) == - "(Ljava/lang/Object;)Ljava/lang/Object;"); - - std::vector - expected_instructions{{"aload_0", {}}, {"areturn", {}}}; - - require_parse_tree::require_instructions_match_expectation( - expected_instructions, lambda_method.instructions); - } - THEN( - "There should be an entry for the lambda that returns a specialised " - "generic type local variable and the method it references should have " - "an appropriate descriptor") - { - // Since it is a local variable, the corresponding method takes the - // captured variable as an input - std::string descriptor = "()LDummyGeneric;"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor, 1); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const java_bytecode_parse_treet::methodt &lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE( - id2string(lambda_method.descriptor) == - "(LDummyGeneric;)LDummyGeneric;"); - - // since just returning the parameter, nothing to put on the stack - std::vector - expected_instructions{{"aload_0", {}}, {"areturn", {}}}; - - require_parse_tree::require_instructions_match_expectation( - expected_instructions, lambda_method.instructions); - } - } - } + run_test_with_compilers( + [](const std::string &compiler) { // NOLINT(whitespace/braces) + null_message_handlert message_handler; + GIVEN("A method with local lambdas from " + compiler + " compiler.") + { + java_bytecode_parse_treet parse_tree; + java_bytecode_parse( + "./java_bytecode/java_bytecode_parser/lambda_examples/" + compiler + + "_classes/LocalLambdas.class", + parse_tree, + message_handler); + WHEN("Parsing that class") + { + REQUIRE(parse_tree.loading_successful); + const java_bytecode_parse_treet::classt parsed_class = + parse_tree.parsed_class; + REQUIRE(parsed_class.attribute_bootstrapmethods_read); + REQUIRE(parsed_class.lambda_method_handle_map.size() == 12); + + // Simple lambdas + THEN( + "There should be an entry for the lambda that has no parameters or " + "returns and the method it references should have an appropriate " + "descriptor") + { + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, "()V"); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = require_parse_tree::require_method( + parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == "()V"); + } + + // Parameter lambdas + THEN( + "There should be an entry for the lambda that takes parameters and " + "the " + "method it references should have an appropriate descriptor") + { + std::string descriptor = "(ILjava/lang/Object;LDummyGeneric;)V"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = require_parse_tree::require_method( + parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that takes array " + "parameters " + "and the method it references should have an appropriate " + "descriptor") + { + std::string descriptor = "([I[Ljava/lang/Object;[LDummyGeneric;)V"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = require_parse_tree::require_method( + parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + + // Return lambdas + THEN( + "There should be an entry for the lambda that returns a primitive " + "and " + "the method it references should have an appropriate descriptor") + { + std::string descriptor = "()I"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = require_parse_tree::require_method( + parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that returns a reference " + "type " + "and the method it references should have an appropriate " + "descriptor") + { + std::string descriptor = "()Ljava/lang/Object;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = require_parse_tree::require_method( + parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that returns a " + "specialised " + "generic type and the method it references should have an " + "appropriate " + "descriptor") + { + std::string descriptor = "()LDummyGeneric;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = require_parse_tree::require_method( + parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + + // Array returning lambdas + THEN( + "There should be an entry for the lambda that returns an array of " + "primitives and the method it references should have an " + "appropriate " + "descriptor") + { + std::string descriptor = "()[I"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = require_parse_tree::require_method( + parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that returns an array of " + "reference types and the method it references should have an " + "appropriate descriptor") + { + std::string descriptor = "()[Ljava/lang/Object;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = require_parse_tree::require_method( + parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that returns an array of " + "specialised generic types and the method it references should " + "have an " + "appropriate descriptor") + { + std::string descriptor = "()[LDummyGeneric;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = require_parse_tree::require_method( + parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + + // Capturing lamdbas + THEN( + "There should be an entry for the lambda that returns a primitive " + "local variable and the method it references should have an " + "appropriate descriptor") + { + std::string descriptor = "()I"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor, 1); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = require_parse_tree::require_method( + parsed_class, lambda_impl_name); + // Note here the descriptor of the implementation is different - the + // implementation requries the input to be passed in + REQUIRE(id2string(lambda_method.descriptor) == "(I)I"); + + std::vector + expected_instructions{{"iload_0", {}}, {"ireturn", {}}}; + + require_parse_tree::require_instructions_match_expectation( + expected_instructions, lambda_method.instructions); + } + THEN( + "There should be an entry for the lambda that returns a reference " + "type " + "local variable and the method it references should have an " + "appropriate descriptor") + { + // Since it is a local variable, the corresponding method takes the + // captured variable as an input + std::string descriptor = "()Ljava/lang/Object;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor, 1); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = require_parse_tree::require_method( + parsed_class, lambda_impl_name); + REQUIRE( + id2string(lambda_method.descriptor) == + "(Ljava/lang/Object;)Ljava/lang/Object;"); + + std::vector + expected_instructions{{"aload_0", {}}, {"areturn", {}}}; + + require_parse_tree::require_instructions_match_expectation( + expected_instructions, lambda_method.instructions); + } + THEN( + "There should be an entry for the lambda that returns a " + "specialised " + "generic type local variable and the method it references should " + "have " + "an appropriate descriptor") + { + // Since it is a local variable, the corresponding method takes the + // captured variable as an input + std::string descriptor = "()LDummyGeneric;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor, 1); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const java_bytecode_parse_treet::methodt &lambda_method = + require_parse_tree::require_method( + parsed_class, lambda_impl_name); + REQUIRE( + id2string(lambda_method.descriptor) == + "(LDummyGeneric;)LDummyGeneric;"); + + // since just returning the parameter, nothing to put on the stack + std::vector + expected_instructions{{"aload_0", {}}, {"areturn", {}}}; + + require_parse_tree::require_instructions_match_expectation( + expected_instructions, lambda_method.instructions); + } + } + } + }); } SCENARIO( "lambda_method_handle_map with member lambdas", "[core][java_bytecode][java_bytecode_parse_lambda_method_handle]") { - null_message_handlert message_handler; - GIVEN("A class that has lambdas as member variables") - { - java_bytecode_parse_treet parse_tree; - java_bytecode_parse( - "./java_bytecode/java_bytecode_parser/lambda_examples/" - "MemberLambdas.class", - parse_tree, - message_handler); - WHEN("Parsing that class") - { - REQUIRE(parse_tree.loading_successful); - const java_bytecode_parse_treet::classt parsed_class = - parse_tree.parsed_class; - REQUIRE(parsed_class.attribute_bootstrapmethods_read); - REQUIRE(parsed_class.lambda_method_handle_map.size() == 12); - - // Simple lambdas - THEN( - "There should be an entry for the lambda that has no parameters or " - "returns and the method it references should have an appropriate " - "descriptor") - { - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, "()V"); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == "()V"); - } - - // Parameter lambdas - THEN( - "There should be an entry for the lambda that takes parameters and the " - "method it references should have an appropriate descriptor") - { - std::string descriptor = "(ILjava/lang/Object;LDummyGeneric;)V"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - } - THEN( - "There should be an entry for the lambda that takes array parameters " - "and the method it references should have an appropriate descriptor") - { - std::string descriptor = "([I[Ljava/lang/Object;[LDummyGeneric;)V"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - } - - // Return lambdas - THEN( - "There should be an entry for the lambda that returns a primitive and " - "the method it references should have an appropriate descriptor") - { - std::string descriptor = "()I"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - } - THEN( - "There should be an entry for the lambda that returns a reference type " - "and the method it references should have an appropriate descriptor") - { - std::string descriptor = "()Ljava/lang/Object;"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - } - THEN( - "There should be an entry for the lambda that returns a specialised " - "generic type and the method it references should have an appropriate " - "descriptor") - { - std::string descriptor = "()LDummyGeneric;"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - } - - // Array returning lambdas - THEN( - "There should be an entry for the lambda that returns an array of " - "primitives and the method it references should have an appropriate " - "descriptor") - { - std::string descriptor = "()[I"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - } - THEN( - "There should be an entry for the lambda that returns an array of " - "reference types and the method it references should have an " - "appropriate descriptor") - { - std::string descriptor = "()[Ljava/lang/Object;"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - } - THEN( - "There should be an entry for the lambda that returns an array of " - "specialised generic types and the method it references should have an " - "appropriate descriptor") - { - std::string descriptor = "()[LDummyGeneric;"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == descriptor); - } - - // Capturing lamdbas - THEN( - "There should be an entry for the lambda that returns a primitive " - "local variable and the method it references should have an " - "appropriate descriptor") - { - std::string descriptor = "()I"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor, 1); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - // Note here the descriptor of the implementation is different - the - // implementation requries the input to be passed in - REQUIRE(id2string(lambda_method.descriptor) == "()I"); - REQUIRE_FALSE(lambda_method.is_static); - - const fieldref_exprt primitive_fieldref{ - java_int_type(), "memberPrimitive", "java::MemberLambdas"}; - - std::vector - expected_instructions{{"aload_0", {}}, // load this of stack - {"getfield", {primitive_fieldref}}, - {"ireturn", {}}}; - - require_parse_tree::require_instructions_match_expectation( - expected_instructions, lambda_method.instructions); - } - THEN( - "There should be an entry for the lambda that returns a reference type " - "local variable and the method it references should have an " - "appropriate descriptor") - { - // Since it is a local variable, the corresponding method takes the - // captured variable as an input - std::string descriptor = "()Ljava/lang/Object;"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor, 1); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == "()Ljava/lang/Object;"); - REQUIRE_FALSE(lambda_method.is_static); - - const reference_typet dummy_generic_reference_type = - java_reference_type(symbol_typet{"java::java.lang.Object"}); - - const fieldref_exprt reference_fieldref{dummy_generic_reference_type, - "memberReference", - "java::MemberLambdas"}; - - std::vector - expected_instructions{{"aload_0", {}}, // load this of stack - {"getfield", {reference_fieldref}}, - {"areturn", {}}}; - - require_parse_tree::require_instructions_match_expectation( - expected_instructions, lambda_method.instructions); - } - THEN( - "There should be an entry for the lambda that returns a specialised " - "generic type local variable and the method it references should have " - "an appropriate descriptor") - { - // Since it is a local variable, the corresponding method takes the - // captured variable as an input - std::string descriptor = "()LDummyGeneric;"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor, 1); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const java_bytecode_parse_treet::methodt &lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == "()LDummyGeneric;"); - REQUIRE_FALSE(lambda_method.is_static); - - const reference_typet dummy_generic_reference_type = - java_reference_type(symbol_typet{"java::DummyGeneric"}); - - const fieldref_exprt generic_reference_fieldref{ - dummy_generic_reference_type, - "memberSpecalisedGeneric", - "java::MemberLambdas"}; - - // since just returning the parameter, nothing to put on the stack - std::vector - expected_instructions{{"aload_0", {}}, // load this of stack - {"getfield", {generic_reference_fieldref}}, - {"areturn", {}}}; - - require_parse_tree::require_instructions_match_expectation( - expected_instructions, lambda_method.instructions); - } - } - } + run_test_with_compilers( + [](const std::string &compiler) { // NOLINT(whitespace/braces) + null_message_handlert message_handler; + GIVEN( + "A class that has lambdas as member variables from " + compiler + + " compiler.") + { + java_bytecode_parse_treet parse_tree; + java_bytecode_parse( + "./java_bytecode/java_bytecode_parser/lambda_examples/" + compiler + + "_classes/MemberLambdas.class", + parse_tree, + message_handler); + WHEN("Parsing that class") + { + REQUIRE(parse_tree.loading_successful); + const java_bytecode_parse_treet::classt parsed_class = + parse_tree.parsed_class; + REQUIRE(parsed_class.attribute_bootstrapmethods_read); + REQUIRE(parsed_class.lambda_method_handle_map.size() == 12); + + // Simple lambdas + THEN( + "There should be an entry for the lambda that has no parameters or " + "returns and the method it references should have an appropriate " + "descriptor") + { + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, "()V"); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = require_parse_tree::require_method( + parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == "()V"); + } + + // Parameter lambdas + THEN( + "There should be an entry for the lambda that takes parameters and " + "the " + "method it references should have an appropriate descriptor") + { + std::string descriptor = "(ILjava/lang/Object;LDummyGeneric;)V"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = require_parse_tree::require_method( + parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that takes array " + "parameters " + "and the method it references should have an appropriate " + "descriptor") + { + std::string descriptor = "([I[Ljava/lang/Object;[LDummyGeneric;)V"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = require_parse_tree::require_method( + parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + + // Return lambdas + THEN( + "There should be an entry for the lambda that returns a primitive " + "and " + "the method it references should have an appropriate descriptor") + { + std::string descriptor = "()I"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = require_parse_tree::require_method( + parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that returns a reference " + "type " + "and the method it references should have an appropriate " + "descriptor") + { + std::string descriptor = "()Ljava/lang/Object;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = require_parse_tree::require_method( + parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that returns a " + "specialised " + "generic type and the method it references should have an " + "appropriate " + "descriptor") + { + std::string descriptor = "()LDummyGeneric;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = require_parse_tree::require_method( + parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + + // Array returning lambdas + THEN( + "There should be an entry for the lambda that returns an array of " + "primitives and the method it references should have an " + "appropriate " + "descriptor") + { + std::string descriptor = "()[I"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = require_parse_tree::require_method( + parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that returns an array of " + "reference types and the method it references should have an " + "appropriate descriptor") + { + std::string descriptor = "()[Ljava/lang/Object;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = require_parse_tree::require_method( + parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that returns an array of " + "specialised generic types and the method it references should " + "have an " + "appropriate descriptor") + { + std::string descriptor = "()[LDummyGeneric;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = require_parse_tree::require_method( + parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + + // Capturing lamdbas + THEN( + "There should be an entry for the lambda that returns a primitive " + "local variable and the method it references should have an " + "appropriate descriptor") + { + std::string descriptor = "()I"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor, 1); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = require_parse_tree::require_method( + parsed_class, lambda_impl_name); + // Note here the descriptor of the implementation is different - the + // implementation requries the input to be passed in + REQUIRE(id2string(lambda_method.descriptor) == "()I"); + REQUIRE_FALSE(lambda_method.is_static); + + const fieldref_exprt primitive_fieldref{// NOLINT(whitespace/braces) + java_int_type(), + "memberPrimitive", + "java::MemberLambdas"}; + + std::vector + expected_instructions{{"aload_0", {}}, // load this of stack + {"getfield", {primitive_fieldref}}, + {"ireturn", {}}}; + + require_parse_tree::require_instructions_match_expectation( + expected_instructions, lambda_method.instructions); + } + THEN( + "There should be an entry for the lambda that returns a reference " + "type " + "local variable and the method it references should have an " + "appropriate descriptor") + { + // Since it is a local variable, the corresponding method takes the + // captured variable as an input + std::string descriptor = "()Ljava/lang/Object;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor, 1); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = require_parse_tree::require_method( + parsed_class, lambda_impl_name); + REQUIRE( + id2string(lambda_method.descriptor) == "()Ljava/lang/Object;"); + REQUIRE_FALSE(lambda_method.is_static); + + const reference_typet dummy_generic_reference_type = + java_reference_type(symbol_typet{"java::java.lang.Object"}); + + // NOLINTNEXTLINE(whitespace/braces) + const fieldref_exprt reference_fieldref{ + dummy_generic_reference_type, + "memberReference", + "java::MemberLambdas"}; + + std::vector + expected_instructions{{"aload_0", {}}, // load this of stack + {"getfield", {reference_fieldref}}, + {"areturn", {}}}; + + require_parse_tree::require_instructions_match_expectation( + expected_instructions, lambda_method.instructions); + } + THEN( + "There should be an entry for the lambda that returns a " + "specialised " + "generic type local variable and the method it references should " + "have " + "an appropriate descriptor") + { + // Since it is a local variable, the corresponding method takes the + // captured variable as an input + std::string descriptor = "()LDummyGeneric;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor, 1); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const java_bytecode_parse_treet::methodt &lambda_method = + require_parse_tree::require_method( + parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == "()LDummyGeneric;"); + REQUIRE_FALSE(lambda_method.is_static); + + const reference_typet dummy_generic_reference_type = + java_reference_type(symbol_typet{"java::DummyGeneric"}); + + // NOLINTNEXTLINE(whitespace/braces) + const fieldref_exprt generic_reference_fieldref{ + dummy_generic_reference_type, + "memberSpecalisedGeneric", + "java::MemberLambdas"}; + + // since just returning the parameter, nothing to put on the stack + std::vector + expected_instructions{{"aload_0", {}}, // load this of stack + {"getfield", {generic_reference_fieldref}}, + {"areturn", {}}}; + + require_parse_tree::require_instructions_match_expectation( + expected_instructions, lambda_method.instructions); + } + } + } + }); } SCENARIO( "lambda_method_handle_map with member lambdas capturing outer class " "variables", "[core][java_bytecode][java_bytecode_parse_lambda_method_handle]") { - null_message_handlert message_handler; - GIVEN( - "An inner class with member variables as lambdas that capture outer " - "variables") - { - java_bytecode_parse_treet parse_tree; - java_bytecode_parse( - "./java_bytecode/java_bytecode_parser/lambda_examples/" - "OuterMemberLambdas$Inner.class", - parse_tree, - message_handler); - WHEN("Parsing that class") - { - REQUIRE(parse_tree.loading_successful); - const java_bytecode_parse_treet::classt parsed_class = - parse_tree.parsed_class; - REQUIRE(parsed_class.attribute_bootstrapmethods_read); - REQUIRE(parsed_class.lambda_method_handle_map.size() == 3); - - // Field ref for getting the outer class - const reference_typet outer_class_reference_type = - java_reference_type(symbol_typet{"java::OuterMemberLambdas"}); - const fieldref_exprt outer_fieldref{ - outer_class_reference_type, "this$0", "java::OuterMemberLambdas$Inner"}; - - THEN( - "There should be an entry for the lambda that returns a primitive " - "local variable and the method it references should have an " - "appropriate descriptor") - { - std::string descriptor = "()I"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - // Note here the descriptor of the implementation is different - the - // implementation requries the input to be passed in - REQUIRE(id2string(lambda_method.descriptor) == "()I"); - REQUIRE_FALSE(lambda_method.is_static); - - const fieldref_exprt primitive_fieldref{ - java_int_type(), "memberPrimitive", "java::OuterMemberLambdas"}; - - std::vector - expected_instructions{{"aload_0", {}}, // load this of stack - {"getfield", {outer_fieldref}}, - {"getfield", {primitive_fieldref}}, - {"ireturn", {}}}; - - require_parse_tree::require_instructions_match_expectation( - expected_instructions, lambda_method.instructions); - } - THEN( - "There should be an entry for the lambda that returns a reference type " - "local variable and the method it references should have an " - "appropriate descriptor") - { - // Since it is a local variable, the corresponding method takes the - // captured variable as an input - std::string descriptor = "()Ljava/lang/Object;"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const auto lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == "()Ljava/lang/Object;"); - REQUIRE_FALSE(lambda_method.is_static); - - const reference_typet dummy_generic_reference_type = - java_reference_type(symbol_typet{"java::java.lang.Object"}); - - const fieldref_exprt reference_fieldref{dummy_generic_reference_type, - "memberReference", - "java::OuterMemberLambdas"}; - - std::vector - expected_instructions{{"aload_0", {}}, // load this of stack - {"getfield", {outer_fieldref}}, - {"getfield", {reference_fieldref}}, - {"areturn", {}}}; - - require_parse_tree::require_instructions_match_expectation( - expected_instructions, lambda_method.instructions); - } - THEN( - "There should be an entry for the lambda that returns a specialised " - "generic type local variable and the method it references should have " - "an appropriate descriptor") - { - // Since it is a local variable, the corresponding method takes the - // captured variable as an input - std::string descriptor = "()LDummyGeneric;"; - const lambda_method_handlet &lambda_entry = - require_parse_tree::require_lambda_entry_for_descriptor( - parsed_class, descriptor); - - const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; - - const java_bytecode_parse_treet::methodt &lambda_method = - require_parse_tree::require_method(parsed_class, lambda_impl_name); - REQUIRE(id2string(lambda_method.descriptor) == "()LDummyGeneric;"); - REQUIRE_FALSE(lambda_method.is_static); - - const reference_typet dummy_generic_reference_type = - java_reference_type(symbol_typet{"java::DummyGeneric"}); - - const fieldref_exprt generic_reference_fieldref{ - dummy_generic_reference_type, - "memberSpecalisedGeneric", - "java::OuterMemberLambdas"}; - - // since just returning the parameter, nothing to put on the stack - std::vector - expected_instructions{{"aload_0", {}}, // load this of stack - {"getfield", {outer_fieldref}}, - {"getfield", {generic_reference_fieldref}}, - {"areturn", {}}}; - - require_parse_tree::require_instructions_match_expectation( - expected_instructions, lambda_method.instructions); - } - } - } + run_test_with_compilers( + [](const std::string &compiler) { // NOLINT(whitespace/braces) + null_message_handlert message_handler; + GIVEN( + "An inner class with member variables as lambdas that capture outer " + "variables from " + + compiler + " compiler.") + { + java_bytecode_parse_treet parse_tree; + java_bytecode_parse( + "./java_bytecode/java_bytecode_parser/lambda_examples/" + compiler + + "_classes/OuterMemberLambdas$Inner.class", + parse_tree, + message_handler); + WHEN("Parsing that class") + { + REQUIRE(parse_tree.loading_successful); + const java_bytecode_parse_treet::classt parsed_class = + parse_tree.parsed_class; + REQUIRE(parsed_class.attribute_bootstrapmethods_read); + REQUIRE(parsed_class.lambda_method_handle_map.size() == 3); + + // Field ref for getting the outer class + const reference_typet outer_class_reference_type = + java_reference_type(symbol_typet{"java::OuterMemberLambdas"}); + const fieldref_exprt outer_fieldref{outer_class_reference_type, + "this$0", + "java::OuterMemberLambdas$Inner"}; + + THEN( + "There should be an entry for the lambda that returns a primitive " + "local variable and the method it references should have an " + "appropriate descriptor") + { + std::string descriptor = "()I"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = require_parse_tree::require_method( + parsed_class, lambda_impl_name); + // Note here the descriptor of the implementation is different - the + // implementation requries the input to be passed in + REQUIRE(id2string(lambda_method.descriptor) == "()I"); + REQUIRE_FALSE(lambda_method.is_static); + + // NOLINTNEXTLINE(whitespace/braces) + const fieldref_exprt primitive_fieldref{ + java_int_type(), "memberPrimitive", "java::OuterMemberLambdas"}; + + std::vector + expected_instructions{{"aload_0", {}}, // load this of stack + {"getfield", {outer_fieldref}}, + {"getfield", {primitive_fieldref}}, + {"ireturn", {}}}; + + require_parse_tree::require_instructions_match_expectation( + expected_instructions, lambda_method.instructions); + } + THEN( + "There should be an entry for the lambda that returns a reference " + "type " + "local variable and the method it references should have an " + "appropriate descriptor") + { + // Since it is a local variable, the corresponding method takes the + // captured variable as an input + std::string descriptor = "()Ljava/lang/Object;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = require_parse_tree::require_method( + parsed_class, lambda_impl_name); + REQUIRE( + id2string(lambda_method.descriptor) == "()Ljava/lang/Object;"); + REQUIRE_FALSE(lambda_method.is_static); + + const reference_typet dummy_generic_reference_type = + java_reference_type(symbol_typet{"java::java.lang.Object"}); + + // NOLINTNEXTLINE(whitespace/braces) + const fieldref_exprt reference_fieldref{ + dummy_generic_reference_type, + "memberReference", + "java::OuterMemberLambdas"}; + + std::vector + expected_instructions{{"aload_0", {}}, // load this of stack + {"getfield", {outer_fieldref}}, + {"getfield", {reference_fieldref}}, + {"areturn", {}}}; + + require_parse_tree::require_instructions_match_expectation( + expected_instructions, lambda_method.instructions); + } + THEN( + "There should be an entry for the lambda that returns a " + "specialised " + "generic type local variable and the method it references should " + "have " + "an appropriate descriptor") + { + // Since it is a local variable, the corresponding method takes the + // captured variable as an input + std::string descriptor = "()LDummyGeneric;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const java_bytecode_parse_treet::methodt &lambda_method = + require_parse_tree::require_method( + parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == "()LDummyGeneric;"); + REQUIRE_FALSE(lambda_method.is_static); + + const reference_typet dummy_generic_reference_type = + java_reference_type(symbol_typet{"java::DummyGeneric"}); + + // NOLINTNEXTLINE(whitespace/braces) + const fieldref_exprt generic_reference_fieldref{ + dummy_generic_reference_type, + "memberSpecalisedGeneric", + "java::OuterMemberLambdas"}; + + // since just returning the parameter, nothing to put on the stack + std::vector + expected_instructions{{"aload_0", {}}, // load this of stack + {"getfield", {outer_fieldref}}, + {"getfield", {generic_reference_fieldref}}, + {"areturn", {}}}; + + require_parse_tree::require_instructions_match_expectation( + expected_instructions, lambda_method.instructions); + } + } + } + }); } diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/ReturningLambdaPrimitive.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/ReturningLambdaPrimitive.class deleted file mode 100644 index 81073aa0155..00000000000 Binary files a/unit/java_bytecode/java_bytecode_parser/lambda_examples/ReturningLambdaPrimitive.class and /dev/null differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/ReturningLambdaPrimitiveArray.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/ReturningLambdaPrimitiveArray.class deleted file mode 100644 index f9f231bc326..00000000000 Binary files a/unit/java_bytecode/java_bytecode_parser/lambda_examples/ReturningLambdaPrimitiveArray.class and /dev/null differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/ReturningLambdaReference.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/ReturningLambdaReference.class deleted file mode 100644 index 549084ee1a6..00000000000 Binary files a/unit/java_bytecode/java_bytecode_parser/lambda_examples/ReturningLambdaReference.class and /dev/null differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/ReturningLambdaReferenceArray.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/ReturningLambdaReferenceArray.class deleted file mode 100644 index 423190ffd3f..00000000000 Binary files a/unit/java_bytecode/java_bytecode_parser/lambda_examples/ReturningLambdaReferenceArray.class and /dev/null differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/ReturningLambdaSpecalisedGeneric.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/ReturningLambdaSpecalisedGeneric.class deleted file mode 100644 index 3a82b5ddbda..00000000000 Binary files a/unit/java_bytecode/java_bytecode_parser/lambda_examples/ReturningLambdaSpecalisedGeneric.class and /dev/null differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/ReturningLambdaSpecalisedGenericArray.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/ReturningLambdaSpecalisedGenericArray.class deleted file mode 100644 index 8e9183ed10b..00000000000 Binary files a/unit/java_bytecode/java_bytecode_parser/lambda_examples/ReturningLambdaSpecalisedGenericArray.class and /dev/null differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/SimpleLambda.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/SimpleLambda.class deleted file mode 100644 index ff1dae8ba4b..00000000000 Binary files a/unit/java_bytecode/java_bytecode_parser/lambda_examples/SimpleLambda.class and /dev/null differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/ArrayParameterLambda.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/ArrayParameterLambda.class new file mode 100644 index 00000000000..00e4747b0aa Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/ArrayParameterLambda.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/DummyGeneric.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/DummyGeneric.class new file mode 100644 index 00000000000..e66d9766fce Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/DummyGeneric.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/LocalLambdas.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/LocalLambdas.class new file mode 100644 index 00000000000..411cb26b993 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/LocalLambdas.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/MemberLambdas.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/MemberLambdas.class new file mode 100644 index 00000000000..fdc38149e65 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/MemberLambdas.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/OuterMemberLambdas$Inner.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/OuterMemberLambdas$Inner.class new file mode 100644 index 00000000000..cc890bb1481 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/OuterMemberLambdas$Inner.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/OuterMemberLambdas.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/OuterMemberLambdas.class new file mode 100644 index 00000000000..a1ae8095097 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/OuterMemberLambdas.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/ParameterLambda.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/ParameterLambda.class new file mode 100644 index 00000000000..e338cb6642d Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/ParameterLambda.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/ReturningLambdaPrimitive.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/ReturningLambdaPrimitive.class new file mode 100644 index 00000000000..c9433aa3004 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/ReturningLambdaPrimitive.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/ReturningLambdaPrimitiveArray.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/ReturningLambdaPrimitiveArray.class new file mode 100644 index 00000000000..332d65646b8 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/ReturningLambdaPrimitiveArray.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/ReturningLambdaReference.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/ReturningLambdaReference.class new file mode 100644 index 00000000000..4a2929c8916 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/ReturningLambdaReference.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/ReturningLambdaReferenceArray.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/ReturningLambdaReferenceArray.class new file mode 100644 index 00000000000..4a01a155148 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/ReturningLambdaReferenceArray.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/ReturningLambdaSpecalisedGeneric.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/ReturningLambdaSpecalisedGeneric.class new file mode 100644 index 00000000000..d7994cd2ddb Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/ReturningLambdaSpecalisedGeneric.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/ReturningLambdaSpecalisedGenericArray.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/ReturningLambdaSpecalisedGenericArray.class new file mode 100644 index 00000000000..ebe151d6240 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/ReturningLambdaSpecalisedGenericArray.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/SimpleLambda.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/SimpleLambda.class new file mode 100644 index 00000000000..82f6ca5758f Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/SimpleLambda.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/StaticLambdas.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/StaticLambdas.class new file mode 100644 index 00000000000..5181e07a228 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/eclipse_classes/StaticLambdas.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/ArrayParameterLambda.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/ArrayParameterLambda.class similarity index 56% rename from unit/java_bytecode/java_bytecode_parser/lambda_examples/ArrayParameterLambda.class rename to unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/ArrayParameterLambda.class index 56886405324..b8f263c9af8 100644 Binary files a/unit/java_bytecode/java_bytecode_parser/lambda_examples/ArrayParameterLambda.class and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/ArrayParameterLambda.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/DummyGeneric.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/DummyGeneric.class similarity index 60% rename from unit/java_bytecode/java_bytecode_parser/lambda_examples/DummyGeneric.class rename to unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/DummyGeneric.class index afbff9f82d1..88831761629 100644 Binary files a/unit/java_bytecode/java_bytecode_parser/lambda_examples/DummyGeneric.class and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/DummyGeneric.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/LocalLambdas.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/LocalLambdas.class similarity index 69% rename from unit/java_bytecode/java_bytecode_parser/lambda_examples/LocalLambdas.class rename to unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/LocalLambdas.class index 28f9f1d7990..53684f85361 100644 Binary files a/unit/java_bytecode/java_bytecode_parser/lambda_examples/LocalLambdas.class and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/LocalLambdas.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/MemberLambdas.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/MemberLambdas.class similarity index 100% rename from unit/java_bytecode/java_bytecode_parser/lambda_examples/MemberLambdas.class rename to unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/MemberLambdas.class diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/OuterMemberLambdas$Inner.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/OuterMemberLambdas$Inner.class similarity index 100% rename from unit/java_bytecode/java_bytecode_parser/lambda_examples/OuterMemberLambdas$Inner.class rename to unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/OuterMemberLambdas$Inner.class diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/OuterMemberLambdas.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/OuterMemberLambdas.class similarity index 100% rename from unit/java_bytecode/java_bytecode_parser/lambda_examples/OuterMemberLambdas.class rename to unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/OuterMemberLambdas.class diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/ParameterLambda.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/ParameterLambda.class similarity index 56% rename from unit/java_bytecode/java_bytecode_parser/lambda_examples/ParameterLambda.class rename to unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/ParameterLambda.class index 9d52eef3aa7..b07856c29dc 100644 Binary files a/unit/java_bytecode/java_bytecode_parser/lambda_examples/ParameterLambda.class and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/ParameterLambda.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/ReturningLambdaPrimitive.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/ReturningLambdaPrimitive.class new file mode 100644 index 00000000000..b069f3568a9 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/ReturningLambdaPrimitive.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/ReturningLambdaPrimitiveArray.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/ReturningLambdaPrimitiveArray.class new file mode 100644 index 00000000000..c23af24c64d Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/ReturningLambdaPrimitiveArray.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/ReturningLambdaReference.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/ReturningLambdaReference.class new file mode 100644 index 00000000000..3aef85d0cb4 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/ReturningLambdaReference.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/ReturningLambdaReferenceArray.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/ReturningLambdaReferenceArray.class new file mode 100644 index 00000000000..54c79ae08f1 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/ReturningLambdaReferenceArray.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/ReturningLambdaSpecalisedGeneric.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/ReturningLambdaSpecalisedGeneric.class new file mode 100644 index 00000000000..3b2cc99144b Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/ReturningLambdaSpecalisedGeneric.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/ReturningLambdaSpecalisedGenericArray.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/ReturningLambdaSpecalisedGenericArray.class new file mode 100644 index 00000000000..d58653a30d1 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/ReturningLambdaSpecalisedGenericArray.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/SimpleLambda.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/SimpleLambda.class new file mode 100644 index 00000000000..db8113dbbc6 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/SimpleLambda.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/StaticLambdas.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/StaticLambdas.class similarity index 100% rename from unit/java_bytecode/java_bytecode_parser/lambda_examples/StaticLambdas.class rename to unit/java_bytecode/java_bytecode_parser/lambda_examples/openjdk_8_classes/StaticLambdas.class diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/ArrayParameterLambda.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/ArrayParameterLambda.class new file mode 100644 index 00000000000..b8f263c9af8 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/ArrayParameterLambda.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/DummyGeneric.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/DummyGeneric.class new file mode 100644 index 00000000000..88831761629 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/DummyGeneric.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/LocalLambdas.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/LocalLambdas.class new file mode 100644 index 00000000000..53684f85361 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/LocalLambdas.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/MemberLambdas.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/MemberLambdas.class new file mode 100644 index 00000000000..04984e52720 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/MemberLambdas.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/OuterMemberLambdas$Inner.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/OuterMemberLambdas$Inner.class new file mode 100644 index 00000000000..19b99a98190 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/OuterMemberLambdas$Inner.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/OuterMemberLambdas.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/OuterMemberLambdas.class new file mode 100644 index 00000000000..da380075695 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/OuterMemberLambdas.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/ParameterLambda.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/ParameterLambda.class new file mode 100644 index 00000000000..b07856c29dc Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/ParameterLambda.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/ReturningLambdaPrimitive.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/ReturningLambdaPrimitive.class new file mode 100644 index 00000000000..b069f3568a9 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/ReturningLambdaPrimitive.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/ReturningLambdaPrimitiveArray.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/ReturningLambdaPrimitiveArray.class new file mode 100644 index 00000000000..c23af24c64d Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/ReturningLambdaPrimitiveArray.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/ReturningLambdaReference.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/ReturningLambdaReference.class new file mode 100644 index 00000000000..3aef85d0cb4 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/ReturningLambdaReference.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/ReturningLambdaReferenceArray.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/ReturningLambdaReferenceArray.class new file mode 100644 index 00000000000..54c79ae08f1 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/ReturningLambdaReferenceArray.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/ReturningLambdaSpecalisedGeneric.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/ReturningLambdaSpecalisedGeneric.class new file mode 100644 index 00000000000..3b2cc99144b Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/ReturningLambdaSpecalisedGeneric.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/ReturningLambdaSpecalisedGenericArray.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/ReturningLambdaSpecalisedGenericArray.class new file mode 100644 index 00000000000..d58653a30d1 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/ReturningLambdaSpecalisedGenericArray.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/SimpleLambda.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/SimpleLambda.class new file mode 100644 index 00000000000..db8113dbbc6 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/SimpleLambda.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/StaticLambdas.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/StaticLambdas.class new file mode 100644 index 00000000000..a5d959f5781 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_8_classes/StaticLambdas.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/ArrayParameterLambda.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/ArrayParameterLambda.class new file mode 100644 index 00000000000..ffb673a5db6 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/ArrayParameterLambda.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/DummyGeneric.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/DummyGeneric.class new file mode 100644 index 00000000000..e1b3e6b4764 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/DummyGeneric.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/LocalLambdas.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/LocalLambdas.class new file mode 100644 index 00000000000..e1699404588 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/LocalLambdas.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/MemberLambdas.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/MemberLambdas.class new file mode 100644 index 00000000000..3467c00a80a Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/MemberLambdas.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/OuterMemberLambdas$Inner.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/OuterMemberLambdas$Inner.class new file mode 100644 index 00000000000..5342e84c278 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/OuterMemberLambdas$Inner.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/OuterMemberLambdas.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/OuterMemberLambdas.class new file mode 100644 index 00000000000..55c7bac2548 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/OuterMemberLambdas.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/ParameterLambda.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/ParameterLambda.class new file mode 100644 index 00000000000..aa02bb1dea1 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/ParameterLambda.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/ReturningLambdaPrimitive.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/ReturningLambdaPrimitive.class new file mode 100644 index 00000000000..3a13a75eabe Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/ReturningLambdaPrimitive.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/ReturningLambdaPrimitiveArray.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/ReturningLambdaPrimitiveArray.class new file mode 100644 index 00000000000..b560ac34ad8 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/ReturningLambdaPrimitiveArray.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/ReturningLambdaReference.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/ReturningLambdaReference.class new file mode 100644 index 00000000000..afad7d8c0f6 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/ReturningLambdaReference.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/ReturningLambdaReferenceArray.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/ReturningLambdaReferenceArray.class new file mode 100644 index 00000000000..698da113a00 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/ReturningLambdaReferenceArray.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/ReturningLambdaSpecalisedGeneric.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/ReturningLambdaSpecalisedGeneric.class new file mode 100644 index 00000000000..f86df394ef6 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/ReturningLambdaSpecalisedGeneric.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/ReturningLambdaSpecalisedGenericArray.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/ReturningLambdaSpecalisedGenericArray.class new file mode 100644 index 00000000000..b39b5f987bf Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/ReturningLambdaSpecalisedGenericArray.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/SimpleLambda.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/SimpleLambda.class new file mode 100644 index 00000000000..a7af9c4cfe3 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/SimpleLambda.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/StaticLambdas.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/StaticLambdas.class new file mode 100644 index 00000000000..73005861fc5 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parser/lambda_examples/oracle_9_classes/StaticLambdas.class differ diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/readme.md b/unit/java_bytecode/java_bytecode_parser/lambda_examples/readme.md new file mode 100644 index 00000000000..cdbabfb9947 --- /dev/null +++ b/unit/java_bytecode/java_bytecode_parser/lambda_examples/readme.md @@ -0,0 +1,45 @@ +Each sub directory inside this one contains class files which have been compiled +with specific java compilers. The procedure taken to produce these files is as +follows - + 1. Install the java compilers of interest. Skip this step if you already have + them installed. + 2. Use `sudo update-alternatives --config javac` to configure your system to + use the compiler of interest. + 3. Use `javac -version` to confirm the desired compilier has been correctly + configured. The version information for each compiler is as follows - + * openJdk 8 - 1.8.0_151 + * oracle java 8 - 1.8.0_161 + * oracle java 9 - 9.0.4 + 4. Compile the `.java` files using `javac -g ./*.java`. The `-g` flag switches + on debugging output, which we require. + 5. The `.class` files should have been written to the current directory. They + can now be moved into the appropriate sub directory. For example - + `mkdir my_compiler_classes && mv ./*.class ./my_compiler_classes` + 6. If this is a new compiler, add it to the test, by adding the compilier to + the list in the `run_test_with_compilers` function in + `java_bytecode_parse_lambda_method_table.cpp`. + 7. Repeat steps 2 through 6 for each additional compiler. + +The procedure for compiling with Eclipse is different. Installing the java +Eclipse IDE does not setup a version of javac command. So to produce the class +files for Eclipse, the procedure is as follows - + 1. Open Eclipse IDE. + 2. Create new project. + 3. Import the `.java` files into the project, using the "General->File System" + import source. + 4. The `.java` files should now show in the src folder of the package explorer. + The IDE will have automatically compiled these, because it needs the `.class` + files for its autocomplete/syntax highlighting/tool tip functionality. + 5. The auto compiled files should be in a `bin` sub directory of the project + directory. These can be copied into the appropriate sub directory of the unit + test using your command line shell or file browser of choice. Note that the + `bin` directory and the class files are not shown in the Eclipse IDE. + +The Eclipse java compiler is distibuted as a .jar file, which can be run from +the command line. For detailed information see here [https://help.eclipse.org/neon/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Ftasks%2Ftask-using_batch_compiler.htm] +For example the eclipse compiler version could be extracted with `java -jar +./ecj-4.7.2.jar -version`. However this is redundant as the version number is +usually in the file name of the jar file already. The java files can be compiled +with the eclipse compiler through the command line with `java -jar +./ecj-4.7.2.jar -g -1.8 ./*.java`. The additional `-1.8` is required to use java +compilance level 1.8, which is required for lambdas.