kwala 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/README +62 -0
  2. data/bin/kwala +39 -0
  3. data/lib/kwala.rb +59 -0
  4. data/lib/kwala/actions/code_change.rb +128 -0
  5. data/lib/kwala/actions/code_coverage.rb +303 -0
  6. data/lib/kwala/actions/code_duplication.rb +222 -0
  7. data/lib/kwala/actions/code_formatting.rb +358 -0
  8. data/lib/kwala/actions/cycle_detection.rb +118 -0
  9. data/lib/kwala/actions/cyclomatic_complexity.rb +159 -0
  10. data/lib/kwala/actions/dead_code.rb +68 -0
  11. data/lib/kwala/actions/executable_files_check.rb +111 -0
  12. data/lib/kwala/actions/flagged_comments.rb +128 -0
  13. data/lib/kwala/actions/gem_plugin.rb +31 -0
  14. data/lib/kwala/actions/loc_count.rb +153 -0
  15. data/lib/kwala/actions/multi_ruby_unit_test.rb +62 -0
  16. data/lib/kwala/actions/outside_links.rb +85 -0
  17. data/lib/kwala/actions/rails_migrate.rb +62 -0
  18. data/lib/kwala/actions/strange_requires.rb +106 -0
  19. data/lib/kwala/actions/syntax_check.rb +130 -0
  20. data/lib/kwala/actions/unit_test.rb +368 -0
  21. data/lib/kwala/build_action.rb +88 -0
  22. data/lib/kwala/build_context.rb +49 -0
  23. data/lib/kwala/command_line_runner.rb +184 -0
  24. data/lib/kwala/ext/demos.jar +0 -0
  25. data/lib/kwala/ext/pmd.jar +0 -0
  26. data/lib/kwala/ext/prefuse.jar +0 -0
  27. data/lib/kwala/extensions.rb +36 -0
  28. data/lib/kwala/lib/code_analyzer.rb +678 -0
  29. data/lib/kwala/lib/cycle_detector.rb +793 -0
  30. data/lib/kwala/lib/strange_requires_detector.rb +145 -0
  31. data/lib/kwala/notification.rb +45 -0
  32. data/lib/kwala/notifications/email.rb +54 -0
  33. data/lib/kwala/notifications/rss.rb +151 -0
  34. data/lib/kwala/project_builder_utils.rb +178 -0
  35. data/lib/kwala/templates/build_template.html +33 -0
  36. data/lib/kwala/templates/code_change_summary.html +27 -0
  37. data/lib/kwala/templates/code_coverage_detailed.html +25 -0
  38. data/lib/kwala/templates/code_coverage_summary.html +30 -0
  39. data/lib/kwala/templates/code_duplication_detailed.html +45 -0
  40. data/lib/kwala/templates/code_duplication_summary.html +9 -0
  41. data/lib/kwala/templates/code_formatting_detailed.html +27 -0
  42. data/lib/kwala/templates/code_formatting_summary.html +11 -0
  43. data/lib/kwala/templates/cycle_detection_detailed.html +20 -0
  44. data/lib/kwala/templates/cycle_detection_summary.html +7 -0
  45. data/lib/kwala/templates/cyclomatic_complexity_summary.html +27 -0
  46. data/lib/kwala/templates/executable_files_check_detailed.html +31 -0
  47. data/lib/kwala/templates/executable_files_check_summary.html +20 -0
  48. data/lib/kwala/templates/flagged_comments_detailed.html +22 -0
  49. data/lib/kwala/templates/flagged_comments_summary.html +10 -0
  50. data/lib/kwala/templates/loc_count_detailed.html +24 -0
  51. data/lib/kwala/templates/loc_count_summary.html +14 -0
  52. data/lib/kwala/templates/mdd/1.png +0 -0
  53. data/lib/kwala/templates/mdd/2.png +0 -0
  54. data/lib/kwala/templates/mdd/3.png +0 -0
  55. data/lib/kwala/templates/mdd/4.png +0 -0
  56. data/lib/kwala/templates/mdd/5.png +0 -0
  57. data/lib/kwala/templates/outside_links_summary.html +4 -0
  58. data/lib/kwala/templates/strange_requires_detailed.html +23 -0
  59. data/lib/kwala/templates/strange_requires_summary.html +13 -0
  60. data/lib/kwala/templates/style.css +95 -0
  61. data/lib/kwala/templates/syntax_check_detailed.html +21 -0
  62. data/lib/kwala/templates/syntax_check_summary.html +7 -0
  63. data/lib/kwala/templates/unit_test_detailed.html +66 -0
  64. data/lib/kwala/templates/unit_test_summary.html +70 -0
  65. data/test/tc_build_action.rb +32 -0
  66. data/test/tc_templates.rb +24 -0
  67. metadata +118 -0
@@ -0,0 +1,118 @@
1
+ # $Id: cycle_detection.rb 32 2008-04-02 07:50:18Z zev $
2
+ #
3
+ # Implements a Ruby require cycle detection and graphing action.
4
+
5
+ # Copyright (c) 2006, Ubiquitous Business Technology (http://ubit.com)
6
+ # All rights reserved.
7
+ #
8
+ # Redistribution and use in source and binary forms, with or without
9
+ # modification, are permitted provided that the following conditions are
10
+ # met:
11
+ #
12
+ #
13
+ # * Redistributions of source code must retain the above copyright
14
+ # notice, this list of conditions and the following disclaimer.
15
+ #
16
+ # * Redistributions in binary form must reproduce the above
17
+ # copyright notice, this list of conditions and the following
18
+ # disclaimer in the documentation and/or other materials provided
19
+ # with the distribution.
20
+ #
21
+ # * Neither the name of Ubit nor the names of its
22
+ # contributors may be used to endorse or promote products derived
23
+ # from this software without specific prior written permission.
24
+ #
25
+ #
26
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29
+ # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30
+ # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32
+ # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34
+ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37
+ #
38
+ # == Author
39
+ # Zev Blut (zb@ubit.com)
40
+
41
+ require 'stringio'
42
+
43
+ require "#{LIB_DIR}/cycle_detector"
44
+
45
+ class CycleDetectionAction < BuildAction
46
+
47
+ def initialize
48
+ @cycle_detector = CycleDetector.new
49
+ @cycle_detector.print_strategy = self
50
+ @output_directory = nil
51
+ @cycles = nil
52
+ end
53
+
54
+ def build_action(context)
55
+ # convert obj?
56
+ @cycle_detector.make_graph(context.project_directory)
57
+ end
58
+
59
+
60
+ def summary_display(context)
61
+ template = TemplateFile.new(self.class.summary_template_file)
62
+ @cycle_detector.print_unique_cycles( @cycle_detector.find_cycles )
63
+
64
+ if @cycles.empty?
65
+ context.amrita_data[:cycle_results] = "There are no require cycles."
66
+ else
67
+ data = @cycles.map do |cycle|
68
+ {
69
+ :name => "#{ cycle.first} <=> #{ cycle.last }",
70
+ :list => cycle
71
+ }
72
+ end
73
+ context.amrita_data[:cycle_results] = { :entry => data }
74
+ end
75
+
76
+
77
+ loc_base = "#{context.project_name}_cycle.html"
78
+ context.amrita_data[:cycle_details] =
79
+ Amrita.e(:a, :href => loc_base ) { "Require Graph Details" }
80
+
81
+ summary_expand(template, context)
82
+ end
83
+
84
+ def detailed_display(context)
85
+ template = TemplateFile.new(self.class.detailed_template_file)
86
+
87
+ @output_directory = context.output_directory
88
+ @cycle_detector.print_graph
89
+
90
+ ["demos.jar", "prefuse.jar"].each do |jarfile|
91
+ FileUtils.cp(EXTERNAL_DIR + jarfile, context.output_directory)
92
+ end
93
+
94
+ det_res = ProjectBuilderUtils.expand_template(template, context.amrita_data)
95
+ det_file = "#{context.output_directory}/#{context.project_name}_cycle.html"
96
+ [det_file, det_res]
97
+ end
98
+
99
+
100
+ def print_graph(graph)
101
+ graph_ml = CycleDetector::GraphMLPrintStrategy.new
102
+ begin
103
+ oldstd = $stdout
104
+ $stdout = StringIO.new
105
+ graph_ml.print_graph(graph)
106
+ gxml = $stdout.string
107
+ ensure
108
+ $stdout = oldstd
109
+ end
110
+ # now dump that into the out dir
111
+ File.open(@output_directory + "/require_graph.xml", "w") { |f| f.puts gxml }
112
+ end
113
+
114
+ def print_cycles(cycles)
115
+ @cycles = cycles
116
+ end
117
+
118
+ end
@@ -0,0 +1,159 @@
1
+ # $Id: cyclomatic_complexity.rb 34 2008-04-03 06:01:19Z zev $
2
+ #
3
+ # This file checks the cyclomatic complexity of a source base.
4
+ #
5
+ # Uses Saikuro http://saikuro.rubyforge.org
6
+
7
+ # Copyright (c) 2006, Ubiquitous Business Technology (http://ubit.com)
8
+ # All rights reserved.
9
+ #
10
+ # Redistribution and use in source and binary forms, with or without
11
+ # modification, are permitted provided that the following conditions are
12
+ # met:
13
+ #
14
+ #
15
+ # * Redistributions of source code must retain the above copyright
16
+ # notice, this list of conditions and the following disclaimer.
17
+ #
18
+ # * Redistributions in binary form must reproduce the above
19
+ # copyright notice, this list of conditions and the following
20
+ # disclaimer in the documentation and/or other materials provided
21
+ # with the distribution.
22
+ #
23
+ # * Neither the name of Ubit nor the names of its
24
+ # contributors may be used to endorse or promote products derived
25
+ # from this software without specific prior written permission.
26
+ #
27
+ #
28
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31
+ # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32
+ # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34
+ # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36
+ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39
+ #
40
+ # == Author
41
+ # Zev Blut (zb@ubit.com)
42
+
43
+ class CyclomaticComplexityAction < BuildAction
44
+
45
+ def initialize
46
+ @limit = 11 # 1 more for header
47
+ @cyclo_count = nil
48
+ @bound = 0 # This should be methods instead of files.
49
+ end
50
+
51
+ def build_action(context)
52
+ args = [ "-o #{context.output_directory}" ]
53
+ args << [ "-c -t"]
54
+ args << [ "-y 0 -w 11 -e 15"]
55
+ args << [ "-k 0 -s 30 -d 35"]
56
+ args << [ "-i #{context.project_directory}" ]
57
+
58
+ stdout_data = stderr_data = Array.new
59
+ system("/usr/bin/env saikuro #{args.join(" ")}")
60
+ @cyclo_count = get_cyclo_violations(context)
61
+ @bound = context.ruby_files.size + context.test_files.size
62
+ end
63
+
64
+ def summary_display(context)
65
+ template = TemplateFile.new(self.class.summary_template_file)
66
+ context.amrita_data[:saikuro_metrics_summary] = {
67
+ :cyclo_summary => get_cyclo_summary(context),
68
+ :token_summary => get_token_summary(context),
69
+ :cyclo_violations => get_cyclo_violations(context),
70
+ :token_violations => get_token_violations(context),
71
+ :cyclo_link => Amrita::e(:a, :href => "index_cyclo.html") { "Cyclomatic Complexity Details" },
72
+ :token_link => Amrita::e(:a, :href => "index_token.html") { "Token Count Details" }
73
+ }
74
+ summary_expand(template, context)
75
+ end
76
+
77
+ def score
78
+ # high complexity is probably one of the things that should weigh higher.
79
+ score_scaling(( @cyclo_count[:errors] * 3 + @cyclo_count[:warnings]), @bound)
80
+ end
81
+
82
+ def self.detailed_template_file
83
+ nil
84
+ end
85
+
86
+ def get_cyclo_summary(context)
87
+ get_summary_from_file(context.output_directory + "/index_cyclo.html")
88
+ end
89
+
90
+ def get_token_summary(context)
91
+ get_summary_from_file(context.output_directory + "/index_token.html")
92
+ end
93
+
94
+ def get_cyclo_violations(context)
95
+ count_violations(context.output_directory + "/index_cyclo.html")
96
+ end
97
+
98
+ def get_token_violations(context)
99
+ count_violations(context.output_directory + "/index_token.html")
100
+ end
101
+
102
+ def get_summary_from_file(file)
103
+ if !File.exists?(file)
104
+ STDERR.puts "Saikuro : Cannot find #{file}"
105
+ return ""
106
+ end
107
+ data = IO.readlines(file).join
108
+ res = ""
109
+ if m = /(<table.*?>)(.*)(<\/table>)/mi.match(data)
110
+ head = m[1]
111
+ data = m[2]
112
+ tail = m[3]
113
+ rows = Array.new
114
+ while rows.size < @limit && m = /(<tr>.*?<\/tr>)(.*)/mi.match(data)
115
+ rows << m[1]
116
+ data = m[2]
117
+ end
118
+
119
+ res = head.to_s + rows.join("\n") + tail.to_s
120
+ end
121
+
122
+ SanitizedString.new(res)
123
+ end
124
+
125
+
126
+ # XXX: This is basically the same as get_summary_from_file, there
127
+ # should be a nice way to reuse the logic in a more clean way.
128
+ def count_violations(file)
129
+ if !File.exists?(file)
130
+ return 0
131
+ end
132
+
133
+ data = IO.readlines(file).join
134
+ errors = 0
135
+ warnings = 0
136
+
137
+ if m = /(<table.*?>)(.*)(<\/table>)/mi.match(data)
138
+ data = m[2]
139
+ while m = /(<tr>.*?<\/tr>)(.*)/mi.match(data)
140
+ if /^<tr><th>/ !~ m[1]
141
+ # Make sure not to count the header row.
142
+ if /class=\"error\"/ =~ m[1]
143
+ errors += 1
144
+ elsif /class=\"warning\"/ =~ m[1]
145
+ warnings += 1
146
+ end
147
+ end
148
+ data = m[2]
149
+ end
150
+ end
151
+
152
+ {
153
+ :total => errors + warnings,
154
+ :errors => errors,
155
+ :warnings => warnings
156
+ }
157
+ end
158
+
159
+ end
@@ -0,0 +1,68 @@
1
+ # $Id$
2
+ #
3
+ # This file handles logic for dead code checking
4
+
5
+ # All rights reserved.
6
+ #
7
+ # Redistribution and use in source and binary forms, with or without
8
+ # modification, are permitted provided that the following conditions are
9
+ # met:
10
+ #
11
+ #
12
+ # * Redistributions of source code must retain the above copyright
13
+ # notice, this list of conditions and the following disclaimer.
14
+ #
15
+ # * Redistributions in binary form must reproduce the above
16
+ # copyright notice, this list of conditions and the following
17
+ # disclaimer in the documentation and/or other materials provided
18
+ # with the distribution.
19
+ #
20
+ # * Neither the name of Ubit nor the names of its
21
+ # contributors may be used to endorse or promote products derived
22
+ # from this software without specific prior written permission.
23
+ #
24
+ #
25
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28
+ # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29
+ # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31
+ # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33
+ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
+ #
37
+ # == Author
38
+ # Zev Blut ()
39
+
40
+ class DeadCodeAction < BuildAction
41
+
42
+ def initialize
43
+ end
44
+
45
+ def build_action(context)
46
+ end
47
+
48
+ def summary_display(context)
49
+ template = TemplateFile.new("#{TEMPLATE_DIR}/dead_code_template.html")
50
+ summary_expand(template, context)
51
+ end
52
+
53
+ def detailed_display(context)
54
+ context.amrita_data[:syntax_results] = {
55
+ :entry => @syntax_results
56
+ }
57
+ det_res = expand_syntax_check_template(context.amrita_data[:syntax_results])
58
+ det_file = "#{context.output_directory}/#{context.project_name}_dead_code.html"
59
+ [det_file, det_res]
60
+ end
61
+
62
+ def score
63
+ 10
64
+ end
65
+
66
+
67
+
68
+ end
@@ -0,0 +1,111 @@
1
+ # $Id: executable_files_check.rb 29 2008-04-02 07:32:44Z zev $
2
+ #
3
+ # This action checks for the code size within ruby scripts starting with
4
+ # a shell bang. By our convention, we want to keep those files as small
5
+ # as possible, all logic should be in reusable classes.
6
+
7
+ # Copyright (c) 2006, Ubiquitous Business Technology (http://ubit.com)
8
+ # All rights reserved.
9
+ #
10
+ # Redistribution and use in source and binary forms, with or without
11
+ # modification, are permitted provided that the following conditions are
12
+ # met:
13
+ #
14
+ #
15
+ # * Redistributions of source code must retain the above copyright
16
+ # notice, this list of conditions and the following disclaimer.
17
+ #
18
+ # * Redistributions in binary form must reproduce the above
19
+ # copyright notice, this list of conditions and the following
20
+ # disclaimer in the documentation and/or other materials provided
21
+ # with the distribution.
22
+ #
23
+ # * Neither the name of Ubit nor the names of its
24
+ # contributors may be used to endorse or promote products derived
25
+ # from this software without specific prior written permission.
26
+ #
27
+ #
28
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31
+ # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32
+ # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34
+ # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36
+ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39
+ #
40
+ # == Author
41
+ # Michael Reinsch (mr@ubit.com)
42
+
43
+ require File.dirname(__FILE__) + "/loc_count.rb"
44
+
45
+ class ExecutableFilesCheckAction < BuildAction
46
+ include LOCCountModule
47
+
48
+ def initialize
49
+ @problem_files = Array.new
50
+ @shellbang_files_LOC = Hash.new
51
+ end
52
+
53
+ def build_action(context)
54
+ context.ruby_files.each do |f|
55
+ exec = File.executable?(f)
56
+ bang = ("#!/" == IO.read(f, 3, 0))
57
+ if exec ^ bang
58
+ if exec
59
+ prob = "executable, no shell bang"
60
+ else
61
+ prob = "shell bang, not executable"
62
+ end
63
+ @problem_files << { :filename => f, :problem => prob }
64
+ end
65
+ @shellbang_files_LOC[f] = count_loc(f) if bang
66
+ end
67
+ @sorted_shellbang_files_LOC = @shellbang_files_LOC.sort {|a,b| b[1] <=> a[1] }
68
+ end
69
+
70
+ def summary_display(context)
71
+ template = TemplateFile.new(self.class.summary_template_file)
72
+
73
+ res = {}
74
+ if @problem_files.size > 0
75
+ res[:problem_files] = { :files => @problem_files }
76
+ end
77
+
78
+ # get top 10
79
+ top_ten_files = @sorted_shellbang_files_LOC[0..9]
80
+ res[:files] = top_ten_files.map do |f, l|
81
+ { :filename => f, :lines_of_code => l }
82
+ end
83
+
84
+ context.amrita_data[:executable_files_check_results] = res
85
+ execfilecodesize_base = "#{context.project_name}_executable_files_check.html"
86
+ context.amrita_data[:executable_files_check_details] =
87
+ (Amrita::e(:a, :href => execfilecodesize_base) { "Executable Files Check Details" } )
88
+
89
+ summary_expand(template, context)
90
+ end
91
+
92
+ def detailed_display(context)
93
+ template = TemplateFile.new(self.class.detailed_template_file)
94
+
95
+ res = {}
96
+ if @problem_files.size > 0
97
+ res[:problem_files] = { :files => @problem_files }
98
+ end
99
+
100
+ res[:files] = @sorted_shellbang_files_LOC.map do |f, l|
101
+ { :filename => f, :lines_of_code => l }
102
+ end
103
+
104
+ context.amrita_data[:executable_files_check_results] = res
105
+
106
+ det_res = ProjectBuilderUtils.expand_template(template, context.amrita_data)
107
+ det_file = "#{context.output_directory}/#{context.project_name}_executable_files_check.html"
108
+ [det_file, det_res]
109
+ end
110
+
111
+ end