Skip to content

Commit 1c29381

Browse files
authored
Add method reference for find_api_usage in document (#466)
1 parent 331eb7f commit 1c29381

File tree

1 file changed

+73
-0
lines changed

1 file changed

+73
-0
lines changed

docs/source/quark_method_reference.rst

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,76 @@ Here is the process of ``method_recursive_search``.
164164
return self.find_intersection(
165165
next_level_set_1, next_level_set_2, depth
166166
)
167+
168+
find_api_usage
169+
==============
170+
171+
**The algorithm of find_api_usage**
172+
173+
``find_api_usage`` searches for methods with ``method_name`` and ``descriptor_name``, that belong to either the ``class_name`` or its subclass. It returns a list that contains matching methods.
174+
175+
Here is the process of ``find_api_usage``.
176+
177+
.. code-block:: TEXT
178+
179+
1. Initialize an empty "method_list".
180+
2. Search for an exact match of the method by its "class_name", "method_name", and "descriptor_name".
181+
- If found, return a list with the matching methods.
182+
3. Create a list of potential methods with matching "method_name" and "descriptor_name".
183+
4. Filter the list of potential methods to include only those with bytecodes.
184+
5. Check if the class of each potential method is a subclass of the given "class_name".
185+
- If yes, add the method to "method_list".
186+
6. Return "method_list".
187+
188+
Here is the flowchart of ``find_api_usage``.
189+
190+
.. image:: https://i.imgur.com/FZKRMgX.png
191+
192+
**The code of find_api_usage**
193+
194+
.. code-block:: python
195+
196+
def find_api_usage(self, class_name, method_name, descriptor_name):
197+
method_list = []
198+
199+
# Source method
200+
source_method = self.apkinfo.find_method(
201+
class_name, method_name, descriptor_name
202+
)
203+
if source_method:
204+
return [source_method]
205+
206+
# Potential Method
207+
potential_method_list = [
208+
method
209+
for method in self.apkinfo.all_methods
210+
if method.name == method_name
211+
and method.descriptor == descriptor_name
212+
]
213+
214+
potential_method_list = [
215+
method
216+
for method in potential_method_list
217+
if not next(self.apkinfo.get_method_bytecode(method), None)
218+
]
219+
220+
# Check if each method's class is a subclass of the given class
221+
for method in potential_method_list:
222+
current_class_set = {method.class_name}
223+
224+
while current_class_set and not current_class_set.intersection(
225+
{class_name, "Ljava/lang/Object;"}
226+
):
227+
next_class_set = set()
228+
for clazz in current_class_set:
229+
next_class_set.update(
230+
self.apkinfo.superclass_relationships[clazz]
231+
)
232+
233+
current_class_set = next_class_set
234+
235+
current_class_set.discard("Ljava/lang/Object;")
236+
if current_class_set:
237+
method_list.append(method)
238+
239+
return method_list

0 commit comments

Comments
 (0)