Gradle eclipse plugin

Hi,

I’m trying to create a text plugin for our eclipse projects.

eclipse.gradle:

allprojects {
    apply plugin:'eclipse'
    eclipse {
        project {
            buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
            buildCommand 'org.eclipse.jdt.core.javabuilder'
            buildCommand 'edu.umd.cs.findbugs.plugin.eclipse.findbugsBuilder'
            natures = [
                    'org.eclipse.buildship.core.gradleprojectnature',
                    'org.eclipse.jdt.core.javanature',
                    'org.sonar.ide.eclipse.core.sonarNature',
                    'edu.umd.cs.findbugs.plugin.eclipse.findbugsNature']
        }
        classpath {
            file {
                beforeMerged { classpath ->
                    classpath.entries.removeAll { entry -> entry.kind == 'lib' || entry.kind == 'var' }
                }
                whenMerged { classpath ->
                    classpath.entries.findAll { entry -> entry.kind == 'lib' }*.exported = true
                }
            }

            if (env == 'dev') {
                downloadSources = true
                downloadJavadoc = true
            } else {
                downloadSources = false
                downloadJavadoc = false
            }
        }
    }
}

This produces this very clean .classpath, which is 1000% better than the mess that the default settings do.

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
        <classpathentry kind="output" path="bin"/>
        <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
</classpath>

What I would like to end up with, is this:

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
        <classpathentry kind="src" path="src">
                <attributes>
                        <attribute name="FROM_GRADLE_MODEL" value="true"/>
                </attributes>
        </classpathentry>
        <classpathentry exported="true" kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
        <classpathentry exported="true" kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
        <classpathentry kind="output" path="bin"/>
</classpath>

Hi,

Unfortunately there is no out-of-the-box build script support to do that. The reason being is that Buildship is optimised to use the import wizard UI functionality.

But it can be achieved with your approach. If you replace the whenMerged block with the one below, the desired .classpath will be generated.

whenMerged { classpath ->
    classpath.entries.findAll { entry -> entry.kind == 'lib' }*.exported = true
    withXml { classpathXml ->
    def classpathXmlNode = classpathXml.asNode()
    classpathXmlNode.appendNode('classpathentry', [kind: 'src', path: 'src'])
        .appendNode('attributes')
        .appendNode('attribute', [key: 'FROM_GRADLE_MODEL', value: 'true'])
    classpathXmlNode.appendNode('classpathentry',  [exported: 'true', kind: 'con', path: 'org.eclipse.buildship.core.gradleclasspathcontainer'])
    }
}

Thank you very much for the reply.

I had tried (although unsuccessfully) to do what you did here - the problem I ran into is that I couldn’t get rid of the entry after the XML node creation so you actually end up with both a container full of jars as well as the original jars still being on your classpath, which is not idle since both end up being on your classpath (duplicate jars).

    <classpathentry kind="lib" path="C:/Users/Aram/.gradle/caches/modules-2/files-2.1/org.glassfish.hk2/hk2-utils/2.4.0-b31/2c5cb698cfec8dde859c3db854178d03bf7248a6/hk2-utils-2.4.0-b31.jar" exported="true"/>
    <classpathentry kind="lib" path="C:/Users/Aram/.gradle/caches/modules-2/files-2.1/org.glassfish.hk2.external/aopalliance-repackaged/2.4.0-b31/5e7899ad02fd55f5651a5e5d1a70aee421ba2030/aopalliance-repackaged-2.4.0-b31.jar" exported="true"/>
    <classpathentry kind="lib" path="C:/Users/Aram/.gradle/caches/modules-2/files-2.1/javax.inject/javax.inject/1/6975da39a7040257bd51d21a231b76c915872d38/javax.inject-1.jar" exported="true"/>
    <classpathentry kind="lib" path="C:/Users/Aram/.gradle/caches/modules-2/files-2.1/org.jvnet.staxex/stax-ex/1.7.7/18bed5a0da27a6b43efe01282f2dc911b1cb3a72/stax-ex-1.7.7.jar" exported="true"/>
    <classpathentry kind="lib" path="C:/Users/Aram/.gradle/caches/modules-2/files-2.1/javax.xml.stream/stax-api/1.0-2/d6337b0de8b25e53e81b922352fbea9f9f57ba0b/stax-api-1.0-2.jar" exported="true"/>
    <classpathentry kind="src" path="src">
            <attributes>
                    <attribute key="FROM_GRADLE_MODEL" value="true"/>
            </attributes>
    </classpathentry>

What we would want is to get rid of the classpathentry elements in the XML in this case. It doesn’t look like there is a whenMerged block for the classpath container?

Thanks.

My snippet was just an example showing that you can manipulate the .classpath file however you want to. If you want to remove all jars from the classpath, you can do it by calling a conditional removeAll on the classpath entries:

whenMerged { classpath ->
    classpath.entries.findAll { entry -> entry.kind == 'lib' }*.exported = true
    classpath.entries.removeAll { entry -> entry.kind == 'lib' }
    withXml { classpathXml ->
    def classpathXmlNode = classpathXml.asNode()
    classpathXmlNode.appendNode('classpathentry', [kind: 'src', path: 'src'])
        .appendNode('attributes')
        .appendNode('attribute', [key: 'FROM_GRADLE_MODEL', value: 'true'])
    classpathXmlNode.appendNode('classpathentry',  [exported: 'true', kind: 'con', path: 'org.eclipse.buildship.core.gradleclasspathcontainer'])
    }
}

For completeness I’ve attached my complete example project to this entry.

Thank you very much. Worked great.