Skip to content

[TG-1633] Fix for inner generic types have incorrect type identifier #1698

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/java_bytecode/java_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ std::string erase_type_arguments(const std::string &src)
class_name.erase(f_pos, e_pos - f_pos + 1);

// Search the remainder of the string for generic signature
f_pos = class_name.find('<', e_pos + 1);
f_pos = class_name.find('<', f_pos + 1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might consider writing a unit test for this specific function.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, the function only takes a string as an input so this should be easy to do.

}
return class_name;
}
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ class TwoParamInnerClass<K, L>
TwoParamInnerClass<Interface_Implementation,T> field9;
TwoParamInnerClass<T,T> field10;

GenericInnerClass<GenericClassWithGenericInnerClasses<Integer>>.DoublyNestedInnerGenericClass<T> field11;

void method(InnerClass input)
{

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,47 @@ SCENARIO(
{require_type::type_argument_kindt::Var, class_prefix + "::T"}});
}
}

THEN(
"The field11 component should be a pointer to "
"GenericClassWithGenericInnerClasses$"
"GenericInnerClass$DoublyNestedInnerGenericClass")
{
const struct_union_typet::componentt &field_component =
require_type::require_component(java_generic_class, "field11");

// Declaration of field11 to be tested -
// GenericInnerClass<GenericClassWithGenericInnerClasses<Integer>>.
// DoublyNestedInnerGenericClass<T> field11;

require_type::require_pointer(
field_component.type(),
symbol_typet(
class_prefix + "$GenericInnerClass$DoublyNestedInnerGenericClass"));

THEN("The pointer should be GenericClassWithGenericInnerClasses")
{
const java_generic_typet &generic_field =
require_type::require_java_generic_type(
field_component.type(),
{{require_type::type_argument_kindt::Var,
"java::GenericClassWithGenericInnerClasses::T"},
{require_type::type_argument_kindt::Inst,
"java::GenericClassWithGenericInnerClasses"},
{require_type::type_argument_kindt::Var,
"java::GenericClassWithGenericInnerClasses::T"}});

THEN("Test nested Integer parameter.")
{
const typet &nested_generic_field =
generic_field.generic_type_arguments().at(1);
require_type::require_java_generic_type(
nested_generic_field,
{{require_type::type_argument_kindt::Inst,
"java::java.lang.Integer"}});
}
}
}
}
}

Expand Down
68 changes: 68 additions & 0 deletions unit/java_bytecode/java_types/erase_type_arguments.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*******************************************************************\

Module: Unit tests for java_types

Author: DiffBlue Limited. All rights reserved.

\*******************************************************************/

#include <testing-utils/catch.hpp>
#include <java_types.h>

SCENARIO("erase_type_arguments", "[core][java_types]")
{
THEN(
"erase_type_arguments should leave strings with no type arguments "
"unaltered.")
{
const std::string testInput1 = "testString1";

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit - no need for a variable, give it as an input to the function directly as in the rest of the file.

REQUIRE(erase_type_arguments(testInput1) == testInput1);
}

THEN("erase_type_arguments should remove a simple type argument")
{
REQUIRE(
erase_type_arguments("testClassName<testTypeArgument>") ==
"testClassName");
}

THEN(
"erase_type_arguments should remove multiple type arguments in cases "
"of nested classes")
{
REQUIRE(
erase_type_arguments(
"outerClass<testTypeArgument1>$"
"innerClass<testTypeArgument2>") == "outerClass$innerClass");
}

THEN(
"erase_type_arguments should remove type arguments which contain nested "
"type arguments")
{
REQUIRE(
erase_type_arguments(
"outerClass<testTypeArgument1<testTypeArgument2>>") == "outerClass");
}

THEN(
"erase_type_arguments should remove multiple type arguments which contain "
"nested type arguments in cases of nested classes")
{
REQUIRE(
erase_type_arguments(
"outerClass<testTypeArgument1<testTypeArgument2>>$"
"innerClass<testTypeArgument3<testTypeArgument4>>") ==
"outerClass$innerClass");
}

THEN(
"erase_type_arguments should throw an error if a type argument is "
"unterminated")
{
REQUIRE_THROWS_AS(
erase_type_arguments(
"testClassName<testTypeArgument1<testTypeArgument2>"),
unsupported_java_class_signature_exceptiont &);
}
}