Skip to content
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

AndroidEntryPointFinder added #37

Merged
merged 6 commits into from
Jul 14, 2021
Merged

AndroidEntryPointFinder added #37

merged 6 commits into from
Jul 14, 2021

Conversation

Diarilex
Copy link
Contributor

@Diarilex Diarilex commented Jul 9, 2021

No description provided.

@errt errt requested a review from TorunR July 10, 2021 15:28
Copy link
Collaborator

@TorunR TorunR left a comment

Choose a reason for hiding this comment

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

Are you planning to add support for the androidx/support library version of Activity etc? e.g. https://developer.android.com/reference/androidx/activity/package-summary or https://developer.android.com/reference/android/support/packages

val eps = ArrayBuffer.empty[Method]

var peps: List[String] = List("onCreate", "onRestart", "onStart", "onResume", "onStop", "onDestroy",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do not use a 'var', use individual 'val's defined outside of the method.

val mc = sc.findMethod(pep)
for (m ← mc) {
if (m.body != null) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

m.body should never be null, it's an Option, thus either using isDefined or just mapping over it as part of the 'for' should work

classHierarchy.foreachSubclass(ObjectType("android/app/Activity"), project) { sc ⇒
for (pep ← peps) {
val mc = sc.findMethod(pep)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe better use Scala's extended 'for' syntax to have just one 'for' that iterates over 'peps', 'mc' and possibly even 'm.body' (see next comment).

var peps: List[String] = List("onCreate", "onRestart", "onStart", "onResume", "onStop", "onDestroy",
"onActivityResult")
classHierarchy.foreachSubclass(ObjectType("android/app/Activity"), project) { sc ⇒
Copy link
Collaborator

Choose a reason for hiding this comment

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

Are you aware that 'foreachSubclass' a) is not reflexive (i.e., it won't include the class file for the Activity class here) and b) may include a subclass multiple times if the given ObjectType is an interface (Activity isn't, but I didn't check your other invocations of this method)?

}

peps = List("onCreate", "onStartCommand", "onBind", "onStart")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Code is utterly repetitive, please extract a method to do this.


peps = List("onLocationChanged", "onProviderDisabled", "onProviderEnabled", "onStatusChanged")
classHierarchy.foreachSubtype(ObjectType("android/location/LocationListener")) { st ⇒
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why are you using foreachSubtype here, but foreachSubclass on the previous ones? foreachSubclass directly provides you with the classfile, already ensuring that it is available.

@@ -355,71 +355,47 @@ object AllEntryPointsFinder extends EntryPointFinder {
* @author Tom Nikisch
*/
object AndroidEntryPointsFinder extends EntryPointFinder {

val ActivityEPS: List[String] = List("onCreate", "onRestart", "onStart", "onResume", "onStop", "onDestroy",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Use camel case with lower case first letter here.

}

def verifyEPS(possibleEPS: List[String], sc: ClassFile): ArrayBuffer[Method] = {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you move the foreachSubclass invokation to this method, too? You can just pass List("onNmeaMessage") for the last one (or, e.g. use Traversable[String] for the parameter type).

Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is this called "verifyEPS"? What verification does it perform?

def verifyEPS(possibleEPS: List[String], sc: ClassFile): ArrayBuffer[Method] = {
val eps = ArrayBuffer.empty[Method]
for (pep ← possibleEPS; m ← sc.findMethod(pep) if m.body.isDefined && !eps.contains(m)) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Depending on how large eps grows, it may be more (or less) performant to use a Set (where contains is constant time instead of linear, but addition may be more costly).

val eps = ArrayBuffer.empty[Method]
for (pep ← possibleEPS; m ← sc.findMethod(pep) if m.body.isDefined && !eps.contains(m)) {
eps.append(m)
Copy link
Collaborator

Choose a reason for hiding this comment

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

You may want to use += instead of append (and ++= instead of appendAll).

*/
object AndroidEntryPointsFinder extends EntryPointFinder {

val activityEPS: List[String] = List("android/app/Activity", "onCreate", "onRestart", "onStart", "onResume",
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not a fan of Lists in which certain indexes have different semantics, but if @errt says it's fine I don't mind.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah, didn't notice that. Yes, please have the list only for the methods and provide the ObjectTypes individually.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Or maybe a map?

*
* @author Tom Nikisch
*/
object AndroidEntryPointsFinder extends EntryPointFinder {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since you didn't answer:
Are you planning to add support for the androidx/support library version of Activity etc? e.g. https://developer.android.com/reference/androidx/activity/package-summary or https://developer.android.com/reference/android/support/packages
If you're not doing that, please at least add a comment that makes this clear.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Currently i am not planning to do that but i can probably do it later. Thank you for your suggestion.


override def collectEntryPoints(project: SomeProject): Traversable[Method] = {
val eps = ArrayBuffer.empty[Method]
for (key ← defaultEPS.keys) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Last change, then I guess I'll accept it:
Please use for((k,v) <- map) syntax here and use meaningful names for k and v.
You then obviously don't need to query the map for the key as you got the value already in v.

@errt errt merged commit 283ef68 into opalj:feature/IDFS-improvements Jul 14, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants