vscode-java icon indicating copy to clipboard operation
vscode-java copied to clipboard

How to handle extra classpath from generated code

Open minkyn opened this issue 7 years ago • 48 comments

I'm using Google's AutoValue and Protocol Buffer, both which generate source code under build/generated/source/.... However, each time I start vscode, this java plugin would automatically create a new .classpath file that overrides my manual edit.

Is the plugin going to handle the generated source code? Is there a workaround for now? Thanks.

minkyn avatar Apr 01 '17 15:04 minkyn

Are you using Maven or Gradle? With Maven, if you configure build-helper-maven-plugin, vscode-java 0.1.0 should setup the classpath accordingly.

Could you please attach a sample project?

fbricon avatar Apr 01 '17 15:04 fbricon

@minkyn ping. See previous comment

fbricon avatar May 30 '17 14:05 fbricon

That seems like a duplicate of #285. @minkyn are you using gradle?

fbricon avatar Aug 24 '17 15:08 fbricon

I have the same problem when using Maven to generate protocol buffer sources.

Source files are generated like so in the pom:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>3.0.1</version>
    <executions>
        <execution>
            <id>unpack-proto-dependencies</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>unpack-dependencies</goal>
            </goals>
            <configuration>
                <includeArtifactIds>artifact-name-here</includeArtifactIds>
                <excludeTransitive>true</excludeTransitive>
                <overWrite>true</overWrite>
                <outputDirectory>${project.build.directory}/generated-sources/proto</outputDirectory>                            
                <overWriteReleases>true</overWriteReleases>
                <overWriteSnapshots>true</overWriteSnapshots>
            </configuration>
        </execution>
    </executions>
</plugin>

we event try to add it to the test class path like so (not needed for mvn install to work).

<plugin>
    <!-- a hint for IDE's to add the java sources to the classpath -->
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <version>3.0.0</version>
    <executions>
        <execution>
            <id>01-add-test-sources</id>
            <phase>generate-test-sources</phase>
            <goals>
                <goal>add-test-source</goal>
            </goals>
            <configuration>
                <sources>
                    <source>${project.build.directory}/generated-sources/protobuf/java</source>
                </sources>
            </configuration>
        </execution>
    </executions>
</plugin>    

IzakMarais avatar Mar 09 '18 07:03 IzakMarais

The problem is compounded by interaction with https://github.com/redhat-developer/vscode-java/issues/322. Since I often need to close VSCode to get tests to run, the classpath gets messed up often.

IzakMarais avatar Mar 09 '18 07:03 IzakMarais

There seems to be support specifically for build-helper-maven-plugin. However, there are lots of plugins which generate sources and add them to the classpath, usually under target/generated-sources. In this case, build-helper-maven-plugin is not required. VS Code should automatically recognize this. Directories like target/generated-sources and target/generated-resources could be automatically added. Alternatively, an option to configure additional classpath folders per Maven module would be welcome.

unguiculus avatar Dec 11 '18 13:12 unguiculus

Same here. We generate Pojos for XML schemas using the jaxb2-maven-plugin. By default does classes are placed in target/generated-sources/jaxb/com/mypackage/MyGeneratedClass.java

Is there a chance to add a classpath by hand in VC code?

samba2 avatar Apr 09 '19 10:04 samba2

There seems to be support specifically for build-helper-maven-plugin. However, there are lots of plugins which generate sources and add them to the classpath, usually under target/generated-sources. In this case, build-helper-maven-plugin is not required. VS Code should automatically recognize this. Directories like target/generated-sources and target/generated-resources could be automatically added. Alternatively, an option to configure additional classpath folders per Maven module would be welcome.

@fbricon Any comments on the above?

I have this work project that places a few packages inside target/generated-sources and target/generated-resources and these are not being picked up by the plugin. Making it impossible for me to use VS Code with these Java projects.

rfgamaral avatar Jun 03 '19 18:06 rfgamaral

Hello,

Any hope this issue gets addressed? It prevents to use java-templating plugin, CXF plugins, and a bunch of other plugins.

Thanks a lot for the hard work, Romain

rmannibucau avatar Jun 03 '19 18:06 rmannibucau

Sure, we'll investigate this in the near feature. Can't commit to a timeframe though.

fbricon avatar Jun 03 '19 18:06 fbricon

Guys, if you want to make sure your use case is covered eventually, please add some small sample projects using various maven plugins contributing source folders.

fbricon avatar Jun 03 '19 19:06 fbricon

@fbricon here it is https://github.com/rmannibucau/generated-sources-demo, just try to code/compile in Main.java through vscode (works in CLI), it will miss the two generated folder created by java-templating and wadl cxf plugin.

rmannibucau avatar Jun 03 '19 19:06 rmannibucau

@rmannibucau I cloned it, ran a CLI build, opened vscode, the source folders have been added to the classpath automatically:

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
	<classpathentry kind="src" output="target/classes" path="src/main/java">
		<attributes>
			<attribute name="optional" value="true"/>
			<attribute name="maven.pomderived" value="true"/>
		</attributes>
	</classpathentry>
	<classpathentry kind="src" output="target/classes" path="target/generated-sources/java-templates">
		<attributes>
			<attribute name="optional" value="true"/>
			<attribute name="maven.pomderived" value="true"/>
		</attributes>
	</classpathentry>
	<classpathentry kind="src" output="target/classes" path="target/generated/src/main/java">
		<attributes>
			<attribute name="optional" value="true"/>
			<attribute name="maven.pomderived" value="true"/>
		</attributes>
	</classpathentry>
	<classpathentry kind="src" output="target/test-classes" path="src/test/java">
		<attributes>
			<attribute name="optional" value="true"/>
			<attribute name="maven.pomderived" value="true"/>
			<attribute name="test" value="true"/>
		</attributes>
	</classpathentry>
	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
		<attributes>
			<attribute name="maven.pomderived" value="true"/>
		</attributes>
	</classpathentry>
	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
		<attributes>
			<attribute name="maven.pomderived" value="true"/>
		</attributes>
	</classpathentry>
	<classpathentry kind="src" path="target/generated-sources/annotations">
		<attributes>
			<attribute name="optional" value="true"/>
			<attribute name="maven.pomderived" value="true"/>
			<attribute name="ignore_optional_problems" value="true"/>
			<attribute name="m2e-apt" value="true"/>
		</attributes>
	</classpathentry>
	<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
		<attributes>
			<attribute name="optional" value="true"/>
			<attribute name="maven.pomderived" value="true"/>
			<attribute name="ignore_optional_problems" value="true"/>
			<attribute name="m2e-apt" value="true"/>
			<attribute name="test" value="true"/>
		</attributes>
	</classpathentry>
	<classpathentry kind="output" path="target/classes"/>
</classpath>

fbricon avatar Jun 03 '19 19:06 fbricon

Hmm, does it mean it needs m2 lifecycle mapping plugin? Or do you use a dev version? Can you also drop target/classes and give it another try?

rmannibucau avatar Jun 03 '19 20:06 rmannibucau

for the sources to be regenerated on incremental build, an m2e lifecycle mapping/connector would need to be required yes. But if the sources are generated outside vscode (CLI build for instance), in theory we should be able to recover from the compilation errors by refreshing the compilation units on the server side. But those generated sources are not detected because of a hack we had to introduce to prevent nasty feedback loops between jdt.ls and vscode. jdt.ls would generate the sources automatically (from annotation processing), vscode detects the changes, sending change deltas back to the server, messing up the compilation units, causing weird error reports. So I guess we need to be smarter in that case.

fbricon avatar Jun 03 '19 21:06 fbricon

I seem to have a slightly different issue, but related, I think.

I'm not a Java developer and my Java/Maven knowledge is very limited. But my team inherited this Java project which we'll be working on the frontend side only. The project works fine with IntelliJ and we can use that to work on the project but I'm trying to setup this with VS Code cause it's our editor of choice for frontend.

The problem is that this Java project is configured with an internal Maven plugin that generates sources (so I can't post a sample project) and places them at target/generated-sources/java and this plugin is not picking that for the classpath, but IntelliJ does.

Maybe the issue here is that the generated sources come from a custom internal plugin and not something like templating-maven-plugin as in the sample project posted by @rmannibucau?

I was able to workaround it with something like this:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <version>3.0.0</version>
    <executions>
        <execution>
            <id>addSource</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>add-source</goal>
            </goals>
            <configuration>
                <sources>
                    <source>${project.basedir}/target/generated-sources/java</source>
                </sources>
            </configuration>
        </execution>
    </executions>
</plugin>

But it would be much better if, somehow, this plugin could pick whatever is at ${project.basedir}/target/generated-sources/java by default and automatically since that seems to be a standard folder for generated sources?

rfgamaral avatar Jun 04 '19 09:06 rfgamaral

No it's not a standard folder. Multiple plugins generate different content in subdirectories of ${project.basedir}/target/generated-sources. Having 2 plugins writing content to the same directory (target/generated-sources/java) might cause some issues (one plugin overwriting the other one's output)

fbricon avatar Jun 04 '19 19:06 fbricon

This is a common default for annotation processors but not for generating sources plugin so nothing better than adding a source folder in vscode or supporting lifecycle mapping - but not sure it is that great to use eclipse here :s

rmannibucau avatar Jun 04 '19 19:06 rmannibucau

Having 2 plugins writing content to the same directory (target/generated-sources/java) might cause some issues (one plugin overwriting the other one's output)

Not sure what you mean by this, but I only have 1 plugin writing content to target/generated-sources/java, it's just not being picked up by vscode-java unless I make it aware with the build-helper-maven-plugin plugin configuration above.

rfgamaral avatar Jun 04 '19 19:06 rfgamaral

Similar issue here. We do a

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <version>3.0.0</version>
    <executions>
        <execution>
            <id>add-integration-test-source</id>
            <phase>generate-test-sources</phase>
            <goals>
                <goal>add-test-source</goal>
            </goals>
            <configuration>
                <sources>
                    <source>src/integration-test/java</source>
                </sources>
            </configuration>
        </execution>
        <execution>
            <id>add-integration-test-resource</id>
            <phase>generate-test-resources</phase>
            <goals>
                <goal>add-test-resource</goal>
            </goals>
            <configuration>
                <resources>
                    <resource>
                        <directory>src/integration-test/resources</directory>
                    </resource>
                </resources>
            </configuration>
        </execution>
    </executions>
</plugin>

When trying to run/debug tests from within VSCode that fall under src/integration-test/java the tests won't run. Works just fine if I run them manually with maven in my terminal.

agsimeonov avatar Jun 18 '19 19:06 agsimeonov

Same issue with Apache NiFi: https://github.com/apache/nifi It uses ANTLR to generate sources for its expression language DSL. It uses the ANTLR maven plugin:

            <plugin>
                <groupId>org.antlr</groupId>
                <artifactId>antlr3-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>antlr</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

It ends up putting generated sources in target/generated-sources/antlrv3 which do not get picked up by VSCode.

achristianson avatar Jul 02 '19 19:07 achristianson

~Have this in a project that is not working:~

I was rereading the thread and found out, this was actually working for @rfgamaral. I looked more into it and noticed the error messages are looking more like this: https://github.com/redhat-developer/vscode-java/issues/551. The actual issue was interference of a linting plugin, that wasn't aware of the generated sources. (Also I'm using the coc-java fork of this project). So it looks like build-helper-maven-plugin is working :)

            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>build-helper-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <id>generated-folder</id>
                        <goals>
                            <goal>add-source</goal>
                        </goals>
                        <configuration>
                            <sources>
                                <source>${basedir}/src-gen/main/java</source>
                            </sources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

andys8 avatar Jul 03 '19 14:07 andys8

@fbricon Here is a grpc example: https://github.com/jackielii/grpc-java-example

The problem I see is not that the generated sources are not added in the .classpath, but the grpc files are not generated. Whenever I re-open the project, it removes the generated sources...

jackielii avatar Jul 18 '19 09:07 jackielii

This issue is causing one of my team members to move off of VS Code as well. We are using the gRPC protobuf plugin which places generated files here: target/generated-sources/protobuf/java. These are picked up fine by Eclipse and IntelliJ just fine, but not by VS Code. Would love to see a fix for this.

jmartin127 avatar Aug 05 '19 19:08 jmartin127

same here, with gradle google protobuf plugin, the generated folder is no way to recognized

rory-ye-nv avatar Sep 12 '19 02:09 rory-ye-nv

Same here with auto-generated jooq sources. Manually editing .classpath worked - but who knows how long this will last.

gombosg avatar Sep 25 '19 14:09 gombosg

Hi all. I'm having the same issues this GWT, that generates some classes and puts it in ${project.build.directory}/generated-sources/gwt. I added the following execution in pom.xml:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <executions>
        <execution>
            <id>add-source</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>add-source</goal>
            </goals>
            <configuration>
                <sources>
                    <source>${project.build.directory}/generated-sources/gwt</source>
                </sources>
            </configuration>
        </execution>
    </executions>
</plugin>

But apparently vscode doesn't add anything in the .classpath file.

A working demo can be found at https://github.com/lorthirk/kapua/tree/change-generatedSourcesMaven/console

lorthirk avatar Oct 24 '19 10:10 lorthirk

I have a detail that may be important to my case: all the console modules that are missing the target/generated-sources/gwt in classpath are only compiled in a specific console Maven profile. Anyway I tried to add both the console profile in every org.eclipse.m2e.core.prefs under .settings directory, in the activeProfile option, and even enabled all the console modules with the standard profile, but the code is still not recognized.

lorthirk avatar Oct 25 '19 07:10 lorthirk

我看不太懂这些英文,但是我大概知道你们应该还没有解决这个问题。如何能像 Intellig Idea 那样智能呢?

XuPengfei-1020 avatar Nov 12 '19 09:11 XuPengfei-1020

我看不太懂这些英文,但是我大概知道你们应该还没有解决这个问题。如何能像 Intellig Idea 那样智能呢?

同时又能保持 vscode 的轻量级,不要像 Intellig Idea 这么臃肿,似乎有点难。

XuPengfei-1020 avatar Nov 12 '19 10:11 XuPengfei-1020