I want to restrict the usage of some library methods in my project (so I get a warning when I use these methods). Is there a list of custom deprecated methods in IDEA?
Example: I should never use PrimitiveIterator.OfInt.next(). I should use nextInt() instead. I want to see a warning every time I use next().
Put the text cursor on a method or a call to a method you want to deprecate and type Alt+Enter, invoke Annotate method '<name>' and choose java.lang.Deprecated. If the method you are annotating is located in a library, IntelliJ IDEA will automatically store the annotation "externally" (i.e. in an xml file, the location of which you will be asked for).
Another option is to create a pattern for the Structural Search Inspection to highlight any call to an undesirable method with a warning.
Related
I've been playing around with Java Annotation Processors, with great results.
Now I would like to do the following, which as far as I can see is not possible.
I have several Classes that implement the Builder Pattern. Say for instance
new FooBuilder().doSomething("A").doSomethingElse("B").execute();
It is vital that the "chain" of method calls is terminated using an execute() method. Otherwise, the builder will basically do nothing.
So I wanted to use JAP to verify the presence of an execute() method on certain expression types at compile time. Unfortunately it appears that the finest-grained information I can retrieve is on method declaration level, not expressions.
Is what I want at all possible?
Java's standard annotation processors provide a callback only at declarations, such as method and field declarations.
It's possible to use an annotation processor to analyze expressions, but it's a bit more work. You will have to write an annotation processor that, at each method, obtains the AST (abstract syntax tree or parse tree) for the method and then visits each expression in the method. The AST is compiler-specific.
The two best-known projects that do this are the Checker Framework and Project Lombok. Maybe you could take inspiration from their implementations, or even write your annotation processor on top of one of them.
I'm making a small project and I'm currently stuck on a way to achieve one of the capabilities I need.
Basically I want a method to execute when I'm calling an annotated method.For example
#PrintAnnotation
public void print(){
System.out.println("inside method");
The print annotation would just print extra test, so on calling the above method I would like to get
"Used print annotation"
"Inside method"
That's all.
I'm looking into the annotation processor API but there is no documentation anywhere except reading the javadoc which is crazy, and if I understand correctly its compile only so you cant change the original classes, only add.
I also found answers suggesting to use reflection, but to use reflection I need code triggered that checks if the method is annotated, but to do that I have to add an extra method to every method in the program, like
public void print(){
checkAnnotation();
System.out.println("test");
}
But I need it to work with only adding the annotation, not hundreds of one lines in every method of every class.
It is not possible through "only annotation" with no third party libraries and no custom code.
Annotation is only an annotation and nothing else.
It means you have to have those print and checkAnnotation methods which will detect presence of your Annotation on desired Target (Class,Method, Field...) and do what you'd like to. System.out.println("test"); definitely will not do that.
If you go with those print and checkAnnotation methods - create an utility with those methods and call print from anywhere instead of System.out.println.
But actually, what you try to achieve is about AOP. Your custom annotation can be used with it.
Then, you tagged question with spring tag, do you use Spring? It is a set of third party libraries and has AOP.
I reloaded on of my test application classes using Instrumentation#redefineClasses(ClassDefinition) method. When I tried adding a new method in the class file and call it from an existing method. It was not happy to for me to do so. But when I called some existing method and other Java Built-In Library methods, it was working fine.
My question is - Is this limitation known/acknowledged by Oracle or Open JDK implementations? I suspect even if you can redefine/retransform your classes using INstrumentation Manifest.MF file - there must be somre sort of limitations to how far you can go with it.
Does anyone have any experience in this thing?
From Instrumentation.html#redefineClasses:
The redefinition may change method bodies, the constant pool and attributes. The redefinition must not add, remove or rename fields or methods, change the signatures of methods, or change inheritance. These restrictions maybe be lifted in future versions. The class file bytes are not checked, verified and installed until after the transformations have been applied, if the resultant bytes are in error this method will throw an exception.
So the answer would be no, it's not possible.
There are some shared codes in both my Android project and my Java app server project. In the server project I overrode some toString() methods for logging, which are not needed in the Android project. Then I optimized the codes in my Android project with ProGuard. But when I decompiled the generated APK's classes.dex, the toString() methods were still there. It can remain as a defect for easy reverse-engineering if I don't remove them.
I have tried the -assumenosideeffects option but it doesn't work. Is there a way to remove these toString() methods by editing the ProGuard configuration or the Android project configuration?
There is no easy usage detection, any Object.toString could invoke your class' toString.
Mark every illuminating toString with your own compile-time annotation, like
#DevelopOnly
#Override
public String toString() { ...
And then use an annotation processor (apt) to remove the methods.
There are many nice examples out there.
Collect the classes in an AbstractProcessor and use ASM or another library to remove the methods.
No. Proguard won't remove code with references to it.
Your best option would be something to "force" the compiler to drop the lines:
use BuildConfig.DEBUG or a custom constant and wrap the calls in it.
If the compiler finds a constant expression which evaluates to false, it might drop the nested code.
I am using a large and unfamiliar API and would like to find all the ways of obtaining a particular class or interface. Is there a way in Javadocs to find all the methods that return such a type? If not, what are some good ways? (I'm using IntelliJ.)
In the standard Javadoc layout, you cannot do that specifically.
However, you can find all usages of a particular class, provided you are on the javadoc page for that class: at the top of the page, you have a set of links; one of them is called Use (it's right next to Class). It will indeed list all the uses of that class, whether it be as a return value or as an argument.
In IDEA itself, if you have the cursor on the class you want, you can press Alt+F7, you'll have the option to search for the uses of a particular class in your project, or your project PLUS the libraries you depend upon.
If you are using IntelliJ, for finding a particular Class, you can use Ctrl+N to find any class you have in your project. To find all methods that return a type, I would go with Find Usages option, Alt+F7. You can refine your results afterward.
Additionally, if you have a lengthy class open in your editor, you can use Ctrl-F12 to open the File Structure view. Start typing the returning type you are looking for, you will get a shorter list of potential methods you want.
Other than javadoc, you can get the return type of all methods of a specific class by Reflection.