Intellij IDEA support for buildr
This extension provides tasks to generate Intellij IDEA project files by issuing:
$ buildr iidea:generate
This task will generate an .iml file for every project (or sub-project) and a .ipr that you can directly open for the root project.
The generated project files can be removed by issuing;
$ buildr iidea:clean
The iidea task generates the project files based on the settings of each project and extension specific settings. The main and test source trees are added to the .iml file for each project as are the respective resource directories. The target and report directories are excluded from the project. If the project files exist on the file system the extension will replace specific component sections in the xml with the generated component configurations.
Dependencies come in two forms. Dependencies on other projects and dependencies on external jars. Dependencies on other projects are added as module dependencies in the .iml while jars are added as regular file dependencies. Dependencies are exported from the .iml file if they are compile dependencies. If a artifact that matches dependency but has a classifier of ‘sources’ is present then it is configured as the source for the dependency. Note: Use “buildr artifacts:sources” to download the source for dependencies.
Installation
The extension is packaged as a gem named “buildr-iidea”, consult the ruby gems installation steps but typically it is either
sudo gem install buildr-iidea
for MRI ruby or
jgem install buildr-iidea
for jruby.
The user then needs to add the following require into the build file:
require 'buildr_iidea'
Warning
The iidea task may generate project files that conflict with the files generated by the built-in ‘idea’ and ‘idea7x’ tasks. As a result the built-in tasks would fail if ran while the extension is present. To avoid this problem the extension removes these tasks.
Idea Specific Directives
The extension specific settings of sub-projects inherit the parent projects settings unless overwritten.
Project file naming
The extension will use the last element of the projects name when generating the .ipr and .iml files. i.e. A project named “foo” will generate “foo.iml” and “foo.ipr” while a project named “foo:bar” will generate “bar/bar.iml” and no ipr. (The .ipr project files are only generated for base project). The name can be modified by setting the “ipr.suffix” or “iml.suffix” settings which specifies the suffix appended to the file names. The user can also override the name completely by setting “ipr.id” or “iml.id”.
Example: Setting id
define "foo" do
ipr.id = "beep"
define "bar" do
iml.id = "baz"
end
end
Will generate:
beep.ipr
foo.iml
/baz.iml
Example: Setting suffix
define "foo" do
ipr.suffix = "-suffix1"
iml.suffix = "-suffix2"
define "bar"
end
Will generate:
foo-suffix1.ipr
foo-suffix2.iml
/-suffix2.iml
Disabling project file generation
The extension will not generate an iml file for a project if the “project.no_iml” method is invoked. Generation of ipr files can be disabled by invoking the method “project.no_ipr”.
Example
define "foo" do
project.no_ipr
define "bar" do
project.no_iml
end
end
Will generate:
foo.iml
Disabling generation of content section in .iml file
The extension will not generate a content section in an iml file if the “iml.skip_content!” method is invoked. This can be useful if a project is just exporting dependencies and has no associated source code. This may also be of use in scenarios where the build is repackaging an existing jar with more meta-data or the project is just a container for other projects.
Example
define "foo" do
iml.skip_content!
end
VCS Integration
The extension will attempt to guess the VCS type of the project by looking for a .svn or .git directory in the base projects directory. If either of these are set it will configure the component as appropriate. Otherwise the user will need to manually specify the project to one of either ‘Git’ or ‘svn’ using the ipr.vcs setting.
Example
define "foo" do
ipr.vcs = 'Git'
end
Dependency generation
A file dependency that exists in the local maven 2 repository is stored in the IML file relative to the $MAVEN_REPOSITORY$ environment variable (that defaults to ~/.m2/repository). The user can override the environment variable by setting the “iml.local_repository_env_override” setting. If the dependency does not exist in to maven repository or the “iml.local_repository_env_override” setting is set to nil, then the path stored in the IML is relative to the IML file.
Example: Setting local_repository_env_override
define "foo" do
iml.local_repository_env_override = nil
compile.with 'group:id:jar:1.0'
end
Will generate a dependency with a path like:
jar:///home/peter/.m2/repository/group/id/1.0/id-1.0.jar!/
rather than the default
jar://$MAVEN_REPOSITORY$/group/id/1.0/id-1.0.jar!/
Example: A dependency outside the maven repository
define "foo" do
compile.with _("foos-dep.jar")
end
Will generate a dependency with a path like:
jar://$MODULE_DIR$/foo-dep.jar!/
Module Facets
Facets are IDEAs mechanism for adding support for languages, tools and frameworks other than core java. A facet can be added to a project so that it can be deployed as a web application or a hibernate application. A facet can also be used t provide support for other languages such as ruby and scala. The extension makes it possible to generate .iml with the appropriate facets via the “iml.add_facet” method. It should be noted that facets are NOT inherited by sub-projects.
Example
This example adds the web facet to a project.
define "foo" do
iml.add_facet("Web","web") do |facet|
facet.configuration do |conf|
conf.descriptors do |desc|
desc.deploymentDescriptor :name => 'web.xml',
:url => "file://$MODULE_DIR$/src/main/webapp/WEB-INF/web.xml",
:optional => "false", :version => "2.4"
end
conf.webroots do |webroots|
webroots.root :url => "file://$MODULE_DIR$/src/main/webapp", :relative => "/"
end
end
end
end
Custom Component Sections
If the extension does not provide capability to generate configuration for a particular IDEA plugin the user can provide their own configuration data via the “ipr.add_component” or “iml.add_component” methods.
Example: Adding .ipr specific component
This example changes the compiler configuration for project.
define "foo" do
ipr.add_component("CompilerConfiguration") do |component|
component.option :name => 'DEFAULT_COMPILER', :value => 'Javac'
component.option :name => 'DEPLOY_AFTER_MAKE', :value => '0'
component.resourceExtensions do |xml|
xml.entry :name => '.+\.nonexistent'
end
component.wildcardResourceExtensions do |xml|
xml.entry :name => '?*.nonexistent'
end
end
end
Example: Adding .iml specific component
This example adds the web facet to a project. Note: This overrides the facets defined by the “iml.add_facet” method.
define "foo" do
iml.add_component("FacetManager") do |component|
component.facet :type => 'web', :name => 'Web' do |facet|
facet.configuration do |conf|
conf.descriptors do |desc|
desc.deploymentDescriptor :name => 'web.xml',
:url => "file://$MODULE_DIR$/src/main/webapp/WEB-INF/web.xml",
:optional => "false", :version => "2.4"
end
conf.webroots do |webroots|
webroots.root :url => "file://$MODULE_DIR$/src/main/webapp", :relative => "/"
end
end
end
end
end
Templates
The underlying project files are xml the contain elements for a number of “components”. The extension will load any existing project files and replace or add any component elements that are generated by the extension. The extension also allows the user to specify a template with either ipr.template or iml.template settings. If a template is specified it will be loaded and any component elements in these documents will be merged into the base document prior to merging in generated sections. Templates are useful if you want to enforce certain configuration options (i.e. project specific code style).
Example
define "foo" do
ipr.template = 'project.ipr.template'
iml.template = 'module.iml.template'
end
Groups
IDEA provides the facility to organise modules into groups. By default the extension does not do this but it can be enabled by iml.group setting. If that setting is set to true then the .iml file will be placed in a group based on the parent projects name. If the setting is a string then that is used as the name of the group.
Example
define "foo" do
iml.group = true
define 'bar' do
define 'baz'
end
define 'rab' do
iml.group = "MyGroup"
end
end
Will place the generated .imls in the following groups:
foo.iml => ''
/.iml => 'foo'
/baz/baz.iml => 'foo/bar'
rab/rab.iml => 'MyGroup'
Add Extra .iml files to .ipr
The ‘ipr.extra_modules’ setting makes it possible to add extra modules to the generated iml file. The setting is an array of file names relative to the base project directory.
Example
define "foo" do
ipr.extra_modules << 'other.iml'
ipr.extra_modules << 'other_other.iml'
end
Will add the ‘other.iml’ and ‘other_other.iml’ files to the .ipr project files.
Compatibility
It’s been tested with IDEA 9.x.
Future Work
The following is a list of feature requests for future versions of the extension. Feel free to jump in and supply a patch if you have gone ahead and implemented the feature.
Auto-generate Web Facet
Any project that defines a war package should have a web facet auto-generated for it.
Auto-generate Scala Facet
Any project that contains scala source code should have a scala facet autogenerated for it.
Support generation of IDEA files into separate hierarchy
Add the ability for the module and project files to be generated off into a different directory hierarchy. i.e. Generate project modules into .idea_project in projects base directory.
Fix tests to work when installed as a gem
The library should determine whether it is installed as a gem and if so use the gem to invoke the the tests. See rubygems.rubyforge.org/rubygems-update/Gem.html#M000228 for a possible interface to determine if currently installed as a gem.