// Copyright (C) 2024 Gradle, Inc.
//
// Licensed under the Creative Commons Attribution-Noncommercial-ShareAlike 4.0 International License.;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

[[eclipse_plugin]]
= The Eclipse Plugins

WARNING: The Eclipse Plugins are not fully compatible with the <<configuration_cache_status.adoc#config_cache:plugins:core,Configuration Cache>>. When applied, the Configuration Cache is automatically disabled.

The Eclipse plugins generate files that are used by the http://eclipse.org[Eclipse IDE], thus making it possible to import the project into Eclipse (`File` - `Import...` - `Existing Projects into Workspace`).

The `eclipse-wtp` is automatically applied whenever the `eclipse` plugin is applied to a <<war_plugin.adoc#war_plugin,War>> or <<ear_plugin.adoc#ear_plugin,Ear>> project. For utility projects (i.e. <<java_plugin.adoc#java_plugin,Java>> projects used by other web projects), you need to apply the `eclipse-wtp` plugin explicitly.

What exactly the `eclipse` plugin generates depends on which other plugins are used:

.Eclipse plugin behavior
[%header%autowidth,compact]
|===
| Plugin | Description

| None
| Generates minimal `.project` file.

| <<java_plugin.adoc#java_plugin,Java>>
| Adds Java configuration to `.project`. Generates `.classpath` and JDT settings file.

| <<groovy_plugin.adoc#groovy_plugin,Groovy>>
| Adds Groovy configuration to `.project` file.

| <<scala_plugin.adoc#scala_plugin,Scala>>
| Adds Scala support to `.project` and `.classpath` files.

| <<war_plugin.adoc#war_plugin,War>>
| Adds web application support to `.project` file.

| <<ear_plugin.adoc#ear_plugin,Ear>>
| Adds ear application support to `.project` file.
|===

The `eclipse-wtp` plugin generates all WTP settings files and enhances the `.project` file. If a <<java_plugin.adoc#java_plugin,Java>> or <<war_plugin.adoc#war_plugin,War>> is applied, `.classpath` will be extended to get a proper packaging structure for this utility library or web application project.

Both Eclipse plugins are open to customization and provide a standardized set of hooks for adding and removing content from the generated files.


[[sec:eclipse_usage]]
== Usage

To use either the Eclipse or the Eclipse WTP plugin, include one of the lines in your build script.

Using the Eclipse plugin:

====
include::sample[dir="snippets/ide/eclipse/kotlin",files="build.gradle.kts[tags=use-eclipse-plugin]"]
include::sample[dir="snippets/ide/eclipse/groovy",files="build.gradle[tags=use-eclipse-plugin]"]
====

Using the Eclipse WTP plugin:

====
include::sample[dir="snippets/ide/eclipse/kotlin",files="build.gradle.kts[tags=use-eclipse-wtp-plugin]"]
include::sample[dir="snippets/ide/eclipse/groovy",files="build.gradle[tags=use-eclipse-wtp-plugin]"]
====

_Note:_ Internally, the `eclipse-wtp` plugin also applies the `eclipse` plugin so you don't need to apply both.

Both Eclipse plugins add a number of tasks to your projects. The main tasks that you will use are the `eclipse` and `cleanEclipse` tasks.

[[sec:eclipse_tasks]]
== Tasks

The Eclipse plugins add the tasks shown below to a project.

[[eclipsetasks]]
=== Eclipse Plugin tasks

`eclipse` — link:{groovyDslPath}/org.gradle.api.Task.html[Task]::
_Depends on_: all Eclipse configuration file generation tasks
+
Generates all Eclipse configuration files

`cleanEclipse` — link:{groovyDslPath}/org.gradle.api.tasks.Delete.html[Delete]::
_Depends on_: all Eclipse configuration file clean tasks
+
Removes all Eclipse configuration files

`cleanEclipseProject` — link:{groovyDslPath}/org.gradle.api.tasks.Delete.html[Delete]::
+
Removes the `.project` file.

`cleanEclipseClasspath` — link:{groovyDslPath}/org.gradle.api.tasks.Delete.html[Delete]::
+
Removes the `.classpath` file.

`cleanEclipseJdt` — link:{groovyDslPath}/org.gradle.api.tasks.Delete.html[Delete]::
+
Removes the `.settings/org.eclipse.jdt.core.prefs` file.

`eclipseProject` — link:{groovyDslPath}/org.gradle.plugins.ide.eclipse.GenerateEclipseProject.html[GenerateEclipseProject]::
+
Generates the `.project` file.

`eclipseClasspath` — link:{groovyDslPath}/org.gradle.plugins.ide.eclipse.GenerateEclipseClasspath.html[GenerateEclipseClasspath]::
+
Generates the `.classpath` file.

`eclipseJdt` — link:{groovyDslPath}/org.gradle.plugins.ide.eclipse.GenerateEclipseJdt.html[GenerateEclipseJdt]::
+
Generates the `.settings/org.eclipse.jdt.core.prefs` file.

[[eclipsewtptasks]]
=== Eclipse WTP Plugin — additional tasks

`cleanEclipseWtpComponent` — link:{groovyDslPath}/org.gradle.api.tasks.Delete.html[Delete]::
+
Removes the `.settings/org.eclipse.wst.common.component` file.

`cleanEclipseWtpFacet` — link:{groovyDslPath}/org.gradle.api.tasks.Delete.html[Delete]::
+
Removes the `.settings/org.eclipse.wst.common.project.facet.core.xml` file.

`eclipseWtpComponent` — link:{groovyDslPath}/org.gradle.plugins.ide.eclipse.GenerateEclipseWtpComponent.html[GenerateEclipseWtpComponent]::
+
Generates the `.settings/org.eclipse.wst.common.component` file.

`eclipseWtpFacet` — link:{groovyDslPath}/org.gradle.plugins.ide.eclipse.GenerateEclipseWtpFacet.html[GenerateEclipseWtpFacet]::
+
Generates the `.settings/org.eclipse.wst.common.project.facet.core.xml` file.


[[sec:eclipse_configuration]]
== Configuration


[[eclipse-configuration]]
.Configuration of the Eclipse plugins
[%header%autowidth,compact]
|===
| Model | Reference name | Description

| link:{groovyDslPath}/org.gradle.plugins.ide.eclipse.model.EclipseModel.html[EclipseModel]
| `eclipse`
| Top level element that enables configuration of the Eclipse plugin in a DSL-friendly fashion.

| link:{groovyDslPath}/org.gradle.plugins.ide.eclipse.model.EclipseProject.html[EclipseProject]
| `eclipse.project`
| Allows configuring project information

| link:{groovyDslPath}/org.gradle.plugins.ide.eclipse.model.EclipseClasspath.html[EclipseClasspath]
| `eclipse.classpath`
| Allows configuring classpath information.

| link:{groovyDslPath}/org.gradle.plugins.ide.eclipse.model.EclipseJdt.html[EclipseJdt]
| `eclipse.jdt`
| Allows configuring jdt information (source/target Java compatibility).

| link:{groovyDslPath}/org.gradle.plugins.ide.eclipse.model.EclipseWtpComponent.html[EclipseWtpComponent]
| `eclipse.wtp.component`
| Allows configuring wtp component information only if `eclipse-wtp` plugin was applied.

| link:{groovyDslPath}/org.gradle.plugins.ide.eclipse.model.EclipseWtpFacet.html[EclipseWtpFacet]
| `eclipse.wtp.facet`
| Allows configuring wtp facet information only if `eclipse-wtp` plugin was applied.
|===

[[sec:eclipse_customizing_the_generated_files]]
== Customizing the generated files

The Eclipse plugins allow you to customize the generated metadata files. The plugins provide a DSL for configuring model objects that model the Eclipse view of the project. These model objects are then merged with the existing Eclipse XML metadata to ultimately generate new metadata. The model objects provide lower level hooks for working with domain objects representing the file content before and after merging with the model configuration. They also provide a very low level hook for working directly with the raw XML for adjustment before it is persisted, for fine tuning and configuration that the Eclipse and Eclipse WTP plugins do not model.

[[sec:merging_with_eclipse_files]]
=== Merging

Sections of existing Eclipse files that are also the target of generated content will be amended or overwritten, depending on the particular section. The remaining sections will be left as-is.

[[sec:complete_rewrite_of_eclipse_files]]
==== Disabling merging with a complete rewrite

To completely rewrite existing Eclipse files, execute a clean task together with its corresponding generation task, like "`gradle cleanEclipse eclipse`" (in that order). If you want to make this the default behavior, add "`tasks.eclipse.dependsOn(cleanEclipse)`" to your build script. This makes it unnecessary to execute the clean task explicitly.

This strategy can also be used for individual files that the plugins would generate. For instance, this can be done for the "`.classpath`" file with "`gradle cleanEclipseClasspath eclipseClasspath`".

[[sec:hooking_into_the_eclipse_generation_lifecycle]]
=== Hooking into the generation lifecycle

The Eclipse plugins provide objects modeling the sections of the Eclipse files that are generated by Gradle. The generation lifecycle is as follows:

. The file is read; or a default version provided by Gradle is used if it does not exist
. The `beforeMerged` hook is executed with a domain object representing the existing file
. The existing content is merged with the configuration inferred from the Gradle build or defined explicitly in the eclipse DSL
. The `whenMerged` hook is executed with a domain object representing contents of the file to be persisted
. The `withXml` hook is executed with a raw representation of the XML that will be persisted
. The final XML is persisted

[[eclipse-plugin-hooks]]
==== Advanced configuration hooks

The following list covers the domain object used for each of the Eclipse model types:

link:{groovyDslPath}/org.gradle.plugins.ide.eclipse.model.EclipseProject.html[EclipseProject]::
  * `beforeMerged { link:{javadocPath}/org/gradle/plugins/ide/eclipse/model/Project.html[Project] arg -&gt; ... }`
  * `whenMerged { link:{javadocPath}/org/gradle/plugins/ide/eclipse/model/Project.html[Project] arg -&gt; ... }`
  * `withXml { link:{javadocPath}/org/gradle/api/XmlProvider.html[XmlProvider] arg -&gt; ... }`

link:{groovyDslPath}/org.gradle.plugins.ide.eclipse.model.EclipseClasspath.html[EclipseClasspath]::
  * `beforeMerged { link:{javadocPath}/org/gradle/plugins/ide/eclipse/model/Classpath.html[Classpath] arg -&gt; ... }`
  * `whenMerged { link:{javadocPath}/org/gradle/plugins/ide/eclipse/model/Classpath.html[Classpath] arg -&gt; ... }`
  * `withXml { link:{javadocPath}/org/gradle/api/XmlProvider.html[XmlProvider] arg -&gt; ... }`

link:{groovyDslPath}/org.gradle.plugins.ide.eclipse.model.EclipseWtpComponent.html[EclipseWtpComponent]::
  * `beforeMerged { link:{javadocPath}/org/gradle/plugins/ide/eclipse/model/WtpComponent.html[WtpComponent] arg -&gt; ... }`
  * `whenMerged { link:{javadocPath}/org/gradle/plugins/ide/eclipse/model/WtpComponent.html[WtpComponent] arg -&gt; ... }`
  * `withXml { link:{javadocPath}/org/gradle/api/XmlProvider.html[XmlProvider] arg -&gt; ... }`

link:{groovyDslPath}/org.gradle.plugins.ide.eclipse.model.EclipseWtpFacet.html[EclipseWtpFacet]::
  * `beforeMerged { link:{javadocPath}/org/gradle/plugins/ide/eclipse/model/WtpFacet.html[WtpFacet] arg -&gt; ... }`
  * `whenMerged { link:{javadocPath}/org/gradle/plugins/ide/eclipse/model/WtpFacet.html[WtpFacet] arg -&gt; ... }`
  * `withXml { link:{javadocPath}/org/gradle/api/XmlProvider.html[XmlProvider] arg -&gt; ... }`

link:{groovyDslPath}/org.gradle.plugins.ide.eclipse.model.EclipseJdt.html[EclipseJdt]::
  * `beforeMerged { link:{javadocPath}/org/gradle/plugins/ide/eclipse/model/Jdt.html[Jdt] arg -&gt; ... }`
  * `whenMerged { link:{javadocPath}/org/gradle/plugins/ide/eclipse/model/Jdt.html[Jdt] arg -&gt; ... }`
  * `withProperties { arg -&gt; }` argument type => link:{javaApi}/java/util/Properties.html[`java.util.Properties`]

[[sec:partial-overwrite]]
==== Partial overwrite of existing content

A complete overwrite causes all existing content to be discarded, thereby losing any changes made directly in the IDE. Alternatively, the `beforeMerged` hook makes it possible to overwrite just certain parts of the existing content. The following example removes all existing dependencies from the `Classpath` domain object:

.Partial Overwrite for Classpath
====
include::sample[dir="snippets/ide/eclipse/kotlin",files="build.gradle.kts[tags=module-before-merged]"]
include::sample[dir="snippets/ide/eclipse/groovy",files="build.gradle[tags=module-before-merged]"]
====

The resulting `.classpath` file will only contain Gradle-generated dependency entries, but not any other dependency entries that may have been present in the original file. (In the case of dependency entries, this is also the default behavior.) Other sections of the `.classpath` file will be either left as-is or merged. The same could be done for the natures in the `.project` file:

====
include::sample[dir="snippets/ide/eclipse/kotlin",files="build.gradle.kts[tags=project-before-merged]"]
include::sample[dir="snippets/ide/eclipse/groovy",files="build.gradle[tags=project-before-merged]"]
====

[[sec:eclipse_modify_domain_objects]]
==== Modifying the fully populated domain objects

The `whenMerged` hook allows to manipulate the fully populated domain objects. Often this is the preferred way to customize Eclipse files. Here is how you would export all the dependencies of an Eclipse project:

====
include::sample[dir="snippets/ide/eclipse/kotlin",files="build.gradle.kts[tags=module-when-merged]"]
include::sample[dir="snippets/ide/eclipse/groovy",files="build.gradle[tags=module-when-merged]"]
====

[[sec:eclipse_modify_xml]]
==== Modifying the XML representation

The `withXml` hook allows to manipulate the in-memory XML representation just before the file gets written to disk. Although Groovy's XML support and Kotlin's extension functions make up for a lot, this approach is less convenient than manipulating the domain objects. In return, you get total control over the generated file, including sections not modeled by the domain objects.

====
include::sample[dir="snippets/ide/eclipse/kotlin",files="build.gradle.kts[tags=wtp-with-xml]"]
include::sample[dir="snippets/ide/eclipse/groovy",files="build.gradle[tags=wtp-with-xml]"]
====

[[sec:test-sources]]
== Separation of test classpath entries

Eclipse defines only one classpath per project which implies limitations on how Gradle projects can be mapped.
Eclipse 4.8 introduced the concept of link:https://www.eclipse.org/eclipse/news/4.8/jdt.php#jdt-test-sources[test sources].
This feature allows the Eclipse plugin to define better separation between test and non-test sources.

The Eclipse classpath consists of classpath entries: source directories, jar files, project dependencies, etc.
Each classpath entry can have a list of classpath attributes, where the attributes are string key-value pairs.
There are two classpath attribute relevant for test sources: `test` and `without_test_code`, both of which can have `true` or `false` as values.

If a source directory has the `test=true` classpath attribute then the contents are considered test sources.
Test sources have access to non-test sources, but non-test sources don't have access to test sources.
Similarly, test sources can only reference classes from a jar file if the jar file has the `test=true` classpath attribute.
For project dependencies if the `test=true` attribute is present the classes in the target project are visible to test sources.
If the `without_test_code=false` attribute is present then the test sources of the target project are also accessible.  By default, test code is not available (which can be thought of as implicitly having `without_test_code=true`).

The following rules apply for the test attribute declaration when generating the Eclipse classpath:

- Source sets and dependency configurations are categorized as test if their name contain the 'test' substring, irrespective of case.
- All source sets and dependency configurations defined by the JVM test suite plugin are categorized as test.
- Source directories have the `test=true` classpath attribute if the container source set is a test source set.
- Jar files and project dependencies have the `test=true` attribute if they are present only in test dependency configurations.
- Project dependencies have the `without_test_sources=false` attribute if the target project applies the java-test-fixtures plugin.

You can customize the test source sets and configurations:

====
include::sample[dir="snippets/ide/eclipse/kotlin",files="build.gradle.kts[tags=test-sources]"]
include::sample[dir="snippets/ide/eclipse/groovy",files="build.gradle[tags=test-sources]"]
====

TIP: Consider migrating away from manual definition of additional test source sets and towards the use of the <<jvm_test_suite_plugin#jvm_test_suite_plugin,JVM Test Suite Plugin>> in scenarios like this.

You can also customize if a project should expose test sources to upstream project dependencies via the `containsTestFixtures` property.

====
include::sample[dir="snippets/ide/eclipse/kotlin",files="build.gradle.kts[tags=test-fixtures]"]
include::sample[dir="snippets/ide/eclipse/groovy",files="build.gradle[tags=test-fixtures]"]
====

Note, that this configuration also applies to the classpath of Buildship projects.
