| Name | Total Lines | Lines of Code | Total Coverage | Code Coverage |
|---|---|---|---|---|
| lib/buildr/ide/idea.rb | 592 | 478 | 28.21%
|
30.96%
|
Code reported as executed by Ruby looks like this...and this: this line is also marked as covered.Lines considered as run by rcov, but not reported by Ruby, look like this,and this: these lines were inferred by rcov (using simple heuristics).Finally, here's a line marked as not executed.
1 # Licensed to the Apache Software Foundation (ASF) under one or more |
2 # contributor license agreements. See the NOTICE file distributed with this |
3 # work for additional information regarding copyright ownership. The ASF |
4 # licenses this file to you under the Apache License, Version 2.0 (the |
5 # "License"); you may not use this file except in compliance with the License. |
6 # You may obtain a copy of the License at |
7 # |
8 # http://www.apache.org/licenses/LICENSE-2.0 |
9 # |
10 # Unless required by applicable law or agreed to in writing, software |
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
13 # License for the specific language governing permissions and limitations under |
14 # the License. |
15 |
16 |
17 require 'buildr/core/project' |
18 require 'buildr/packaging' |
19 require 'stringio' |
20 |
21 |
22 module Buildr |
23 module IntellijIdea |
24 def self.new_document(value) |
25 REXML::Document.new(value, :attribute_quote => :quote) |
26 end |
27 |
28 # Abstract base class for IdeaModule and IdeaProject |
29 class IdeaFile |
30 DEFAULT_SUFFIX = "" |
31 |
32 attr_reader :buildr_project |
33 attr_writer :suffix |
34 attr_writer :id |
35 attr_accessor :template |
36 |
37 def suffix |
38 @suffix ||= DEFAULT_SUFFIX |
39 end |
40 |
41 def filename |
42 buildr_project.path_to("#{name}.#{extension}") |
43 end |
44 |
45 def id |
46 @id ||= buildr_project.name.split(':').last |
47 end |
48 |
49 def add_component(name, attrs = {}, &xml) |
50 self.components << create_component(name, attrs, &xml) |
51 end |
52 |
53 def write(f) |
54 document.write(f, 2, false, true) |
55 end |
56 |
57 protected |
58 |
59 def name |
60 "#{self.id}#{suffix}" |
61 end |
62 |
63 def create_component(name, attrs = {}) |
64 target = StringIO.new |
65 Builder::XmlMarkup.new(:target => target, :indent => 2).component(attrs.merge({:name => name})) do |xml| |
66 yield xml if block_given? |
67 end |
68 Buildr::IntellijIdea.new_document(target.string).root |
69 end |
70 |
71 def components |
72 @components ||= self.default_components.compact |
73 end |
74 |
75 def load_document(filename) |
76 Buildr::IntellijIdea.new_document(File.read(filename)) |
77 end |
78 |
79 def document |
80 if File.exist?(self.filename) |
81 doc = load_document(self.filename) |
82 else |
83 doc = base_document |
84 inject_components(doc, self.initial_components) |
85 end |
86 if self.template |
87 template_doc = load_document(self.template) |
88 REXML::XPath.each(template_doc, "//component") do |element| |
89 inject_component(doc, element) |
90 end |
91 end |
92 inject_components(doc, self.components) |
93 doc |
94 end |
95 |
96 def inject_components(doc, components) |
97 components.each do |component| |
98 # execute deferred components |
99 component = component.call if Proc === component |
100 inject_component(doc, component) if component |
101 end |
102 end |
103 |
104 # replace overridden component (if any) with specified component |
105 def inject_component(doc, component) |
106 doc.root.delete_element("//component[@name='#{component.attributes['name']}']") |
107 doc.root.add_element component |
108 end |
109 end |
110 |
111 # IdeaModule represents an .iml file |
112 class IdeaModule < IdeaFile |
113 DEFAULT_TYPE = "JAVA_MODULE" |
114 DEFAULT_LOCAL_REPOSITORY_ENV_OVERRIDE = "MAVEN_REPOSITORY" |
115 |
116 attr_accessor :type |
117 attr_accessor :local_repository_env_override |
118 attr_accessor :group |
119 attr_reader :facets |
120 |
121 def initialize |
122 @type = DEFAULT_TYPE |
123 @local_repository_env_override = DEFAULT_LOCAL_REPOSITORY_ENV_OVERRIDE |
124 end |
125 |
126 def buildr_project=(buildr_project) |
127 @id = nil |
128 @facets = [] |
129 @skip_content = false |
130 @buildr_project = buildr_project |
131 end |
132 |
133 def extension |
134 "iml" |
135 end |
136 |
137 def main_source_directories |
138 @main_source_directories ||= [ |
139 buildr_project.compile.sources, |
140 buildr_project.resources.sources |
141 ].flatten.compact |
142 end |
143 |
144 def test_source_directories |
145 @test_source_directories ||= [ |
146 buildr_project.test.compile.sources, |
147 buildr_project.test.resources.sources |
148 ].flatten.compact |
149 end |
150 |
151 def excluded_directories |
152 @excluded_directories ||= [ |
153 buildr_project.resources.target, |
154 buildr_project.test.resources.target, |
155 buildr_project.path_to(:target, :main), |
156 buildr_project.path_to(:target, :test), |
157 buildr_project.path_to(:reports) |
158 ].flatten.compact |
159 end |
160 |
161 attr_writer :main_output_dir |
162 |
163 def main_output_dir |
164 @main_output_dir ||= buildr_project._(:target, :main, :java) |
165 end |
166 |
167 attr_writer :test_output_dir |
168 |
169 def test_output_dir |
170 @test_output_dir ||= buildr_project._(:target, :test, :java) |
171 end |
172 |
173 def main_dependencies |
174 @main_dependencies ||= buildr_project.compile.dependencies |
175 end |
176 |
177 def test_dependencies |
178 @test_dependencies ||= buildr_project.test.compile.dependencies |
179 end |
180 |
181 def add_facet(name, type) |
182 target = StringIO.new |
183 Builder::XmlMarkup.new(:target => target, :indent => 2).facet(:name => name, :type => type) do |xml| |
184 yield xml if block_given? |
185 end |
186 self.facets << Buildr::IntellijIdea.new_document(target.string).root |
187 end |
188 |
189 def skip_content? |
190 !!@skip_content |
191 end |
192 |
193 def skip_content! |
194 @skip_content = true |
195 end |
196 |
197 protected |
198 |
199 def test_dependency_details |
200 main_dependencies_paths = main_dependencies.map(&:to_s) |
201 target_dir = buildr_project.compile.target.to_s |
202 test_dependencies.select { |d| d.to_s != target_dir }.collect do |d| |
203 dependency_path = d.to_s |
204 export = main_dependencies_paths.include?(dependency_path) |
205 source_path = nil |
206 if d.respond_to?(:to_spec_hash) |
207 source_spec = d.to_spec_hash.merge(:classifier => 'sources') |
208 source_path = Buildr.artifact(source_spec).to_s |
209 source_path = nil unless File.exist?(source_path) |
210 end |
211 [dependency_path, export, source_path] |
212 end |
213 end |
214 |
215 def base_directory |
216 buildr_project.path_to |
217 end |
218 |
219 def base_document |
220 target = StringIO.new |
221 Builder::XmlMarkup.new(:target => target).module(:version => "4", :relativePaths => "true", :type => self.type) |
222 Buildr::IntellijIdea.new_document(target.string) |
223 end |
224 |
225 def initial_components |
226 [] |
227 end |
228 |
229 def default_components |
230 [ |
231 lambda { module_root_component }, |
232 lambda { facet_component } |
233 ] |
234 end |
235 |
236 def facet_component |
237 return nil if self.facets.empty? |
238 fm = self.create_component("FacetManager") |
239 self.facets.each do |facet| |
240 fm.add_element facet |
241 end |
242 fm |
243 end |
244 |
245 def module_root_component |
246 create_component("NewModuleRootManager", "inherit-compiler-output" => "false") do |xml| |
247 generate_compile_output(xml) |
248 generate_content(xml) unless skip_content? |
249 generate_initial_order_entries(xml) |
250 project_dependencies = [] |
251 |
252 |
253 self.test_dependency_details.each do |dependency_path, export, source_path| |
254 next unless export |
255 generate_lib(xml, dependency_path, export, source_path, project_dependencies) |
256 end |
257 |
258 self.test_dependency_details.each do |dependency_path, export, source_path| |
259 next if export |
260 generate_lib(xml, dependency_path, export, source_path, project_dependencies) |
261 end |
262 |
263 xml.orderEntryProperties |
264 end |
265 end |
266 |
267 def generate_lib(xml, dependency_path, export, source_path, project_dependencies) |
268 project_for_dependency = Buildr.projects.detect do |project| |
269 [project.packages, project.compile.target, project.resources.target, project.test.compile.target, project.test.resources.target].flatten. |
270 detect { |artifact| artifact.to_s == dependency_path } |
271 end |
272 if project_for_dependency |
273 if project_for_dependency.iml? && |
274 !project_dependencies.include?(project_for_dependency) && |
275 project_for_dependency != self.buildr_project |
276 generate_project_dependency(xml, project_for_dependency.iml.name, export, !export) |
277 end |
278 project_dependencies << project_for_dependency |
279 else |
280 generate_module_lib(xml, url_for_path(dependency_path), export, (source_path ? url_for_path(source_path) : nil), !export) |
281 end |
282 end |
283 |
284 def jar_path(path) |
285 "jar://#{resolve_path(path)}!/" |
286 end |
287 |
288 def file_path(path) |
289 "file://#{resolve_path(path)}" |
290 end |
291 |
292 def url_for_path(path) |
293 if path =~ /jar$/i |
294 jar_path(path) |
295 else |
296 file_path(path) |
297 end |
298 end |
299 |
300 def resolve_path(path) |
301 m2repo = Buildr::Repositories.instance.local |
302 if path.to_s.index(m2repo) == 0 && !self.local_repository_env_override.nil? |
303 return path.sub(m2repo, "$#{self.local_repository_env_override}$") |
304 else |
305 begin |
306 return "$MODULE_DIR$/#{relative(path)}" |
307 rescue ArgumentError |
308 # ArgumentError happens on windows when self.base_directory and path are on different drives |
309 return path |
310 end |
311 end |
312 end |
313 |
314 def relative(path) |
315 ::Buildr::Util.relative_path(File.expand_path(path.to_s), self.base_directory) |
316 end |
317 |
318 def generate_compile_output(xml) |
319 xml.output(:url => file_path(self.main_output_dir.to_s)) |
320 xml.tag!("output-test", :url => file_path(self.test_output_dir.to_s)) |
321 xml.tag!("exclude-output") |
322 end |
323 |
324 def generate_content(xml) |
325 xml.content(:url => "file://$MODULE_DIR$") do |
326 # Source folders |
327 { |
328 :main => self.main_source_directories, |
329 :test => self.test_source_directories |
330 }.each do |kind, directories| |
331 directories.map { |dir| dir.to_s }.compact.sort.uniq.each do |dir| |
332 xml.sourceFolder :url => file_path(dir), :isTestSource => (kind == :test ? 'true' : 'false') |
333 end |
334 end |
335 |
336 # Exclude target directories |
337 self.net_excluded_directories. |
338 collect { |dir| file_path(dir) }. |
339 select { |dir| relative_dir_inside_dir?(dir) }. |
340 sort.each do |dir| |
341 xml.excludeFolder :url => dir |
342 end |
343 end |
344 end |
345 |
346 def relative_dir_inside_dir?(dir) |
347 !dir.include?("../") |
348 end |
349 |
350 def generate_initial_order_entries(xml) |
351 xml.orderEntry :type => "sourceFolder", :forTests => "false" |
352 xml.orderEntry :type => "inheritedJdk" |
353 end |
354 |
355 def generate_project_dependency(xml, other_project, export, test = false) |
356 attribs = {:type => 'module', "module-name" => other_project} |
357 attribs[:exported] = '' if export |
358 attribs[:scope] = 'TEST' if test |
359 xml.orderEntry attribs |
360 end |
361 |
362 def generate_module_lib(xml, path, export, source_path, test = false) |
363 attribs = {:type => 'module-library'} |
364 attribs[:exported] = '' if export |
365 attribs[:scope] = 'TEST' if test |
366 xml.orderEntry attribs do |
367 xml.library do |
368 xml.CLASSES do |
369 xml.root :url => path |
370 end |
371 xml.JAVADOC |
372 xml.SOURCES do |
373 if source_path |
374 xml.root :url => source_path |
375 end |
376 end |
377 end |
378 end |
379 end |
380 |
381 # Don't exclude things that are subdirectories of other excluded things |
382 def net_excluded_directories |
383 net = [] |
384 all = self.excluded_directories.map { |dir| buildr_project._(dir.to_s) }.sort_by { |d| d.size } |
385 all.each_with_index do |dir, i| |
386 unless all[0 ... i].find { |other| dir =~ /^#{other}/ } |
387 net << dir |
388 end |
389 end |
390 net |
391 end |
392 end |
393 |
394 # IdeaModule represents an .ipr file |
395 class IdeaProject < IdeaFile |
396 attr_accessor :vcs |
397 attr_accessor :extra_modules |
398 attr_writer :jdk_version |
399 |
400 def initialize(buildr_project) |
401 @buildr_project = buildr_project |
402 @vcs = detect_vcs |
403 @extra_modules = [] |
404 end |
405 |
406 def jdk_version |
407 @jdk_version ||= buildr_project.compile.options.source || "1.6" |
408 end |
409 |
410 protected |
411 |
412 def extension |
413 "ipr" |
414 end |
415 |
416 def detect_vcs |
417 if File.directory?(buildr_project._('.svn')) |
418 "svn" |
419 elsif File.directory?(buildr_project._('.git')) |
420 "Git" |
421 end |
422 end |
423 |
424 def base_document |
425 target = StringIO.new |
426 Builder::XmlMarkup.new(:target => target).project(:version => "4", :relativePaths => "false") |
427 Buildr::IntellijIdea.new_document(target.string) |
428 end |
429 |
430 def default_components |
431 [ |
432 lambda { modules_component }, |
433 vcs_component |
434 ] |
435 end |
436 |
437 def initial_components |
438 [ |
439 lambda { project_root_manager_component }, |
440 lambda { project_details_component } |
441 ] |
442 end |
443 |
444 def project_root_manager_component |
445 attribs = {"version" => "2", |
446 "assert-keyword" => "true", |
447 "jdk-15" => "true", |
448 "project-jdk-name" => self.jdk_version, |
449 "project-jdk-type" => "JavaSDK", |
450 "languageLevel" => "JDK_#{self.jdk_version.gsub('.', '_')}"} |
451 create_component("ProjectRootManager", attribs) do |xml| |
452 xml.output("url" => "file://$PROJECT_DIR$/out") |
453 end |
454 end |
455 |
456 def project_details_component |
457 create_component("ProjectDetails") do |xml| |
458 xml.option("name" => "projectName", "value" => self.name) |
459 end |
460 end |
461 |
462 def modules_component |
463 create_component("ProjectModuleManager") do |xml| |
464 xml.modules do |
465 buildr_project.projects.select { |subp| subp.iml? }.each do |subproject| |
466 module_path = subproject.base_dir.gsub(/^#{buildr_project.base_dir}\//, '') |
467 path = "#{module_path}/#{subproject.iml.name}.iml" |
468 attribs = {:fileurl => "file://$PROJECT_DIR$/#{path}", :filepath => "$PROJECT_DIR$/#{path}"} |
469 if subproject.iml.group == true |
470 attribs[:group] = subproject.parent.name.gsub(':', '/') |
471 elsif !subproject.iml.group.nil? |
472 attribs[:group] = subproject.group.to_s |
473 end |
474 xml.module attribs |
475 end |
476 self.extra_modules.each do |iml_file| |
477 xml.module :fileurl => "file://$PROJECT_DIR$/#{iml_file}", |
478 :filepath => "$PROJECT_DIR$/#{iml_file}" |
479 end |
480 if buildr_project.iml? |
481 xml.module :fileurl => "file://$PROJECT_DIR$/#{buildr_project.iml.name}.iml", |
482 :filepath => "$PROJECT_DIR$/#{buildr_project.iml.name}.iml" |
483 end |
484 end |
485 end |
486 end |
487 |
488 def vcs_component |
489 if vcs |
490 create_component("VcsDirectoryMappings") do |xml| |
491 xml.mapping :directory => "", :vcs => vcs |
492 end |
493 end |
494 end |
495 end |
496 |
497 module ProjectExtension |
498 include Extension |
499 |
500 first_time do |
501 desc "Generate Intellij IDEA artifacts for all projects" |
502 Project.local_task "idea" => "artifacts" |
503 |
504 desc "Delete the generated Intellij IDEA artifacts" |
505 Project.local_task "idea:clean" |
506 end |
507 |
508 before_define do |project| |
509 project.recursive_task("idea") |
510 project.recursive_task("idea:clean") |
511 end |
512 |
513 after_define do |project| |
514 idea = project.task("idea") |
515 |
516 files = [ |
517 (project.iml if project.iml?), |
518 (project.ipr if project.ipr?) |
519 ].compact |
520 |
521 files.each do |ideafile| |
522 module_dir = File.dirname(ideafile.filename) |
523 # Need to clear the actions else the extension included as part of buildr will run |
524 file(ideafile.filename).clear_actions |
525 idea.enhance [file(ideafile.filename)] |
526 file(ideafile.filename => [Buildr.application.buildfile]) do |task| |
527 mkdir_p module_dir |
528 info "Writing #{task.name}" |
529 t = Tempfile.open("buildr-idea") |
530 temp_filename = t.path |
531 t.close! |
532 File.open(temp_filename, "w") do |f| |
533 ideafile.write f |
534 end |
535 mv temp_filename, ideafile.filename |
536 end |
537 end |
538 |
539 project.task("idea:clean") do |
540 files.each do |f| |
541 info "Removing #{f.filename}" if File.exist?(f.filename) |
542 rm_rf f.filename |
543 end |
544 end |
545 end |
546 |
547 def ipr |
548 if ipr? |
549 @ipr ||= IdeaProject.new(self) |
550 else |
551 raise "Only the root project has an IPR" |
552 end |
553 end |
554 |
555 def ipr? |
556 !@no_ipr && self.parent.nil? |
557 end |
558 |
559 def iml |
560 if iml? |
561 unless @iml |
562 inheritable_iml_source = self.parent |
563 while inheritable_iml_source && !inheritable_iml_source.iml? |
564 inheritable_iml_source = inheritable_iml_source.parent; |
565 end |
566 @iml = inheritable_iml_source ? inheritable_iml_source.iml.clone : IdeaModule.new |
567 @iml.buildr_project = self |
568 end |
569 return @iml |
570 else |
571 raise "IML generation is disabled for #{self.name}" |
572 end |
573 end |
574 |
575 def no_ipr |
576 @no_ipr = true |
577 end |
578 |
579 def no_iml |
580 @has_iml = false |
581 end |
582 |
583 def iml? |
584 @has_iml = @has_iml.nil? ? true : @has_iml |
585 end |
586 end |
587 end |
588 end |
589 |
590 class Buildr::Project |
591 include Buildr::IntellijIdea::ProjectExtension |
592 end |
Generated on 2011-07-06 23:35:37 -0700 with rcov 0.9.8