Skip to content

Commit

Permalink
Support DCG components
Browse files Browse the repository at this point in the history
Summary: DCG components are just getters with `component` in the name. Patch their return when the field they're getting is annotated

Reviewed By: thezhangwei

Differential Revision: D67367181

fbshipit-source-id: 2e66dd49fd0be9f04a21d08a22228ac62f632484
  • Loading branch information
itang00 authored and facebook-github-bot committed Jan 6, 2025
1 parent b6b5ca3 commit 9e69700
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 10 deletions.
38 changes: 28 additions & 10 deletions opt/typedef-anno-checker/TypedefAnnoCheckerPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ constexpr const char* OBJ_REF_CLS = "Lkotlin/jvm/internal/Ref$ObjectRef;";
constexpr const char* OBJ_REF_FIELD =
"Lkotlin/jvm/internal/Ref$ObjectRef;.element:Ljava/lang/Object;";

constexpr const char* DATA_CLASS_COMPONENT = "component";

namespace {

bool is_int(const type_inference::TypeEnvironment& env, reg_t reg) {
Expand Down Expand Up @@ -465,23 +467,28 @@ void patch_return_anno_from_get(type_inference::TypeInference& inference,
opcode::is_an_sget(insn->opcode()));
auto name = caller->get_simple_deobfuscated_name();
auto last_dollar = name.find('$');
if (last_dollar == std::string::npos) {
return;
}
last_dollar++;
if (!(last_dollar < name.size() && name[last_dollar] >= '0' &&
name[last_dollar] <= '9')) {
return;

// the caller methods are either data class components, named "componentX",
// or they're Java field accessors, which have the pattern access$XXX, where
// X is an integer
if (!boost::starts_with(caller->get_simple_deobfuscated_name(),
DATA_CLASS_COMPONENT)) {
if (last_dollar == std::string::npos) {
return;
}
last_dollar++;
if (!(last_dollar < name.size() && name[last_dollar] >= '0' &&
name[last_dollar] <= '9')) {
return;
}
}
auto field_ref = insn->get_field();
auto field_anno = type_inference::get_typedef_anno_from_member(
field_ref, inference.get_annotations());

if (field_anno != boost::none) {
// Patch missing return annotations from accessed fields
auto res = caller->attach_annotation_set(std::make_unique<DexAnnotationSet>(
*field_ref->as_def()->get_anno_set()));
always_assert(res);
add_annotations(caller, field_ref->as_def()->get_anno_set());
}
}

Expand Down Expand Up @@ -644,6 +651,7 @@ void SynthAccessorPatcher::patch_kotlin_property_private_getter(DexMethod* m) {
void SynthAccessorPatcher::run(const Scope& scope) {
walk::parallel::methods(scope, [this](DexMethod* m) {
patch_kotlin_annotated_property_getter_setter(m);
patch_data_class_component(m);
if (is_synthetic_accessor(m) || is_synthetic_bridge(m)) {
patch_accessors(m);
}
Expand Down Expand Up @@ -675,6 +683,16 @@ void SynthAccessorPatcher::run(const Scope& scope) {
});
}

void SynthAccessorPatcher::patch_data_class_component(DexMethod* m) {
if (type_class(m->get_class())->get_super_class()->str() ==
"Lcom/facebook/kotlin/compilerplugins/dataclassgenerate/superclass/"
"DataClassSuper;" &&
boost::starts_with(m->get_simple_deobfuscated_name(),
DATA_CLASS_COMPONENT)) {
patch_accessors(m);
}
}

void SynthAccessorPatcher::patch_ctor_params_from_synth_cls_fields(
DexClass* cls) {
bool has_annotated_fields = false;
Expand Down
2 changes: 2 additions & 0 deletions opt/typedef-anno-checker/TypedefAnnoCheckerPass.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ class SynthAccessorPatcher {

void patch_local_var_lambda(DexMethod* method);

void patch_data_class_component(DexMethod* method);

void collect_annos_from_default_method(
DexMethod* method,
std::vector<std::pair<src_index_t, DexAnnotationSet&>>&
Expand Down

0 comments on commit 9e69700

Please sign in to comment.