square / javapoet

A Java API for generating .java source files.
Apache License 2.0
10.81k stars 1.37k forks source link

MemberRef #317

Open swankjesse opened 9 years ago

swankjesse commented 9 years ago

Would be interesting to have an accelerator for member references, like someObject.instanceMethod() or someObject.instanceField or SomeEnum.CONSTANT or SomeType.staticMethod() etc.

We'd need a new MemberRef type that would include either a TypeName (for static members) or a String name (for instance members).

Would be useful for static imports.

jbgi commented 8 years ago

:+1: would be very useful.

sormuras commented 8 years ago

What would a possible usage look like? Say, you want to write: TimeUnit.DAYS.convert(1701, TimeUnit.SECONDS)

With $A (for anchor like in <a href=...) and Ref for the reference type:

"$A(42, $A)", Ref.get(TimeUnit.DAYS, "convert", long.class, TimeUnit.class), Ref.get(TimeUnit.SECONDS)

instead of

"$T.$L.convert(42, $T.$L)", TimeUnit.class, TimeUnit.DAYS, TimeUnit.class, TimeUnit.SECONDS

or, with $E ( hint, hint https://github.com/square/javapoet/issues/343 ):

"$E.convert(42, $E)", TimeUnit.DAYS, TimeUnit.SECONDS
jbgi commented 8 years ago

For methods I would want something in the like of Ref.get(ExecutableElement method, TypeMirror... typeArguments)

sormuras commented 8 years ago

@jbgi Talking about parameter types, do you? If yes, the parameter types are already included in the ExecutableElement instance, iirc.

Anyway, can you give me an example for someObject.instanceMethod(). Especially, how do you reference someObject. Via a string literal, via NameAllocator?

"$A($A)", Ref.get("this", "equals"), Ref.get(TimeUnit.DAYS)
"$T v = $A", TypeName.get(TimeUnit.class), Ref.get("super", "getCurrentUnit")
jbgi commented 8 years ago

@sormuras no type arguments. like when I want to generate a call to Collections.<String>emptyList()

sormuras commented 8 years ago

I understand. Never used type arguments in that place. Usually the types are infered like:

List<String> strings = Collections.emptyList()
jbgi commented 8 years ago

@sormuras yes I usually do that. there is cases where type inference is poor however, like when chaining methods: Optional<String> oa = Collections.emptyList().stream().findFirst(); // does not compile Contrived example, but it does arise sometimes. I agree that the use case is not worth it.

sormuras commented 8 years ago

Almost implemented locally... :sweat_smile:

sormuras commented 8 years ago

See #388 and #404 before implementing $R again. :smile:

moaxcp commented 4 years ago

Would this be helpful for switch statements using an enum? I'm running into an issue where when an enum is used in a case the code does not compile.

    byte type = in.readCard8();
    byte data = in.readCard8();
    BehaviorTypeEnum typeEnum = BehaviorTypeEnum.getByCode(type);
    switch(typeEnum) {
      case BehaviorTypeEnum.DEFAULT:
      case BehaviorTypeEnum.LOCK:
      case BehaviorTypeEnum.PERMAMENT_LOCK:
        return new DefaultBehaviorStruct(type);
      case BehaviorTypeEnum.RADIO_GROUP:
      case BehaviorTypeEnum.PERMAMENT_RADIO_GROUP:
        return new RadioGroupBehaviorStruct(type, data);
      case BehaviorTypeEnum.OVERLAY1:
      case BehaviorTypeEnum.OVERLAY2:
      case BehaviorTypeEnum.PERMAMENT_OVERLAY1:
      case BehaviorTypeEnum.PERMAMENT_OVERLAY2:
        return new OverlayBehaviorStruct(type, data);
      default:
        return new CommonBehaviorStruct(type, data);
    }

This is the error

/home/john/projects/x11-client/build/generated/xproto/com/github/moaxcp/x11client/protocol/xkb/BehaviorUnion.java:13: error: an enum switch case label must be the unqualified name of an enumeration constant
      case BehaviorTypeEnum.DEFAULT:
                           ^

In this case the enum value must be statically imported.

ronshapiro commented 4 years ago

I don't believe you need to statically import here. javac knows to look for the enum values directly without the import.

בתאריך יום א׳, 16 באוג׳ 2020, 1:05, מאת John Mercier ‏< notifications@github.com>:

Would this be helpful for switch statements using an enum? I'm running into an issue where when an enum is used in a case the code does not compile.

byte type = in.readCard8();
byte data = in.readCard8();
BehaviorTypeEnum typeEnum = BehaviorTypeEnum.getByCode(type);
switch(typeEnum) {
  case BehaviorTypeEnum.DEFAULT:
  case BehaviorTypeEnum.LOCK:
  case BehaviorTypeEnum.PERMAMENT_LOCK:
    return new DefaultBehaviorStruct(type);
  case BehaviorTypeEnum.RADIO_GROUP:
  case BehaviorTypeEnum.PERMAMENT_RADIO_GROUP:
    return new RadioGroupBehaviorStruct(type, data);
  case BehaviorTypeEnum.OVERLAY1:
  case BehaviorTypeEnum.OVERLAY2:
  case BehaviorTypeEnum.PERMAMENT_OVERLAY1:
  case BehaviorTypeEnum.PERMAMENT_OVERLAY2:
    return new OverlayBehaviorStruct(type, data);
  default:
    return new CommonBehaviorStruct(type, data);
}

This is the error

/home/john/projects/x11-client/build/generated/xproto/com/github/moaxcp/x11client/protocol/xkb/BehaviorUnion.java:13: error: an enum switch case label must be the unqualified name of an enumeration constant case BehaviorTypeEnum.DEFAULT: ^

In this case the enum value must be statically imported.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/square/javapoet/issues/317#issuecomment-674451623, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAGBRXJ5NJFZTRF3MEHKCNLSA4BBFANCNFSM4BMTVVVQ .

moaxcp commented 4 years ago

I don't think it does. When I manually edit the code to static import the error goes away. This seems like a common problem developers run into when using enums with a switch. I have found many other examples online for this error message.

I think this makes a good argument for implementing $R and requesting static imports from a CodeBlock.

eamonnmcmanus commented 4 years ago

If you just write the plain enum constants without BehaviorTypeEnum. then the switch will compile, with or without static imports.

moaxcp commented 4 years ago

Ah I missed that. The only problem I see there is that the import of BehaviorTypeEnum needs to be done outside of the case CodeBlocks. The import will likely be done already before the switch so it is probably not a big deal. Thanks for the help!

ronshapiro commented 4 years ago

If the type isn't referenced anywhere else, you don't need an import at all.

switch (SomeClass.returnsAFoo()) { case BAR: // do something }

No import of Foo or Foo.BAR is necessary

בתאריך יום א׳, 23 באוג׳ 2020, 15:15, מאת John Mercier ‏< notifications@github.com>:

Ah I missed that. The only problem I see there is that the import of BehaviorTypeEnum needs to be done outside of the case CodeBlocks. The import will likely be done already before the switch so it is probably not a big deal. Thanks for the help!

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/square/javapoet/issues/317#issuecomment-678766932, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAGBRXIICFIEEUEDMA5GTIDSCEB7ZANCNFSM4BMTVVVQ .