IDEA module facets

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

IDEA module facets

Steffen Schäfer

Hello,


by now, Gradle only generates basic project/module configurations for IntelliJ IDEA when using “gradle idea”. This is enough for simple projects but not for e.g. war projects (GRADLE-1441). For such projects, you need extended configuration including facets and artifacts (and possibly even more).


I know that if I import a project as Gradle project, IntelliJ IDEA will generate the necessary configurations based on the Gradle tooling API (including the beforementioned facet and artifact). This is very good support as long as you only use built-in functionality (e.g. “war” plugin).


In my case I’m writing a GWT plugin (which isn’t known by IntelliJ IDEA) where I would have to configure an additional facet and manipulate the exploded-war artifact. When using IntelliJ IDEA’s built-in support for Gradle, my plugin is simply ignored and I didn’t find a way to adjust the configuration generated by IntelliJ IDEA. When using “gradle idea” there’s much more missing that would have to be added by my plugin (web facet, exploded war artifact).


That’s why I’d like to see improved support in Gradle to generate various configuration aspects (facets, artifacts, …) for IDEA using some kind of model instead of hand-coded xml transformations. This would help to improve the configuration produced by “gradle idea” and improve interoperability between plugins that want to manipulate those aspects.



I did some research on how this could be implemented and hacked a prototype for the web facet stuff (https://github.com/steffenschaefer/gradle/compare/idea-facet).


The following things are changed to make it work:

* The IdeaModule has a new property facets of type “IdeaFacetSet extends DomainObjectSet<IdeaFacet>” that defines some factory methods to create IdeaFacet instances with a given name and class.

* Each IdeaFacet creates an associated Facet instace that generates the XML content of the facet configuration. When creating this Facet instance, the PathFactory stuff is also done.

* The Module class is extended to create the FacetManager component in the *.iml file and delegates the generation of the Facet’s configuration to the given Facet instances

* IdeaWebFacet is the implementation needed to generate the “web” facet (the one that is related to GRADLE-1441).

* The IdeaPlugin adds an instance of the IdeaWebFacet with defaults if the “war” plugin is added


With those changes, the configuration of new facets would look like this:


idea {

   module {

       facets {

           facet('Crazy Facet', MyCustomFacet) {

               someProperty = ‘someValue’

           }

       }

   }

}


The configuration of existing facets (e.g. added by a plugin) would be something like this:


idea {

   module {

       facets {

           withType(IdeaWebFacet) {

               sourceRoots += project.sourceSets.someSourceSet.allSource.srcDirs

               webroot file('more_webapp_files'), '/'

           }

       }

   }

}


As mentioned before, It’s only a prototype by now that would need some love regarding JavaDocs/Tests/Documentation. But I think it’s good as a base for discussions.


Before doing further changes I would like to ask some questions:

* Is this something you would like to see in Gradle? Is there a chance for this to be accepted as PR?

* Is it Gradleish? How could it be changed to be more Gradleish?

* What other things besides JavaDocs/Tests/Documentation would have to be done?

* By now you will have two web facets when importing the project as Gradle project into IntelliJ IDEA as the one added by Gradle isn’t recognized by IDEA. Should the addition of facets be moved to an extra plugin (something like “idea-web”) to ensure interoperability?



With kind regards
Steffen Schäfer
Reply | Threaded
Open this post in threaded view
|

Re: IDEA module facets

johnrengelman
I was done in this code a few months ago as well in relation to supporting Grails applications with Gradle and IDEA. Personally, I think it makes sense to add this kind of support since it's strictly tied to the Idea Model…it's not a change that is pervasive across the entire project model.

Your changes so far are only confined to the IDEA plugin which basically is just adding some nice helper modeling around the IML generation. Everything you're doing can be done manually through the 'iml.withXml' builder. This still requires a person to run 'gradle idea' to generate the Idea project files and then open those. That works, but Idea has been putting a lot of effort into integrating with Gradle through the Tooling API so that I can directly import a project without having to generate the project files yourself.

So, I would suggest looking at expositing this data through the Tooling API model as well (org.gradle.tooling.model.idea.IdeaModel). Then IDEA would require some changes in their code base to use this new exposed model. However, I think this would be very powerful. IMO it makes more sense for IDEA to understand the Gradle model instead of Gradle trying to replicate the IDEA project files.

Just a thought. Don't know how the core-devs feel about this.

-- 
John Engelman

On Tuesday, January 7, 2014 at 6:27 AM, Steffen Schäfer [via Gradle] wrote:

Hello,


by now, Gradle only generates basic project/module configurations for IntelliJ IDEA when using “gradle idea”. This is enough for simple projects but not for e.g. war projects (GRADLE-1441). For such projects, you need extended configuration including facets and artifacts (and possibly even more).


I know that if I import a project as Gradle project, IntelliJ IDEA will generate the necessary configurations based on the Gradle tooling API (including the beforementioned facet and artifact). This is very good support as long as you only use built-in functionality (e.g. “war” plugin).


In my case I’m writing a GWT plugin (which isn’t known by IntelliJ IDEA) where I would have to configure an additional facet and manipulate the exploded-war artifact. When using IntelliJ IDEA’s built-in support for Gradle, my plugin is simply ignored and I didn’t find a way to adjust the configuration generated by IntelliJ IDEA. When using “gradle idea” there’s much more missing that would have to be added by my plugin (web facet, exploded war artifact).


That’s why I’d like to see improved support in Gradle to generate various configuration aspects (facets, artifacts, …) for IDEA using some kind of model instead of hand-coded xml transformations. This would help to improve the configuration produced by “gradle idea” and improve interoperability between plugins that want to manipulate those aspects.



I did some research on how this could be implemented and hacked a prototype for the web facet stuff (https://github.com/steffenschaefer/gradle/compare/idea-facet).


The following things are changed to make it work:

* The IdeaModule has a new property facets of type “IdeaFacetSet extends DomainObjectSet<IdeaFacet>” that defines some factory methods to create IdeaFacet instances with a given name and class.

* Each IdeaFacet creates an associated Facet instace that generates the XML content of the facet configuration. When creating this Facet instance, the PathFactory stuff is also done.

* The Module class is extended to create the FacetManager component in the *.iml file and delegates the generation of the Facet’s configuration to the given Facet instances

* IdeaWebFacet is the implementation needed to generate the “web” facet (the one that is related to GRADLE-1441).

* The IdeaPlugin adds an instance of the IdeaWebFacet with defaults if the “war” plugin is added


With those changes, the configuration of new facets would look like this:


idea {

   module {

       facets {

           facet('Crazy Facet', MyCustomFacet) {

               someProperty = ‘someValue’

           }

       }

   }

}


The configuration of existing facets (e.g. added by a plugin) would be something like this:


idea {

   module {

       facets {

           withType(IdeaWebFacet) {

               sourceRoots += project.sourceSets.someSourceSet.allSource.srcDirs

               webroot file('more_webapp_files'), '/'

           }

       }

   }

}


As mentioned before, It’s only a prototype by now that would need some love regarding JavaDocs/Tests/Documentation. But I think it’s good as a base for discussions.


Before doing further changes I would like to ask some questions:

* Is this something you would like to see in Gradle? Is there a chance for this to be accepted as PR?

* Is it Gradleish? How could it be changed to be more Gradleish?

* What other things besides JavaDocs/Tests/Documentation would have to be done?

* By now you will have two web facets when importing the project as Gradle project into IntelliJ IDEA as the one added by Gradle isn’t recognized by IDEA. Should the addition of facets be moved to an extra plugin (something like “idea-web”) to ensure interoperability?



With kind regards
Steffen Schäfer



If you reply to this email, your message will be added to the discussion below:
http://gradle.1045684.n5.nabble.com/IDEA-module-facets-tp5712168.html
To start a new topic under gradle-dev, email [hidden email]
To unsubscribe from gradle-dev, click here.
NAML

Reply | Threaded
Open this post in threaded view
|

Re: IDEA module facets

Adam Murdoch
In reply to this post by Steffen Schäfer

On 7 Jan 2014, at 10:26 pm, Steffen Schäfer <[hidden email]> wrote:

Hello,

by now, Gradle only generates basic project/module configurations for IntelliJ IDEA when using “gradle idea”. This is enough for simple projects but not for e.g. war projects (GRADLE-1441). For such projects, you need extended configuration including facets and artifacts (and possibly even more).

I know that if I import a project as Gradle project, IntelliJ IDEA will generate the necessary configurations based on the Gradle tooling API (including the beforementioned facet and artifact). This is very good support as long as you only use built-in functionality (e.g. “war” plugin).

In my case I’m writing a GWT plugin (which isn’t known by IntelliJ IDEA) where I would have to configure an additional facet and manipulate the exploded-war artefact.

Which facet(s) to you need to configure for your plugin?


--
Adam Murdoch
Gradle Co-founder
http://www.gradle.org
VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting
http://www.gradleware.com



Reply | Threaded
Open this post in threaded view
|

Re: IDEA module facets

Steffen Schäfer
I would need the "web" and "gwt" facets. In my test project they look like this:

    <facet type="web" name="Web">
      <configuration>
        <descriptors>
          <deploymentDescriptor name="web.xml" url="file://$MODULE_DIR$/web/WEB-INF/web.xml" />
        </descriptors>
        <webroots>
          <root url="file://$MODULE_DIR$/web" relative="/" />
        </webroots>
      </configuration>
    </facet>
    <facet type="gwt" name="GWT">
      <configuration>
        <setting name="compilerMaxHeapSize" value="512" />
        <setting name="gwtScriptOutputStyle" value="DETAILED" />
        <setting name="gwtSdkUrl" value="file://$MODULE_DIR$/../../gwt-2.5.1" />
        <setting name="webFacet" value="Web" />
      </configuration>
    </facet>

Additionally there's a little bit more configuration needed to make the project work in the IDE. E.g. the "exploded-war" artifact has to be configured to also include the output of the "gwt" facet:

  <artifact type="exploded-war" name="web:war exploded">
    <output-path>$PROJECT_DIR$/out/artifacts/web_war_exploded</output-path>
    <root id="root">
      <element id="javaee-facet-resources" facet="gwt-test/web/Web" />
      <element id="directory" name="WEB-INF">
        <element id="directory" name="classes">
          <element id="module-output" name="gwt-test" />
        </element>
        <element id="directory" name="lib">
          <element id="file-copy" path="$PROJECT_DIR$/../../gwt-2.5.1/gwt-servlet.jar" />
        </element>
      </element>
      <element id="gwt-compiler-output" facet="gwt-test/gwt/GWT" />
    </root>
  </artifact>

So It's not as easy as adding an additional facet.


2014/1/8 Adam Murdoch <[hidden email]>

On 7 Jan 2014, at 10:26 pm, Steffen Schäfer <[hidden email]> wrote:

Hello,

by now, Gradle only generates basic project/module configurations for IntelliJ IDEA when using “gradle idea”. This is enough for simple projects but not for e.g. war projects (GRADLE-1441). For such projects, you need extended configuration including facets and artifacts (and possibly even more).

I know that if I import a project as Gradle project, IntelliJ IDEA will generate the necessary configurations based on the Gradle tooling API (including the beforementioned facet and artifact). This is very good support as long as you only use built-in functionality (e.g. “war” plugin).

In my case I’m writing a GWT plugin (which isn’t known by IntelliJ IDEA) where I would have to configure an additional facet and manipulate the exploded-war artefact.

Which facet(s) to you need to configure for your plugin?


--
Adam Murdoch
Gradle Co-founder
http://www.gradle.org
VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting
http://www.gradleware.com