Skip to content
This repository was archived by the owner on Feb 26, 2023. It is now read-only.
This repository was archived by the owner on Feb 26, 2023. It is now read-only.

Compilation fails for methods annotated with @ServiceAction that have the same name as one of their parameters #1070

Description

@kutsal

Given an @EIntentService like so:

@EIntentService
public class FooIntentService extends IntentService {
  @ServiceAction
  public void foo(Object foo) { /* ... */ }
}

Compilation fails annotation processing with the following error, which is misleading:
error: method foo(Object) is already defined in class IntentBuilder_

This is because the generated code in FooIntentService_.java has this bit (see comments in code block):

public FooIntentService_.IntentBuilder_ foo(Object foo) {
  intent_.setAction(ACTION_FOO);
  foo(foo); // <--- Recursive call!!!
  return this;
}

public FooIntentService_.IntentBuilder_ foo(Object foo) { // <--- Because of this
  intent_.putExtra(FOO_EXTRA, ((Serializable) foo);
  return this;
}

And when the parameter name is changed, the Extra is properly passed.

public FooIntentService_.IntentBuilder_ foo(Object bar) {
  intent_.setAction(ACTION_FOO);
  bar(bar); // <--- Happy now
  return this;
}

public FooIntentService_.IntentBuilder_ bar(Object bar) { // <--- Because, this.
  intent_.putExtra(BAR_EXTRA, ((Serializable) bar);
  return this;
}

Since the @EIntentService usage is defined as:

FooIntentService_.intent(getContext()).foo(new Whatever()).start();

I think having public accessors for the Extras generated from the parameters of the annotated methods is unnecessary. They only pollute the IntentBuilder_s namespace since they'll never be used directly.

I think a better way to do this would be, in this case, to make those Extras private, and use a different naming scheme while generating them so they won't collide with the annotated methods...

Or, maybe changing the usage to something like the following is better?

FooIntentService_.intent(getContext()) //
    .foo(/* NO PARAMETERS */).bar(new Whatever()) // .bar() is really the parameter to .foo()
    .start();

so those Extra methods handling the parameters would make sense.

Either of those, or @ServiceAction annotation's processor might warn users when it's placed on a method that has a parameter name the same as its name.

Activity

  1. changed the title [-]Compilation fails for methods annotated with @ServiceAction that have the same name as one of their parameter[/-] [+]Compilation fails for methods annotated with @ServiceAction that have the same name as one of their parameters[/+] on Jul 17, 2014
  2. WonderCsabo commented on Jul 17, 2014

    @WonderCsabo
    Member

    Actually naming a method as the same as the parameter is not a really good practice. I do not think we should make our code more complex by preparing it for this edge case.

  3. kutsal commented on Jul 17, 2014

    @kutsal
    Author

    @WonderCsabo, I disagree with you. My problem here is not what's best practice, but the fact that the current implementation pollutes IntentBuilders namespace with names of the parameters to the methods. This example fails compilation with the same message as well:

      @ServiceAction
      public void foo(int bar) { /* Do something... */ }
      /* other actions... */
      @ServiceAction
      public void bar(int foo) { /* Do completely unrelated thing... */ }

    The error is misleading. In my code, I only defined one foo(...) and one bar(...), not two of them. The fact that each self-contained method's parameter naming scheme leaking into the generated class is my real problem here. You're imposing a method and parameter naming scheme in my project for me.

  4. WonderCsabo commented on Jul 17, 2014

    @WonderCsabo
    Member

    OK, sorry, i see your point now. @yDelouis you contributed this feature, what do you think?

  5. yDelouis commented on Jul 17, 2014

    @yDelouis
    Contributor

    I agree with @kutsal. We shouldn't add the parameter as an extra to the IntentBuilder. (Even if it is added as an extra in the Intent underneath).
    Generally, I think an annotation should do one thing and only one. If the developer wants to pass an extra without the action, he still can with @Extra.

  6. WonderCsabo commented on Jul 17, 2014

    @WonderCsabo
    Member

    Agreed. Can you post a PR to remove the extra methods so the service action method calls super.extra() directly?

  7. yDelouis commented on Jul 17, 2014

    @yDelouis
    Contributor

    I will I soon as I have enough time.

  8. added this to the 3.1 milestone on Aug 15, 2014
  9. modified the milestones: 3.1, 3.2 on Sep 20, 2014
  10. WonderCsabo commented on Sep 22, 2014

    @WonderCsabo
    Member

    I think it is rather a defect than a task. :(

  11. WonderCsabo commented on Nov 5, 2014

    @WonderCsabo
    Member

    @yDelouis can you resolve this?

  12. self-assigned this
    on Nov 5, 2014
  13. WonderCsabo commented on Nov 6, 2014

    @WonderCsabo
    Member

    Fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions