buildr-iidea 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +176 -0
- data/NOTICE +16 -0
- data/README.rdoc +286 -0
- data/Rakefile +27 -0
- data/buildr-iidea.gemspec +23 -0
- data/lib/buildr/intellij_idea/idea_file.rb +86 -0
- data/lib/buildr/intellij_idea/idea_module.rb +217 -0
- data/lib/buildr/intellij_idea/idea_project.rb +98 -0
- data/lib/buildr/intellij_idea/project_extension.rb +92 -0
- data/lib/buildr_iidea.rb +5 -0
- data/spec/buildr/intellij_idea/clean_spec.rb +38 -0
- data/spec/buildr/intellij_idea/dependency_spec.rb +85 -0
- data/spec/buildr/intellij_idea/extra_modules_spec.rb +24 -0
- data/spec/buildr/intellij_idea/facet_generation_spec.rb +36 -0
- data/spec/buildr/intellij_idea/group_spec.rb +33 -0
- data/spec/buildr/intellij_idea/idea_file_generation_spec.rb +177 -0
- data/spec/buildr/intellij_idea/inform_spec.rb +28 -0
- data/spec/buildr/intellij_idea/initial_components_spec.rb +33 -0
- data/spec/buildr/intellij_idea/module_property_inheritance_spec.rb +27 -0
- data/spec/buildr/intellij_idea/project_extension_spec.rb +19 -0
- data/spec/buildr/intellij_idea/template_spec.rb +234 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +75 -0
- data/spec/xpath_matchers.rb +109 -0
- metadata +97 -0
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/rdoctask'
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
require 'spec/rake/spectask'
|
5
|
+
|
6
|
+
gem_spec = Gem::Specification.load(File.expand_path('buildr-iidea.gemspec', File.dirname(__FILE__)))
|
7
|
+
|
8
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
9
|
+
spec.libs << 'lib' << 'spec'
|
10
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
11
|
+
end
|
12
|
+
|
13
|
+
task :default => :spec
|
14
|
+
|
15
|
+
desc "Generate RDoc documentation in rdoc/"
|
16
|
+
Rake::RDocTask.new :rdoc do |rdoc|
|
17
|
+
rdoc.rdoc_dir = 'rdoc'
|
18
|
+
rdoc.title = gem_spec.name
|
19
|
+
rdoc.options = gem_spec.rdoc_options.clone
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
rdoc.rdoc_files.include gem_spec.extra_rdoc_files
|
22
|
+
end
|
23
|
+
|
24
|
+
Rake::GemPackageTask.new(gem_spec) do |pkg|
|
25
|
+
pkg.need_zip = true
|
26
|
+
pkg.need_tar = true
|
27
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
Gem::Specification.new do |spec|
|
2
|
+
spec.name = 'buildr-iidea'
|
3
|
+
spec.version = `git describe`.strip.split('-').first
|
4
|
+
spec.authors = ['Rhett Sutphin', 'Peter Donald']
|
5
|
+
spec.email = ["rhett@detailedbalance.net","peter@realityforge.org"]
|
6
|
+
spec.homepage = "http://github.com/rockninja/buildr-iidea"
|
7
|
+
spec.summary = "Buildr tasks to generate Intellij IDEA project files"
|
8
|
+
spec.description = <<-TEXT
|
9
|
+
This is a buildr extension that provides tasks to generate Intellij IDEA
|
10
|
+
project files. The iidea task generates the project files based on the
|
11
|
+
settings of each project and extension specific settings.
|
12
|
+
TEXT
|
13
|
+
|
14
|
+
spec.files = Dir['{lib,spec}/**/*', '*.gemspec'] +
|
15
|
+
['LICENSE', 'NOTICE', 'README.rdoc', 'Rakefile']
|
16
|
+
spec.require_paths = ['lib']
|
17
|
+
|
18
|
+
spec.has_rdoc = true
|
19
|
+
spec.extra_rdoc_files = 'README.rdoc', 'LICENSE', 'NOTICE'
|
20
|
+
spec.rdoc_options = '--title', "#{spec.name} #{spec.version}", '--main', 'README.rdoc'
|
21
|
+
|
22
|
+
spec.post_install_message = "Thanks for installing the Intellij IDEA extension for Buildr"
|
23
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Buildr
|
2
|
+
module IntellijIdea
|
3
|
+
# Abstract base class for IdeaModule and IdeaProject
|
4
|
+
class IdeaFile
|
5
|
+
DEFAULT_SUFFIX = ""
|
6
|
+
|
7
|
+
attr_reader :buildr_project
|
8
|
+
attr_writer :suffix
|
9
|
+
attr_writer :id
|
10
|
+
attr_accessor :template
|
11
|
+
|
12
|
+
def suffix
|
13
|
+
@suffix ||= DEFAULT_SUFFIX
|
14
|
+
end
|
15
|
+
|
16
|
+
def filename
|
17
|
+
buildr_project.path_to("#{name}.#{extension}")
|
18
|
+
end
|
19
|
+
|
20
|
+
def id
|
21
|
+
@id ||= buildr_project.name.split(':').last
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_component(name, attrs = {}, &xml)
|
25
|
+
self.components << create_component(name, attrs, &xml)
|
26
|
+
end
|
27
|
+
|
28
|
+
def write(f)
|
29
|
+
document.write f
|
30
|
+
end
|
31
|
+
|
32
|
+
protected
|
33
|
+
|
34
|
+
def name
|
35
|
+
"#{self.id}#{suffix}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def create_component(name, attrs = {})
|
39
|
+
target = StringIO.new
|
40
|
+
Builder::XmlMarkup.new(:target => target, :indent => 2).component(attrs.merge({ :name => name })) do |xml|
|
41
|
+
yield xml if block_given?
|
42
|
+
end
|
43
|
+
REXML::Document.new(target.string).root
|
44
|
+
end
|
45
|
+
|
46
|
+
def components
|
47
|
+
@components ||= self.default_components.compact
|
48
|
+
end
|
49
|
+
|
50
|
+
def load_document(filename)
|
51
|
+
REXML::Document.new(File.read(filename))
|
52
|
+
end
|
53
|
+
|
54
|
+
def document
|
55
|
+
if File.exist?(self.filename)
|
56
|
+
doc = load_document(self.filename)
|
57
|
+
else
|
58
|
+
doc = base_document
|
59
|
+
inject_components( doc, self.initial_components )
|
60
|
+
end
|
61
|
+
if self.template
|
62
|
+
template_doc = load_document(self.template)
|
63
|
+
REXML::XPath.each(template_doc, "//component") do |element|
|
64
|
+
inject_component(doc, element)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
inject_components( doc, self.components )
|
68
|
+
doc
|
69
|
+
end
|
70
|
+
|
71
|
+
def inject_components(doc, components)
|
72
|
+
components.each do |component|
|
73
|
+
# execute deferred components
|
74
|
+
component = component.call if Proc === component
|
75
|
+
inject_component(doc, component) if component
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# replace overridden component (if any) with specified component
|
80
|
+
def inject_component(doc, component)
|
81
|
+
doc.root.delete_element("//component[@name='#{component.attributes['name']}']")
|
82
|
+
doc.root.add_element component
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,217 @@
|
|
1
|
+
module Buildr
|
2
|
+
module IntellijIdea
|
3
|
+
class IdeaModule < IdeaFile
|
4
|
+
DEFAULT_TYPE = "JAVA_MODULE"
|
5
|
+
DEFAULT_LOCAL_REPOSITORY_ENV_OVERRIDE = "M2_REPO"
|
6
|
+
MODULE_DIR_URL = "file://$MODULE_DIR$"
|
7
|
+
|
8
|
+
attr_writer :buildr_project
|
9
|
+
attr_accessor :type
|
10
|
+
attr_accessor :local_repository_env_override
|
11
|
+
attr_accessor :group
|
12
|
+
attr_reader :facets
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@type = DEFAULT_TYPE
|
16
|
+
@local_repository_env_override = DEFAULT_LOCAL_REPOSITORY_ENV_OVERRIDE
|
17
|
+
@facets = []
|
18
|
+
end
|
19
|
+
|
20
|
+
def buildr_project=(buildr_project)
|
21
|
+
@id = nil
|
22
|
+
@facets = []
|
23
|
+
@buildr_project = buildr_project
|
24
|
+
end
|
25
|
+
|
26
|
+
def extension
|
27
|
+
"iml"
|
28
|
+
end
|
29
|
+
|
30
|
+
def main_source_directories
|
31
|
+
@main_source_directories ||= [
|
32
|
+
buildr_project.compile.sources,
|
33
|
+
buildr_project.resources.sources
|
34
|
+
].flatten.compact
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_source_directories
|
38
|
+
@test_source_directories ||= [
|
39
|
+
buildr_project.test.compile.sources,
|
40
|
+
buildr_project.test.resources.sources
|
41
|
+
].flatten.compact
|
42
|
+
end
|
43
|
+
|
44
|
+
def excluded_directories
|
45
|
+
@excluded_directories ||= [
|
46
|
+
buildr_project.resources.target,
|
47
|
+
buildr_project.test.resources.target,
|
48
|
+
buildr_project.path_to(:target, :main),
|
49
|
+
buildr_project.path_to(:target, :test),
|
50
|
+
buildr_project.path_to(:reports)
|
51
|
+
].flatten.compact
|
52
|
+
end
|
53
|
+
|
54
|
+
def main_output_dir
|
55
|
+
buildr_project.compile.target || buildr_project.path_to(:target, :main, 'idea')
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_output_dir
|
59
|
+
buildr_project.test.compile.target || buildr_project.path_to(:target, :test, 'idea')
|
60
|
+
end
|
61
|
+
|
62
|
+
def resources
|
63
|
+
[buildr_project.test.resources.target, buildr_project.resources.target].compact
|
64
|
+
end
|
65
|
+
|
66
|
+
def main_dependencies
|
67
|
+
buildr_project.compile.dependencies.map(&:to_s)
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_dependencies
|
71
|
+
buildr_project.test.compile.dependencies.map(&:to_s) - [ buildr_project.compile.target.to_s ]
|
72
|
+
end
|
73
|
+
|
74
|
+
def base_directory
|
75
|
+
buildr_project.path_to
|
76
|
+
end
|
77
|
+
|
78
|
+
def add_facet(name, type)
|
79
|
+
target = StringIO.new
|
80
|
+
Builder::XmlMarkup.new(:target => target, :indent => 2).facet(:name => name, :type => type) do |xml|
|
81
|
+
yield xml if block_given?
|
82
|
+
end
|
83
|
+
self.facets << REXML::Document.new(target.string).root
|
84
|
+
end
|
85
|
+
|
86
|
+
protected
|
87
|
+
|
88
|
+
def base_document
|
89
|
+
target = StringIO.new
|
90
|
+
Builder::XmlMarkup.new(:target => target).module(:version => "4", :relativePaths => "true", :type => self.type)
|
91
|
+
REXML::Document.new(target.string)
|
92
|
+
end
|
93
|
+
|
94
|
+
def initial_components
|
95
|
+
[]
|
96
|
+
end
|
97
|
+
|
98
|
+
def default_components
|
99
|
+
[
|
100
|
+
lambda { module_root_component },
|
101
|
+
lambda { facet_component }
|
102
|
+
]
|
103
|
+
end
|
104
|
+
|
105
|
+
def facet_component
|
106
|
+
return nil if self.facets.empty?
|
107
|
+
fm = self.create_component("FacetManager")
|
108
|
+
self.facets.each do |facet|
|
109
|
+
fm.add_element facet
|
110
|
+
end
|
111
|
+
fm
|
112
|
+
end
|
113
|
+
|
114
|
+
def module_root_component
|
115
|
+
m2repo = Buildr::Repositories.instance.local
|
116
|
+
|
117
|
+
create_component("NewModuleRootManager", "inherit-compiler-output" => "false") do |xml|
|
118
|
+
generate_compile_output(xml)
|
119
|
+
generate_content(xml)
|
120
|
+
generate_initial_order_entries(xml)
|
121
|
+
|
122
|
+
# Note: Use the test classpath since IDEA compiles both "main" and "test" classes using the same classpath
|
123
|
+
self.test_dependencies.each do |dependency_path|
|
124
|
+
export = self.main_dependencies.include?(dependency_path)
|
125
|
+
project_for_dependency = Buildr.projects.detect do |project|
|
126
|
+
project.packages.detect { |pkg| pkg.to_s == dependency_path }
|
127
|
+
end
|
128
|
+
if project_for_dependency
|
129
|
+
if project_for_dependency.iml?
|
130
|
+
generate_project_dependency( xml, project_for_dependency.iml.name, export )
|
131
|
+
end
|
132
|
+
next
|
133
|
+
elsif dependency_path.to_s.index(m2repo) == 0
|
134
|
+
entry_path = dependency_path
|
135
|
+
unless self.local_repository_env_override.nil?
|
136
|
+
entry_path = entry_path.sub(m2repo, "$#{self.local_repository_env_override}$")
|
137
|
+
end
|
138
|
+
generate_module_lib(xml, "jar://#{entry_path}!/", export )
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
self.resources.each do |resource|
|
143
|
+
generate_module_lib(xml, "#{MODULE_DIR_URL}/#{relative(resource.to_s)}", true)
|
144
|
+
end
|
145
|
+
|
146
|
+
xml.orderEntryProperties
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def relative(path)
|
151
|
+
Util.relative_path(File.expand_path(path.to_s), self.base_directory)
|
152
|
+
end
|
153
|
+
|
154
|
+
def generate_compile_output(xml)
|
155
|
+
xml.output(:url => "#{MODULE_DIR_URL}/#{relative(self.main_output_dir.to_s)}")
|
156
|
+
xml.tag!("output-test", :url => "#{MODULE_DIR_URL}/#{relative(self.test_output_dir.to_s)}")
|
157
|
+
xml.tag!("exclude-output")
|
158
|
+
end
|
159
|
+
|
160
|
+
def generate_content(xml)
|
161
|
+
xml.content(:url => MODULE_DIR_URL) do
|
162
|
+
# Source folders
|
163
|
+
{
|
164
|
+
:main => self.main_source_directories,
|
165
|
+
:test => self.test_source_directories
|
166
|
+
}.each do |kind, directories|
|
167
|
+
directories.map { |dir| relative(dir) }.compact.sort.uniq.each do |dir|
|
168
|
+
xml.sourceFolder :url => "#{MODULE_DIR_URL}/#{dir}", :isTestSource => (kind == :test ? 'true' : 'false')
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# Exclude target directories
|
173
|
+
self.net_excluded_directories.sort.each do |dir|
|
174
|
+
xml.excludeFolder :url => "#{MODULE_DIR_URL}/#{dir}"
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def generate_initial_order_entries(xml)
|
180
|
+
xml.orderEntry :type => "sourceFolder", :forTests => "false"
|
181
|
+
xml.orderEntry :type => "inheritedJdk"
|
182
|
+
end
|
183
|
+
|
184
|
+
def generate_project_dependency(xml, other_project, export = true)
|
185
|
+
attribs = {:type => 'module', "module-name" => other_project}
|
186
|
+
attribs[:exported] = '' if export
|
187
|
+
xml.orderEntry attribs
|
188
|
+
end
|
189
|
+
|
190
|
+
def generate_module_lib(xml, path, export)
|
191
|
+
attribs = {:type => 'module-library'}
|
192
|
+
attribs[:exported] = '' if export
|
193
|
+
xml.orderEntry attribs do
|
194
|
+
xml.library do
|
195
|
+
xml.CLASSES do
|
196
|
+
xml.root :url => path
|
197
|
+
end
|
198
|
+
xml.JAVADOC
|
199
|
+
xml.SOURCES
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
# Don't exclude things that are subdirectories of other excluded things
|
205
|
+
def net_excluded_directories
|
206
|
+
net = []
|
207
|
+
all = self.excluded_directories.map { |dir| relative(dir.to_s) }.sort_by { |d| d.size }
|
208
|
+
all.each_with_index do |dir, i|
|
209
|
+
unless all[0 ... i].find { |other| dir =~ /^#{other}/ }
|
210
|
+
net << dir
|
211
|
+
end
|
212
|
+
end
|
213
|
+
net
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module Buildr
|
2
|
+
module IntellijIdea
|
3
|
+
class IdeaProject < IdeaFile
|
4
|
+
attr_accessor :vcs
|
5
|
+
attr_accessor :extra_modules
|
6
|
+
attr_writer :jdk_version
|
7
|
+
|
8
|
+
def initialize(buildr_project)
|
9
|
+
@buildr_project = buildr_project
|
10
|
+
@vcs = detect_vcs
|
11
|
+
@extra_modules = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def jdk_version
|
15
|
+
@jdk_version ||= buildr_project.compile.options.source || "1.6"
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
def extension
|
21
|
+
"ipr"
|
22
|
+
end
|
23
|
+
|
24
|
+
def detect_vcs
|
25
|
+
if File.directory?(buildr_project._('.svn'))
|
26
|
+
"svn"
|
27
|
+
elsif File.directory?(buildr_project._('.git'))
|
28
|
+
"Git"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def base_document
|
33
|
+
target = StringIO.new
|
34
|
+
Builder::XmlMarkup.new(:target => target).project(:version => "4", :relativePaths => "false")
|
35
|
+
REXML::Document.new(target.string)
|
36
|
+
end
|
37
|
+
|
38
|
+
def default_components
|
39
|
+
[
|
40
|
+
lambda { modules_component },
|
41
|
+
vcs_component
|
42
|
+
]
|
43
|
+
end
|
44
|
+
|
45
|
+
def initial_components
|
46
|
+
[
|
47
|
+
lambda { project_root_manager_component }
|
48
|
+
]
|
49
|
+
end
|
50
|
+
|
51
|
+
def project_root_manager_component
|
52
|
+
attribs = {"version" => "2",
|
53
|
+
"assert-keyword" => "true",
|
54
|
+
"jdk-15" => "true",
|
55
|
+
"project-jdk-name" => self.jdk_version,
|
56
|
+
"project-jdk-type" => "JavaSDK",
|
57
|
+
"languageLevel" => "JDK_#{self.jdk_version.gsub('.','_')}" }
|
58
|
+
create_component("ProjectRootManager",attribs) do |xml|
|
59
|
+
xml.output("url" => "file://$PROJECT_DIR$/out")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def modules_component
|
64
|
+
create_component("ProjectModuleManager") do |xml|
|
65
|
+
xml.modules do
|
66
|
+
buildr_project.projects.select { |subp| subp.iml? }.each do |subproject|
|
67
|
+
module_path = subproject.base_dir.gsub(/^#{buildr_project.base_dir}\//, '')
|
68
|
+
path = "#{module_path}/#{subproject.iml.name}.iml"
|
69
|
+
attribs = { :fileurl => "file://$PROJECT_DIR$/#{path}", :filepath => "$PROJECT_DIR$/#{path}" }
|
70
|
+
if subproject.iml.group == true
|
71
|
+
attribs[:group] = subproject.parent.name.gsub(':', '/')
|
72
|
+
elsif !subproject.iml.group.nil?
|
73
|
+
attribs[:group] = subproject.group.to_s
|
74
|
+
end
|
75
|
+
xml.module attribs
|
76
|
+
end
|
77
|
+
self.extra_modules.each do |iml_file|
|
78
|
+
xml.module :fileurl => "file://$PROJECT_DIR$/#{iml_file}",
|
79
|
+
:filepath => "$PROJECT_DIR$/#{iml_file}"
|
80
|
+
end
|
81
|
+
if buildr_project.iml?
|
82
|
+
xml.module :fileurl => "file://$PROJECT_DIR$/#{buildr_project.iml.name}.iml",
|
83
|
+
:filepath => "$PROJECT_DIR$/#{buildr_project.iml.name}.iml"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def vcs_component
|
90
|
+
if vcs
|
91
|
+
create_component("VcsDirectoryMappings") do |xml|
|
92
|
+
xml.mapping :directory => "", :vcs => vcs
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|