INRIA / spoon

Spoon is a metaprogramming library to analyze and transform Java source code. :spoon: is made with :heart:, :beers: and :sparkles:. It parses source files to build a well-designed AST with powerful analysis and transformation API.
http://spoon.gforge.inria.fr/
Other
1.74k stars 347 forks source link

using Spoon-maven-plugin with Lombok #3821

Open dallinbeutler opened 3 years ago

dallinbeutler commented 3 years ago

Hey, fairly new to Spoon here. I'm using Lombok to generate constructors for me on this class:

import lombok.*;

@Getter
@Setter
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
public class SourceData {
    private SystemID systemID = SystemID.UNDEFINED;
    private ServiceID serviceID = ServiceID.UNDEFINED;
    private SourceType sourceType = SourceType.UNKNOWN;

//using Lombok generated constructor (erroring here)
public static final SourceData UNDEFINED = new SourceData(
                                                SystemID.UNDEFINED,
                                                ServiceID.UNDEFINED,
                                                SourceType.UNKNOWN);
}

I'm trying to use the maven plugin to add another layer of functions to the class, but when I compile I get the error:

...
[INFO] --- spoon-maven-plugin:3.4.2:generate (default) @ entity ---
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by fr.inria.gforge.spoon.util.ClasspathHacker (file:/C:/Users/111770/.m2/repository/fr/inria/gforge/spoon/spoon-maven-plugin/3.4.2/spoon-maven-plugin-3.4.2.jar) to method java.net.URLClassLoader.addURL(java.net.URL)
WARNING: Please consider reporting this to the maintainers of fr.inria.gforge.spoon.util.ClasspathHacker
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
[INFO] Running in NOCLASSPATH mode (doc: http://spoon.gforge.inria.fr/launcher.html).
[INFO] Running in FULLCLASSPATH mode (doc: http://spoon.gforge.inria.fr/launcher.html).
[INFO] Spoon version 8.1.0
[INFO] running Spoon...
[INFO] start processing...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  3.188 s
[INFO] Finished at: 2021-03-03T19:07:14-07:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal fr.inria.gforge.spoon:spoon-maven-plugin:3.4.2:generate (default) on project entity: Exception during the spoonify of the target project.: The constructor SourceData(SystemID, ServiceID, SourceType) is undefined at D:\data\entityGenerator\src\main\java\com\entity\SourceData.java:51 -> [Help 1]
...

I'm assuming that this is because the Launcher doesn't know how to handle the all args constructor that would have been generated, but isn't, because this is source code.

So my question is, is there a maven plugin configuration in which I can make this still work? Is there a way to configure the pom.xml so that the spoon-maven-plugin analyzes the compiled bytecode?

andrewbwogi commented 3 years ago

Hello @dallinbeutler, I can take a look.

andrewbwogi commented 3 years ago

I think a new goal for a post-compilation phase can be added to Spoon-maven-plugin that uses spoon-decompiler to add class files as input resources.

In the meantime, have you considered using delombok? Spoon-maven-plugin adds to its input sources generated by other tools. It may be a safer option since bytecode can not always be decompiled to the correct source code.

dallinbeutler commented 3 years ago

yeah, I couldn't figure out how to get those steps to work with the maven plugin? Lombok and maven are both trying to work from the same source, and I don't know how best to chain this stuff.

And yeah, I'm using delombok for now. I figured with our teams impending integration of Spring Boot weaving backend stuff it would be a good question to bring up now.

Thanks again for taking a look!

santos-samuel commented 3 years ago

This is actually something that troubled me in the past and i kinda followed @andrewbwogi suggestion by generating the project packages and then decompiling them with spoon-decompiler. If it helps, i'll post the code i did to overcome this below:

launcher = new Launcher();
File projectDir = new File(projectPath);

// search for .jar files
String[] extensions = new String[]{"jar"};
Collection<File> packageFiles = FileUtils.listFiles(
        projectDir,
        extensions,
        true
);

for (File packageFile : packageFiles) {
    String packagePath = packageFile.getPath();

    // decompile .jar into a custom folder
    String decompiledPackageSourcesPath = Constants.DECOMPILED_SOURCES_PATH
            + packagePath.substring(packagePath.lastIndexOf("/")+1)
            + File.separator;

    new File(decompiledPackageSourcesPath).mkdirs();

    new DecompiledResource(
            packagePath,
            null,
            null,
            decompiledPackageSourcesPath
    );

    // add new folder as input resource
    launcher.addInputResource(decompiledPackageSourcesPath);
}