Skip to content

Commit a4d1891

Browse files
author
Daniel Kroening
authored
Merge pull request diffblue#2160 from diffblue/fix-java-constructor-pretty-name
Improve pretty name of Java methods
2 parents b9db37d + 6b064b3 commit a4d1891

File tree

5 files changed

+106
-19
lines changed

5 files changed

+106
-19
lines changed

regression/cbmc-java/package_friendly1/test.desc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
CORE symex-driven-lazy-loading-expected-failure
22
main.class
33
package_friendly1.class package_friendly2.class --show-goto-functions
4-
^main[.]main[\(][\)].*$
4+
^main[.]main[\(].*[\)].*$
55
^package_friendly2[.]operation2[\(][\)].*$
66
^EXIT=0$
77
^SIGNAL=0$

src/java_bytecode/java_bytecode_convert_class.cpp

+9-1
Original file line numberDiff line numberDiff line change
@@ -377,9 +377,17 @@ void java_bytecode_convert_classt::convert(
377377
if(!c.annotations.empty())
378378
convert_annotations(c.annotations, class_type.get_annotations());
379379

380+
// the base name is the name of the class without the package
381+
const irep_idt base_name = [](const std::string &full_name) {
382+
const size_t last_dot = full_name.find_last_of('.');
383+
return last_dot == std::string::npos
384+
? full_name
385+
: std::string(full_name, last_dot + 1, std::string::npos);
386+
}(id2string(c.name));
387+
380388
// produce class symbol
381389
symbolt new_symbol;
382-
new_symbol.base_name=c.name;
390+
new_symbol.base_name = base_name;
383391
new_symbol.pretty_name=c.name;
384392
new_symbol.name=qualified_classname;
385393
class_type.set(ID_name, new_symbol.name);

src/java_bytecode/java_bytecode_convert_method.cpp

+27-15
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ void java_bytecode_convert_method_lazy(
354354
method_symbol.mode=ID_java;
355355
method_symbol.location=m.source_location;
356356
method_symbol.location.set_function(method_identifier);
357+
357358
if(m.is_public)
358359
member_type.set_access(ID_public);
359360
else if(m.is_protected)
@@ -363,18 +364,6 @@ void java_bytecode_convert_method_lazy(
363364
else
364365
member_type.set_access(ID_default);
365366

366-
if(is_constructor(method_symbol.base_name))
367-
{
368-
method_symbol.pretty_name=
369-
id2string(class_symbol.pretty_name)+"."+
370-
id2string(class_symbol.base_name)+"()";
371-
member_type.set_is_constructor();
372-
}
373-
else
374-
method_symbol.pretty_name=
375-
id2string(class_symbol.pretty_name)+"."+
376-
id2string(m.base_name)+"()";
377-
378367
// do we need to add 'this' as a parameter?
379368
if(!m.is_static)
380369
{
@@ -387,6 +376,24 @@ void java_bytecode_convert_method_lazy(
387376
parameters.insert(parameters.begin(), this_p);
388377
}
389378

379+
const std::string signature_string = pretty_signature(member_type);
380+
381+
if(is_constructor(method_symbol.base_name))
382+
{
383+
// we use full.class_name(...) as pretty name
384+
// for constructors -- the idea is that they have
385+
// an empty declarator.
386+
method_symbol.pretty_name=
387+
id2string(class_symbol.pretty_name) + signature_string;
388+
389+
member_type.set_is_constructor();
390+
}
391+
else
392+
{
393+
method_symbol.pretty_name = id2string(class_symbol.pretty_name) + "." +
394+
id2string(m.base_name) + signature_string;
395+
}
396+
390397
// Load annotations
391398
if(!m.annotations.empty())
392399
{
@@ -559,22 +566,27 @@ void java_bytecode_convert_methodt::convert(
559566
method_symbol.location=m.source_location;
560567
method_symbol.location.set_function(method_identifier);
561568

569+
const std::string signature_string = pretty_signature(code_type);
570+
562571
// Set up the pretty name for the method entry in the symbol table.
563572
// The pretty name of a constructor includes the base name of the class
564573
// instead of the internal method name "<init>". For regular methods, it's
565574
// just the base name of the method.
566575
if(is_constructor(method_symbol.base_name))
567576
{
568-
method_symbol.pretty_name = id2string(class_symbol.pretty_name) + "." +
569-
id2string(class_symbol.base_name) + "()";
577+
// we use full.class_name(...) as pretty name
578+
// for constructors -- the idea is that they have
579+
// an empty declarator.
580+
method_symbol.pretty_name =
581+
id2string(class_symbol.pretty_name) + signature_string;
570582
INVARIANT(
571583
code_type.get_is_constructor(),
572584
"Member type should have already been marked as a constructor");
573585
}
574586
else
575587
{
576588
method_symbol.pretty_name = id2string(class_symbol.pretty_name) + "." +
577-
id2string(method_symbol.base_name) + "()";
589+
id2string(m.base_name) + signature_string;
578590
}
579591

580592
method_symbol.type = code_type;

src/java_bytecode/java_types.cpp

+61
Original file line numberDiff line numberDiff line change
@@ -884,3 +884,64 @@ optionalt<size_t> java_generic_symbol_typet::generic_type_index(
884884
}
885885
return {};
886886
}
887+
888+
std::string pretty_java_type(const typet &type)
889+
{
890+
if(type == java_int_type())
891+
return "int";
892+
else if(type == java_long_type())
893+
return "long";
894+
else if(type == java_short_type())
895+
return "short";
896+
else if(type == java_byte_type())
897+
return "byte";
898+
else if(type == java_char_type())
899+
return "char";
900+
else if(type == java_float_type())
901+
return "float";
902+
else if(type == java_double_type())
903+
return "double";
904+
else if(type == java_boolean_type())
905+
return "boolean";
906+
else if(type == java_byte_type())
907+
return "byte";
908+
else if(is_reference(type))
909+
{
910+
if(type.subtype().id() == ID_symbol)
911+
{
912+
const auto &symbol_type = to_symbol_type(type.subtype());
913+
const irep_idt &id = symbol_type.get_identifier();
914+
if(is_java_array_tag(id))
915+
return pretty_java_type(java_array_element_type(symbol_type)) + "[]";
916+
else
917+
return id2string(strip_java_namespace_prefix(id));
918+
}
919+
else
920+
return "?";
921+
}
922+
else
923+
return "?";
924+
}
925+
926+
std::string pretty_signature(const code_typet &code_type)
927+
{
928+
std::ostringstream result;
929+
result << '(';
930+
931+
bool first = true;
932+
for(const auto p : code_type.parameters())
933+
{
934+
if(p.get_this())
935+
continue;
936+
937+
if(first)
938+
first = false;
939+
else
940+
result << ", ";
941+
942+
result << pretty_java_type(p.type());
943+
}
944+
945+
result << ')';
946+
return result.str();
947+
}

src/java_bytecode/java_types.h

+8-2
Original file line numberDiff line numberDiff line change
@@ -626,12 +626,18 @@ inline java_generic_symbol_typet &to_java_generic_symbol_type(typet &type)
626626
/// the type to be parsed normally, for example
627627
/// `java.util.HashSet<java.lang.Integer>` will be turned into
628628
/// `java.util.HashSet`
629-
std::string erase_type_arguments(const std::string &src);
629+
std::string erase_type_arguments(const std::string &);
630630
/// Returns the full class name, skipping over the generics. This turns any of
631631
/// these:
632632
/// 1. Signature: Lcom/package/OuterClass<TT;>.Inner;
633633
/// 2. Descriptor: Lcom.pacakge.OuterClass$Inner;
634634
/// into `com.package.OuterClass.Inner`
635-
std::string gather_full_class_name(const std::string &src);
635+
std::string gather_full_class_name(const std::string &);
636+
637+
// turn java type into string
638+
std::string pretty_java_type(const typet &);
639+
640+
// pretty signature for methods
641+
std::string pretty_signature(const code_typet &);
636642

637643
#endif // CPROVER_JAVA_BYTECODE_JAVA_TYPES_H

0 commit comments

Comments
 (0)