buildr-iidea 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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