I've never seen a declaration like this, in fact I haven't known it was
possible. Everybody writes "public final static" for defining a
constant. So the rule could be to generate getter/setter for everything
declared without "static" and to do nothing if "static" is present. This
assumes you can find out if static was explicitly given.
Maybe the approach converting plain methods without get/set into
properties is nicer, but what if there's a method you want to keep it as
is? Annotating it with @Getter(AccessLevel.NONE)
@Setter(AccessLevel.NONE) is not very nice.
--
You received this message because you are subscribed to the Google
Groups group for http://projectlombok.org/
To post to this group, send email to project...@googlegroups.com
To unsubscribe from this group, send email to
project-lombo...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/project-lombok?hl=en
I'd say this simply can't happen. When anybody places @Data on an
interface, they must this about it a bit. Using this syntax the only
possibility to get @Data do anything is replacing dummy members by
setters and getters, so there's no surprising disappearing of fields.
The possibility to prevent this behavior by explicitly using "static"
makes it fully usable. However it's not nice.
> Same goes for trying to convert "String hello();" - how is lombok
> supposed to figure out this isn't a normal interface method, and
> instead something that should be turned into get/set?
Agreed.
> If we're ever going to support this it'll likely be by way of
> annotating something or other with @Getter and @Setter.
I have a possibly better proposal: Annotating the class with @Getter
adds a getter to each given setter. Annotating with @Setter works the
other way round. So nothing disappers and it's about the same like for
classes; the only difference is that the starting point is an accessor
instead of a field, which is obviously necessary.
> However, this feels rather low priority - adding get/set to interfaces
> is far rarer than classes, and its going to be a lot more confusing.
Agreed.
Groups group for http://projectlombok.org/
To post to this group, send email to project...@googlegroups.com
To unsubscribe from this group, send email to
project-lombo...@googlegroups.com
Groups group for http://projectlombok.org/
To post to this group, send email to project...@googlegroups.com
To unsubscribe from this group, send email to
project-lombo...@googlegroups.com
That was the idea. Apart from that, you could also specify @Getter of
@Setter on an individual field to generate or suppress the generation
of getters and setters. We might actually be able to also generate
getters and setters on uninitialized fields since that is currently
not valid Java.
Roel
> Groups group for http://projectlombok.org/
>
> To post to this group, send email to project...@googlegroups.com
> To unsubscribe from this group, send email to
> project-lombo...@googlegroups.com
IIRC, you said, you'd have to start with legal Java, but if you can do
this, that's perfect.
> If it looks good, add an issue and we'll tackle it at the same time we
> make "@Setter" and "@Getter" legal on classes.
Theoretically, it could be nice to have a shortcut for @Getter and
@Setter (I think this was the meaning of proposing @Property), but it's
not that important when the whole interface can be annotated.
Btw., with my annotation rewriting proposal from 2010-04-18 everybody
could define such a joint annotation themselves. But I assume, something
like this will take some time.
I suppose that
@Getter @Setter
interface I {
@Setter(Access.NONE)
int hello;
}
creates getHello() only, right? And
@Getter
interface I {
@Setter
int hello;
}
creates both getHello() and setHello(), right? Simply the more specific
annotation wins, that's flexible and consistent.
--
I have different implementations that provide the same business logic:
Book b = (Book) new BookXml() // xml element reader/writer
Book b = (Book) new BookDAO() // db access object
etc.
What about having an annotation, named @ExtractInterface (or similar), which
pulls all public methods, and creates a new interface type filled with those,
the same as with Eclipse's extract interface feature?
Thus a class like so:
@ExtractInterface
class Thing {
public void setHello(String newHello) { ... }
public String getHello() { ... }
}
Would generate:
interface IThing { // the naming would have to be a consideration
public void setHello(String newHello);
public String getHello();
}
This would (hypothetically) interact with other lombok annotations well:
@ExtractInterface
class Thing {
@Getter @Setter String hello;
}
... would produce the same interface as above.
My thoughts are that this proposal would satisfy the specific request to place
getters and setters on an interface, but would have wider uses as well. For
instance, I have recently been working on part of a project where I have many
types implementing interface Foo, and an AbstractFoo providing default
behaviour. It's expected that plugins will be able to provide an
implementation, choosing between implementing Foo or extending AbstractFoo. If
I could place @ExtractInterface on AbstractFoo I wouldn't need to track
changes in multiple places (hopefully it seems pretty DRY).
I would imagine that there will be objections to this, and areas which would
need to be covered (copying javadoc for example) but I thought I would get
your thoughts.
Best regards,
Graham
I had a similar idea, but the other way round, but I'm unsatified with
it. I' prefer to start with the interface as it's the more important
thing - it would be bad if changes in the implementing class promoted
without notice. In the direction from interface to a class there's not
obviouls what could be done, maybe properties could get a real
implementation while all other methods could get a no-op implementation
in a concrete class (and be ignored in an abstract class).
> Thus a class like so:
>
> @ExtractInterface
> class Thing {
> public void setHello(String newHello) { ... }
> public String getHello() { ... }
> }
>
> Would generate:
>
> interface IThing { // the naming would have to be a consideration
> public void setHello(String newHello);
> public String getHello();
> }
I'd prefer to be explicit using @ExtractInterface(IThing.class).
> This would (hypothetically) interact with other lombok annotations well:
>
> @ExtractInterface
> class Thing {
> @Getter @Setter String hello;
> }
>
> ... would produce the same interface as above.
>
> My thoughts are that this proposal would satisfy the specific request to place
> getters and setters on an interface, but would have wider uses as well. For
> instance, I have recently been working on part of a project where I have many
> types implementing interface Foo, and an AbstractFoo providing default
> behaviour. It's expected that plugins will be able to provide an
> implementation, choosing between implementing Foo or extending AbstractFoo. If
> I could place @ExtractInterface on AbstractFoo I wouldn't need to track
> changes in multiple places (hopefully it seems pretty DRY).
IMHO, this is an important and common use case. My above objection
("changes in the implementing class promoted without notice") doesn't
apply here.
> I would imagine that there will be objections to this, and areas which would
> need to be covered (copying javadoc for example)
Sometimes you need a different javadoc, e.g., writing "Compute...." in
IFoo and writing "Do nothing" in the dummy implementation AbstractFoo.
But this is not strictly necessary (cf. MouseAdapter).
Sure. I can even imagine extracting multiple interfaces, but quite often
extracting all public methods would do, just like MouseAdapter ->
MouseListener. IMHO, the "classical" solution should be fine:
public @interface ExtractInterface {
Class<?>[] value();
}
@ExtractInterface(IThing.class)
public class Thing implements IThing {
@ExtractInterface({})
public void youGoNowhere() {}
}
> Unfortunately it's not really the job of lombok. This is a classic job
> for traditional annotation processors, which are perfectly capable of
> generating entirely new files based on a file that will in fact be
> _using_ that file.
I could imagine that both IThing and Thing exists, where IThing is an
interface already declaring a couple of methods and Thing is an abstract
class declaring some other methods. The goal is to add all methods of
Thing to IThing. Sure, this is not as common as the base case.
> The only pragmatic thing lombok could do there is
> silently add "implements IThing", but that's not nearly enough to
> justify lombok adding this feature, and adding considerable logistics
> at the backend to support it - lombok right now cannot generate new
> files.
Sure, adding "implements IThing" is quite useless, but everybody could
profit from integrated features instead of having to install additional
stuff. However, I see you need to concentrate on other things.
On 10-06-27 20:07, Reinier Zwitserloot wrote:
> Oh, and if either of you or someone else wants to give it a try, let
> me know, I can give you some pointers on how to write annotation
> processors. Between lombok and writing quite a few normal ones, I'm
> somewhat knowledgable on the subject :P
I'm sort of interested but it depends on how much work it is. I tried
Google but it gave me nothing really readable.
Is it possible to do something like http://paranamer.codehaus.org using
annotation processors and/or lombok?
Ok, but using strings is generally a bad idea. Replacing an existing
class this way doesn't work due to the "duplicate class" error.
Using IThing.class works partly. I can obtained all the information as
strings only:
for (final AnnotationMirror annotationMirror :
typeElement.getAnnotationMirrors()) {
final DeclaredType annotationType = annotationMirror.getAnnotationType();
final ExtractInterface annotation =
annotationType.asElement().getAnnotation(ExtractInterface.class);
}
Using "annotationType.toString()" gives me the information, but
"annotation" is always null. Even if it wasn't, according to
http://java.sun.com/javase/6/docs/api/javax/lang/model/element/Element.html#getAnnotation(java.lang.Class)
it wouldn't help. I need two things:
- find out if the annotation is ExtractInterface
- get the value() not necessarily as a class (its name would suffice)
Currently, I see no way how to do it except by parsing
annotationType.toString(), which is very strange at best. Any better idea?
So I tried it with a interface name generated by simply prepending "I"
and it sort of works using javac. I'll look now how to integrate it into
eclipse. There may be problems with generics, etc.; maybe generating a
class file instead could be easier.
--
Agreed, however toString() is much worse than necessary. Something like
getClassName() would be a fine replacement where you can't get the Class
itself.
> Integrating into eclipse is not particularly difficult; create a jar
> file containing your annotation processor as well as a services file:
>
> META-INF/services/javax.annotation.processing.Processor
I tried to place it in the project directory, then in its src, then in
existing META-INF (somewhere in WebContent) and finally in the jar file,
the last one worked.
> this file should be a text file containing one line, which is the fully
> qualified class name of your processor. E.g. for lombok this file contains:
>
> lombok.core.AnnotationProcessor
>
>
> In eclipse, for any project, go into its properties, "Java Compiler",
> "Annotation Processing", and check the "Enable annotation processing"
> and "Enable processing in editor" checkboxes. Then pick the "Factory
> Path" subpage and add your jar here. Eclipse will ask for permission to
> recompile your whole project, and boom, it'll all work. If you ever make
> a change to your processor, you need to rebuild the jar, refresh
> eclipse's dir state (click on project, hit F5) (unless you're on
> mac/linux and have auto-refresh on), go back to this page, uncheck the
> processor, hit apply, then check it, and hit OK - unfortunately eclipse,
> at least version 3.5, doesn't refresh this itself.
Even if it did. On my current OS parody the jar gets locked, so I need
to leave eclipse every time when I need to change it.
So, it's not "particularly difficult", it's just about 10 times more
complicated than it should be. Specifying a list of annotation
processors and a classpath for them is the useful part; creating the jar
and clicking around is unnecessary overhead.
> In IDEA you're out of luck, this IDE is way behind on annotation
> processing. On netbeans, in 6.8, you're out of luck. On 6.9, however, I
> hear support is _excellent_.
Ok, I currently stick with eclipse, anyway.
If you uncheck the jar in the list and hit ok, it should unlock, no?
--Reinier Zwitserloot
That said, to use an annotation processor inside Eclipse, you do need a jar file.
Roel
-----Oorspronkelijk bericht-----
Van: rei...@zwitserloot.com [mailto:project...@googlegroups.com] Namens Reinier Zwitserloot
Verzonden: maandag 28 juni 2010 15:26
Aan: project...@googlegroups.com
Onderwerp: Re: [project lombok] Re: It would be nice to define a plain Java interface using @Data
It may not be useless. Reinier or someone more familiar will have to back me
up or shoot me down on this one, but isn't there a caveat with annotation
processing in that the source file containing the annotation must not be
modified? I.E. you can't have a class Thing without the "implements IThing"
that is then modified by the annotation processor to implement it in the source
file[1].
If that is indeed the case, manually entering "implements IThing" isn't that
much of a deal. But if you're specifically looking to reduce boilerplate, it's
fair game. I guess this is where lombok could come in, and it would probably
be the simplest transformer out there :-)
Hopefully someone can help me out if I've made a mistake.
Regards,
Graham
[1] The only source I have for this is coming from a question I asked on
StackOverflow: http://stackoverflow.com/questions/687553/the-drawbacks-of-
annotation-processing-in-java/705812#705812)
It's always useless, unless you need a botnet to send a lot of spam.
> If you uncheck the jar in the list and hit ok, it should unlock, no?
No, it does not. Probably the eclipse guys don't use the parody so they
didn't notice.
On 10-06-28 15:36, Roel Spilker wrote:
> Uhm, I don't know if this is helpful, but I usually have3
> a separate root folderin my eclipse project called SPI.
> In that folder I have a META-INF/services path containing
> the SPI files (javax.annotation.processing.Processor)
> If you mark the SPI folder as source folder,
> eclipse will compy the content to the bin folder
> and during runtime your Service Providers will be discovered.
>
> That said, to use an annotation processor inside Eclipse, you do need a jar file.
Initially, I put it all (Thing, ExtractInterface, and
ExtractInterfaceGenerator) into a single directory and it worked using
javac on the command line. I wonder why eclipse must make things
complicated. I'd like to do something like
interface ExtractInterfaceConfig {
String simpleName(String classPackageName, String classSimpleName);
String packageName(String classPackageName, String classSimpleName);
}
which would provide the interface name in case none is given. This does
not belong to any jar, this is a way how the user could configure it.
I'm afraid this can't be done easily, but I think such a flexibility is
very useful, even more for lombok, where there are (could be) much more
things to configure, e.g.,
- using "is" a getter prefix (should be sort of global option)
- details of toString (s. below)
The most flexible way to configure things is a piece of program.
interface ToStringConfig {
String prefix(String className);
String suffix(String className);
String separator(String className);
String entry(String className, String name, String value);
boolean useGettersInsteadOfFields();
}
I wonder if this is possible somehow, the user configuration should
reside somewhere in the project itself, surely not in any jar. Is it
possible for annotation processors? Is it possible for lombok?
Agreed, but assuming the interface already exists, lombok could do more:
- optionally expand the interface by all public methods from the class
(unless annotated to be ignored)
- optionally expand the class by providing some simple implementation
when told to do so: getters and setters could do what expected, other
methods could get an empty or throwing implementation (recently I needed
a PriorityQueue with only two working methods).
> My main problem with it is that the 'create new file' part of it is
> NOT part of the lombok infrastructure right now, and it's quite a bit
> of work to add it. One could of course make a mixed bag: An annotation
> processor _AND_ a lombok processor, with the lombok processor just
> adding the implements line, but the additional complexity in setting
> that up properly does not seem to be worth the hassle.
But aren't there more useful features which will require creating new
files anyway? There are plans for @Builder annotation, this implies one
or more new classes, doesn't it?
Btw., there's already an @ExtractInterface annotation:
http://code.google.com/p/javadude/wiki/AnnotationsQuickRef