Difficulty extending Lombok - java

I want to create an annotation handler to extend the Java language. However I can't do this easily, because of the SCL files. I wanted to know if the Lombok developers made it this hard on purpose.
If I try extending JavacAnnotationHandler, it can't find it in lombok.jar because the name is JavacAnnotationHandler.SCL.Lombok. I cloned the GitHub repository but I keep getting errors with duplicate classes in the resources.after and resources.before package and Java 12 syntax. I am using lombok 1.18.8.
This is what I have.
import lombok.javac.JavacAnnotationHandler;
public class SingletonJavacHandler extends JavacAnnotationHandler<Singleton> {
It says "Cannot resolve symbol 'JavacAnnotationHandler'"

The SCL files are to hide lombok implementation classes from autocomplete dialogs in IDEs.
The resources-before and resources-after files should not be compiled. They are in the test resources, because our testing framework processes them.

Related

PsiClass to java.lang.Class

I'm developing plugin for IntelliJ IDEA. How can plugin get the name and version of libraries that are imported to the project that is being checked by plugin? I have PsiClass of the project, but cannot convert it to java.lang.Class. Maybe there's the way to get ClassLoader from PsiElement?
super.visitImportStatement(psiImport);
Class importedClass = Class.forName(psiImport.getQualifiedName(), true, psiImport.getClass().getClassLoader());
PsiImport.getClass().GetClassLoader() - returns ClassLoader of class PsiImportStatementImpl instead of ClassLoader of class that I've imported.
IntelliJ does mostly static analysis on your code. In fact, the IDE and the projects you run/debug have completely different classpaths. When you open a project, your dependencies are not added to the IDE classpath. Instead, the IDE will index the JARs, meaning it will automatically discover all the declarations (classes, methods, interfaces etc) and save them for later in a cache.
When you write code in your editor, the static analysis tool will leverage the contents of this index to validate your code and show errors when you're trying to use unknown definitions for example.
On the other hand, when you run a Main class from your project, it will spawn a new java process that has its own classpath. This classpath will likely contain every dependency declared in your module.
Knowing this, you should now understand why you can't "transform" a PsiClass to a corresponding Class.
Back to your original question:
How can plugin get the name and version of libraries that are imported to the project that is being checked by plugin?
You don't need to access Class objects for this. Instead, you can use IntelliJ SDK libraries. Here's an example:
Module mod = ModuleUtil.findModuleForFile(virtualFile,myProject);
ModuleRootManager.getInstance(mod).orderEntries().forEachLibrary(library -> {
// do your thing here with `library`
return true;
});

Java package versions - getting it right

I would like to get deeper understanding on how Java deals with different versions of Classes/Packages/etc., but couldn't find any resources or at least the best way to google for it. The problem is as follows.
Imagine we have some external package com.external.package that contains a definition of SomeInterface.
Now I write a java class MyClass that implements SomeInterface, and using com.external.package v1.0.0. Next I package a (lean) jar containing MyClass.
Now I plug this jar in another program that is looking for implementations of SomeInterface, but in it's dependencies, it is using com.external.package v2.0.0.
Is the reason I get Failed to find any class that implements SomeInterface that versions of SomeInterface don't match in the program and in the jar that contains a class extending it?
Basically the question I would like to find an answer for is what info do jars store regarding external dependencies? Does it store the exact versions of them and if they don't match at the runtime it complains? But why does it even allow running the program with references to same dependency, but different versions?
Is the reason I get Failed to find any class that implements SomeInterface that versions of SomeInterface don't match in the program and in the jar that contains a class extending it?
There is no "versioning" happening here. Simply, the error states no such class exists on the classpath. For example, you didn't put a -cp in your java command to add that extra JAR/class file.
Other reasons this could happen is that an API marks a class as deprecated in v1, then decides to remove it from v2. In which case, you best try to compile and test your code against the proper library versions before you package your own code. If you made an uber JAR, the classes should get shaded, and you probably wouldn't have missing classes.
Maven projects do have the concept of transitive, versioned dependencies, but you've not said anything about that
Seeing that the original question has found an answer already, it seems somewhat relevant to mention that Java Packages and JARs could be used for specifying package version information as discussed in the following documentation:
https://docs.oracle.com/javase/8/docs/technotes/guides/versioning/spec/versioning2.html#wp89936
Also, the Oracle Java Tutorials discuss them and further concepts around deployment of programs as JAR Files as documented here:
https://docs.oracle.com/javase/tutorial/deployment/jar/index.html

Using Java Immutables generated from a different package

I have a class in package foo, FooImmutableCatUser that wishes to use the Immutable, ImmutableCat object defined in package bar. However, I'm having issues getting FooImmutableCatUser in package foo to recognize ImmutableCat despite properly importing it. The import errors (unused import), and building yields the error: error: cannot find symbol at ImmutableCat.of().
My directory structure in bar looks like:
\bar
\models
\Cat.java
Cat.java is defined as
package bar.models;
import org.immutables.value.Value;
#Value.Immutable
public interface Cat {
String getName();
Object getValue();
}
This correctly compiles to the ImmutableCat object.
I try to access this in FooImmutableCatUser like so:
ImmutableCat.of("myString", myObject).
However, this throws the error: cannot find symbol above from both IntelliJ and Gradle.
I'm pretty sure I've seen code that uses Immutables from other packages before. How do you get gradle or IntelliJ to recognize Immutables from other packages while building? Is there a package dependency I need to list somewhere?
Edit: I have already tried enabling annotations with intellij via the APT instructions from Immutable. I've followed those instructions to the letter, but Immutables are still not recognized, possibly due to gradle and Intellij specifying different build output directories. Maybe that is the issue--I'll post back here if resolving that is actually the solution.

Find unused public members in Eclipse

I have a class which has 1600 public static members. I must found and delete the unused ones. Is there a way to do it in Eclipse.
There exists a Eclipse plugin Unused Code Detector (http://www.ucdetector.org/).
It can process a specific file or the entire project, searching for unused members/methods.
Ucdetector: You can install a plugin from this link. It works pretty well we have been using it in all our projects. It generates a html report as well it can mark warnings in eclipse. It helps you find unused classes, methods and variables. Only thing it dosen't do well is finding if a class is used via reflection only or where instance is created via spring. In these cases it still shows that class is unused.
http://ucdetector.sourceforge.net/update
Another thing you can do to clean up other types of unsed code is
GoTo Window>Preferences>Java>Compiler>Error/Warnings
Now look for uncessary code section and tweak the settings as you desire to cleanup further.
I hope it helps :)

How do I locate a clashing class in the IntelliJ classpath?

I'm trying IntelliJ IDEA after many years as an Eclipse user. At the same time, I'm working on a project that I've inherited with many dependencies.
One class will not compile, because IDEA claims that a method in another class does not exist. I can see the method in its source. Control-clicking on the class name in the IDEA editor takes me to the source that looks OK.
My hypothesis is that the compiler isn't using the class compiled from the source within the project, but a class with the same name, somewhere among my dozens of library jars.
How can I find out where IDEA's compiler is finding the clashing class?
CTRL-N and entering the class name should show you all of the matching classes from across the classpath, and which directory/JAR they're in. If there's a clash, you should have duplicates in that list.
Another possibility is that the source you have for the referenced class doesn't match the compiled version of that class.

Categories

Resources