buildr-iidea 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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