There is a lot of confusion about the getCompletions method in the javax.annotation.processing package. What is the completion function returned by this method? Can you give me an example of specific use. Thank you。
Iterable<? extends Completion> getCompletions(Element element,
AnnotationMirror annotation,
ExecutableElement member,
String userText);
There is a lot of confusion about the getCompletions method in the javax.annotation.processing package.
By who?
What is the completion function returned by this method?
it's a nice-to-have, optional feature. What it is for, is to help IDEs specifically.
When you compile code with javac or some other command line compiler, this method isn't invoked at all. It's there solely for IDEs. When you open up your eclipse or intellij or whatnot, type "Hello". and wait 500msec or hit CTRL+SPACE or whatever the IDE uses for shortcut for 'auto-complete', you get a menu of sorts that shows all the various methods that strings have. And possibly some templates and other features as well; IDEs are free to add whatever they want to this, there is no actual java specification for 'auto completers in IDEs'.
Nevertheless, that's what this method is for.
Specifically, it's for having the IDE help you out when you type: #YourAnn(someAnnotationParamName=...) - anywhere in the ... part, that's where this feature is relevant.
How to help yourself next time
Docs are good... if they are there. But in this case, they were there. The docs on this feature can be found where-ever you find your javadoc (google, your IDE, and so many other places): The javadoc of Processor.getCompletions explains stuff, including a great example.
Given that this example is quite nice, I dispute your characterization that 'there is a lot of confusion about the getCompletions method' :)
getCompletions is intended for use by IDEs. It helps users to know what arguments may be supplied to an annotation.
It is well described by its Javadoc documentation.
The example used there is: Suppose there is an annotation defined as
#MersennePrime {
int value(); // must be a prime of the form 2^n-1, e.g., 3, 7, 31, 127, 8191, ...
}
The implementation of getComletions could be
return Arrays.asList(of("3"),
of("7"),
of("31"),
of("127"),
of("8191"),
of("131071"),
of("524287"),
of("2147483647"));
If a user has written #MersennePrime, the IDE can suggest the arguments returned by getCompletions. If a user has written #MersennePrime(1, then getCompletions is passed "1" as its userText command-line argument and should return a list containing just 127 and 131071.
Related
I'm programming a Config class that reads a file and provides config parameters as a Map.
Parameters can be accessed by conf.get("LogLevel") or conf.getLogLevel().
The first function just reads from the map and returns the value (that can be null or invalid) while the second function converts the value to a LogLevel and returns a default value when no valid value is given.
Therefore I want to discourage Programmers from using the genereral get(), but there are special cases where this method is useful so I cant just make it protected.
Right now I use #Deprecated but I dont think this is a good solution because it is only ment for methods that will be removed in the future. (Correct me if I'm wrong there, thats what SonarLint told me about the #Deprecated annotation)
/**
* #Deprecated When possible, use the key-specific getter instead
*/
public String get(String key) {
return values.get(key);
}
public int getLogLevel() {
return Log.getLogLevel(values.get(LOG_LEVEL), Log.getLogLevel(defaultValues.get(LOG_LEVEL)));
}
Well, if #Deprecated is not the solution, you are left with only one option. Put message that notes that the usage is "discouraged" (except for the special cases) into the javadocs ... and hope that people are going to read the javadocs.
Defining your own custom annotation will not help because you can't get your users to use an annotation processor that will recognize it.
Likewise, you can't do it via custom rules for FindBugs, PMD, Sonar and so forth because that requires your users to customize their installations of those products.
(Though ... if this is an in-house product and all of your users use a common CI server ... you could possibly do the checks in the CI server. It depends if you can define custom rules that can reliably distinguish the general "discouraged" use-cases from the special cases. This will also entail convincing your co-workers that this is a good idea.)
In my opinion, the #Deprecated tag would be better than all of the above. For the special cases, encourage people to judiciously add #SuppressWarning("deprecation") in the cases where the usage is necessary.
I don't think this is a good solution because it is only meant for methods that will be removed in the future.
This is incorrect. Possible future removal is only one of the example reasons for deprecation listed in the #Deprecated javadoc (Java 11 version). Other reasons listed there are:
"the tagged element's usage is likely to lead to errors",
"it may be changed incompatibly [...] in a future version",
"it has been superseded by a newer, usually preferable alternative", or
"it is obsolete".
Note that these are listed as example reasons ... which means that you could deprecate for other reasons.
This is also consistent with the older "when to deprecate" guidance here.
IMO, your "discouraged" scenario is covered by that.
If you arrived here and looking for android solution there's #Discouraged annotation in androidx
Ok, this could be a tricky one. For a code generating tool I need to know methods and arguments of a class. The method name and argument types are the easy ones - just using reflection. But the argument name - and I need the real argument name - is a tricky one because this information is in the javadoc. In my case I use Netbeans 8 and I am pretty sure if Netbeans can get the arguments name I can too. Does anyone know how to read the javadoc to get the argument names of a method?
PS I know this question will pop up. I need the real argument names because the generated code provides an api and it is not very helpful for a developper to use an api where the api methods are something like set_a1, set_a2, and so on.
Indeed, this is tricky, and will involve a considerable effort if you intend to find a general solution that works for arbitrary (third-party) classes and arbitrary Java versions.
However, under certain conditions, there may be a simple solution:
If you can compile the classes on your onw, and if you can use Java 8, then you can use the Method Parameter Reflection infrastructure that was added in Java 8. When compiling the classes with javac -parameters ..., then the parameter names are added to the class file, and can be obtained from the method by calling getParameters on the Method object, and then Parameter#getName()
Parameter parameters[] = method.getParameters();
String name = parameters[0].getName();
...
Let's say I have the following incomplete code:
public class Foo<Type> {
public Foo() {
List<Type> list = new ArrayList|
}
}
where the pipe ("|") after ArrayList indicates the current cursor position.
Now, if I press Ctrl+Space and have Eclipse auto-complete the constructor call on the ArrayList, it generates the following line:
List<Type> list = new ArrayList<Foo.Type>();
and immediately reports an error that "Foo.Type cannot be resolved to a type".
This leaves me with a couple of questions:
Why does Eclipse include Foo. in the auto-completed generic parameter? Is this a bug? Is there a reason why it does this? Can it be turned off? And lastly: Why can Foo.Type not be resolved???
I can at least partially answer your question. First, the easy one. Foo.Type cannot be resolved because that would be an inner class named Type inside the Foo class. In your example, there is no such inner class. Also, in your code, the symbol Type is really a generic type variable, neither the name nor a reference to any specific class. This is easily reproducible, shown here in DrJava, and not specific to your use of Eclipse:
"Why does Eclipse include Foo." and "Is this a bug?" I think the answer is clearly yes, it is a bug, simply because there's no such thing as Foo.Type in your posted code and as reported by the compiler. But as a bug, it's harder to answer the why part of your question without looking into the Eclipse code, or whatever code Eclipse relies upon for its autocomplete logic. What Eclipse should recommend for you is simply Type. Again, DrJava shows that using <Type> compiles cleanly as expected:
As for turning this behavior off, since I'm not an Eclipse user, the best I can do at the moment is direct you to this related SO question: Disable content assist in Eclipse
While I do not know whether Eclipse is actually relying on compiler type inference to provide the autocomplete suggestion, there have been a number of javac compiler inference bugs over the years, as well as reports of Eclipse behavior not matching javac. Some of these have been javac bugs, others are probably Eclipse issues. A search on the Web for "java type inference bug" yields plenty of hits, but at this point it's just a guess. You didn't specify which version of Java you were using; it might be interesting to try the same code using different versions (JDK 6 vs 7 vs 8).
GCC supports declaring methods with the attribute warn_unused_result so that any caller who does not save the return value of the method gets a warning.
Does Java have any comparable feature?
No, Java doesn't have such a feature.
This could be accomplished by static code analysis tools like FindBugs, based on an annotation on the method, but I don't think such a rule exists. You could create one, though: FindBugs is free software.
FindBugs does a similar check already for specific API calls like File.delete() (it throws a warning if the result of the method is ignored. See http://findbugs.sourceforge.net/bugDescriptions.html#RV_RETURN_VALUE_IGNORED_BAD_PRACTICE). So you could take this rule as an example.
As far as I know there is no such a thing, but some IDEs such as IntelliJ IDEA warn you so about some known methods (for example methods on a String which return another String).
Lamdbaj allows the definition of closures in the Java language, various examples can be found
here
My question is regarding the underlying Java mechanisms at use, for instance, to define the println closure, the following code is used:
Closure println = closure();
{ of(System.out).println(var(String.class)); }
This closure can be subsequently executed via:
println.apply("foobar");
I am curious as to what mechanisms in Java would allow the call to of(...).println(...) to become associated with the println instance itself.
Naturally, the lambdaj source code is available to read but I was hoping for a slightly higher level explanation if anyone has one. My reflection skills go as far as a bit of introspection and executing methods dynamically.
I am Mario Fusco and I am the main developer of the lambdaj library.
First of all I would like to clarify something: lambdaj is not intended to replace any functional language. As I said last week in my speech at the Jug of Zurich if you have a chance to use Scala, go for it and never look back. Here you can find a resume of my speech where it is clearly stated that:
http://ctpjava.blogspot.com/2009/10/lambdaj-new-trends-in-java.html
I am an happy Scala developer too. But sometimes you are just obliged to develop in Java (in my experience, in the real world, about the 80% of times you cannot choose in which language you have to write your code) and in this case some of the lambdaj features could be helpful (or I hope so). I just wanted to bring to Java some functional features that are totally missing. Of course the result is not completely satisfying mainly due to the limitation imposed by Java itself.
As for the internal lambdaj mechanism, yes it uses a ThreadLocal in order to achieve that result. If you have other questions, curiosities or even better suggestions and constructive critics about lambdaj maybe you could be interested to register yourself to the lambdaj mailing list here:
http://groups.google.com/group/lambdaj
Bye
Mario
Well, of is presumably a static method which is imported statically so it can be called without the enclosing class name. I expect that var is the same. Both methods must return some type which have the methods subsequently called:
public class Printable {
public void println(Var var);
}
public class Fac {
public static Printable of(Object o) {
return new Printable(o);
}
public static Var var(Class<?> clazz) {
return new Var(clazz);
}
}
All of a sudden:
Fac.of(System.out).println(Fac.var(String.class));
Is valid Java. Using static imports, hey presto:
import static Fac.*;
of(System.out).println(var(String.class));
The curly-braces are obviously valid Java as you can add these in any method to aid in defining a lexical sope. This API-design style is called fluent and is best showcased by the JMock testing library.
By the way, if this is supposed to introduce closures to Java, it's quite ridiculous - the syntax is unreadably awful. Their I/O example actually made me laugh out loud. Try Scala!
EDIT - the two println calls are associated I believe because the first sequence of calls allow the library to capture the variables which you have passed in as parameters. These are probably captured in some ThreadLocal structure. When you then call a (also presumably static) println method, the library is using this captured data to actually execute the behaviour at a later point. Also testing related, the EasyMock test framework uses a similar mechanism (which uses Java proxies in the background) to capture expected values.