rubycritic 0.0.5 → 0.0.16

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.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +10 -0
  3. data/README.md +72 -11
  4. data/bin/rubycritic +2 -0
  5. data/lib/rubycritic/adapters/complexity/flog.rb +22 -0
  6. data/lib/rubycritic/adapters/smell/flay.rb +68 -0
  7. data/lib/rubycritic/adapters/smell/flog.rb +62 -0
  8. data/lib/rubycritic/adapters/smell/reek.rb +44 -0
  9. data/lib/rubycritic/analysers/churn.rb +19 -0
  10. data/lib/rubycritic/analysers/config.reek +8 -0
  11. data/lib/rubycritic/analysers/flay.rb +15 -0
  12. data/lib/rubycritic/analysers/flog.rb +1 -2
  13. data/lib/rubycritic/analysers/stats.rb +31 -0
  14. data/lib/rubycritic/analysers_runner.rb +15 -14
  15. data/lib/rubycritic/cli.rb +35 -14
  16. data/lib/rubycritic/configuration.rb +24 -0
  17. data/lib/rubycritic/core/analysed_file.rb +50 -0
  18. data/lib/rubycritic/{location.rb → core/location.rb} +6 -2
  19. data/lib/rubycritic/core/rating.rb +22 -0
  20. data/lib/rubycritic/{smell.rb → core/smell.rb} +5 -12
  21. data/lib/rubycritic/files_initializer.rb +15 -0
  22. data/lib/rubycritic/orchestrator.rb +23 -0
  23. data/lib/rubycritic/report_generators/assets/javascripts/application.js +87 -8
  24. data/lib/rubycritic/report_generators/assets/javascripts/highcharts.src-4.0.1.js +17672 -0
  25. data/lib/rubycritic/report_generators/assets/javascripts/jquery.floatThead-v1.2.7.js +754 -0
  26. data/lib/rubycritic/report_generators/assets/javascripts/jquery.scrollTo-1.4.11.js +186 -0
  27. data/lib/rubycritic/report_generators/assets/javascripts/jquery.tablesorter-2.0.js +1031 -0
  28. data/lib/rubycritic/report_generators/assets/javascripts/jquery.timeago-v1.4.1.js +214 -0
  29. data/lib/rubycritic/report_generators/assets/stylesheets/application.css +204 -1
  30. data/lib/rubycritic/report_generators/assets/stylesheets/prettify.custom_theme.css +1 -4
  31. data/lib/rubycritic/report_generators/base.rb +49 -0
  32. data/lib/rubycritic/report_generators/code_file.rb +38 -0
  33. data/lib/rubycritic/report_generators/code_index.rb +24 -0
  34. data/lib/rubycritic/report_generators/current_code_file.rb +17 -0
  35. data/lib/rubycritic/report_generators/line.rb +31 -0
  36. data/lib/rubycritic/report_generators/overview.rb +25 -0
  37. data/lib/rubycritic/report_generators/smells_index.rb +24 -0
  38. data/lib/rubycritic/report_generators/templates/code_file.html.erb +36 -0
  39. data/lib/rubycritic/report_generators/templates/code_index.html.erb +26 -0
  40. data/lib/rubycritic/report_generators/templates/layouts/application.html.erb +27 -16
  41. data/lib/rubycritic/report_generators/templates/overview.html.erb +5 -0
  42. data/lib/rubycritic/report_generators/templates/smells_index.html.erb +20 -0
  43. data/lib/rubycritic/report_generators/view_helpers.rb +28 -9
  44. data/lib/rubycritic/reporters/base.rb +24 -0
  45. data/lib/rubycritic/reporters/main.rb +52 -0
  46. data/lib/rubycritic/reporters/mini.rb +30 -0
  47. data/lib/rubycritic/revision_comparator.rb +21 -28
  48. data/lib/rubycritic/serializer.rb +32 -0
  49. data/lib/rubycritic/smells_status_setter.rb +7 -16
  50. data/lib/rubycritic/source_control_systems/base.rb +60 -0
  51. data/lib/rubycritic/source_control_systems/double.rb +19 -0
  52. data/lib/rubycritic/source_control_systems/git.rb +47 -37
  53. data/lib/rubycritic/source_locator.rb +8 -12
  54. data/lib/rubycritic/turbulence.rb +17 -0
  55. data/lib/rubycritic/version.rb +1 -1
  56. data/lib/rubycritic.rb +2 -27
  57. data/rubycritic.gemspec +3 -0
  58. data/test/lib/rubycritic/adapters/complexity/flog_test.rb +18 -0
  59. data/test/lib/rubycritic/adapters/smell/flay_test.rb +34 -0
  60. data/test/lib/rubycritic/adapters/smell/flog_test.rb +26 -0
  61. data/test/lib/rubycritic/adapters/smell/reek_test.rb +35 -0
  62. data/test/lib/rubycritic/analysers/churn_test.rb +38 -0
  63. data/test/lib/rubycritic/configuration_test.rb +17 -0
  64. data/test/lib/rubycritic/core/analysed_file_test.rb +71 -0
  65. data/test/lib/rubycritic/{location_test.rb → core/location_test.rb} +8 -4
  66. data/test/lib/rubycritic/core/smell_test.rb +73 -0
  67. data/test/lib/rubycritic/{smells_array_test.rb → core/smells_array_test.rb} +1 -1
  68. data/test/lib/rubycritic/smells_status_setter_test.rb +5 -5
  69. data/test/lib/rubycritic/source_control_systems/source_control_system_test.rb +5 -11
  70. data/test/lib/rubycritic/source_locator_test.rb +26 -17
  71. data/test/lib/rubycritic/turbulence_test.rb +17 -0
  72. data/test/lib/rubycritic/version_test.rb +1 -0
  73. data/test/samples/flay/smelly.rb +17 -0
  74. data/test/samples/flog/complex.rb +11 -0
  75. data/test/samples/flog/smelly.rb +7 -2
  76. data/test/samples/reek/not_smelly.rb +31 -3
  77. data/test/test_helper.rb +1 -0
  78. metadata +97 -32
  79. data/SPEC.md +0 -58
  80. data/lib/rubycritic/report_generators/base_generator.rb +0 -42
  81. data/lib/rubycritic/report_generators/file_generator.rb +0 -42
  82. data/lib/rubycritic/report_generators/index_generator.rb +0 -28
  83. data/lib/rubycritic/report_generators/line_generator.rb +0 -27
  84. data/lib/rubycritic/report_generators/reporter.rb +0 -45
  85. data/lib/rubycritic/report_generators/templates/file.html.erb +0 -3
  86. data/lib/rubycritic/report_generators/templates/index.html.erb +0 -14
  87. data/lib/rubycritic/smell_adapters/flog.rb +0 -41
  88. data/lib/rubycritic/smell_adapters/reek.rb +0 -35
  89. data/lib/rubycritic/smells_aggregator.rb +0 -29
  90. data/lib/rubycritic/smelly_pathnames_serializer.rb +0 -34
  91. data/lib/rubycritic/source_control_systems/source_control_system.rb +0 -42
  92. data/test/lib/rubycritic/metric_adapters/flog_adapter_test.rb +0 -25
  93. data/test/lib/rubycritic/metric_adapters/reek_adapter_test.rb +0 -34
  94. data/test/lib/rubycritic/smell_test.rb +0 -71
  95. data/test/lib/rubycritic/smells_aggregator_test.rb +0 -47
  96. /data/lib/rubycritic/report_generators/assets/javascripts/{prettify.js → prettify-4-Mar-2013.js} +0 -0
@@ -0,0 +1,214 @@
1
+ /**
2
+ * Timeago is a jQuery plugin that makes it easy to support automatically
3
+ * updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago").
4
+ *
5
+ * @name timeago
6
+ * @version 1.4.1
7
+ * @requires jQuery v1.2.3+
8
+ * @author Ryan McGeary
9
+ * @license MIT License - http://www.opensource.org/licenses/mit-license.php
10
+ *
11
+ * For usage and examples, visit:
12
+ * http://timeago.yarp.com/
13
+ *
14
+ * Copyright (c) 2008-2013, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org)
15
+ */
16
+
17
+ (function (factory) {
18
+ if (typeof define === 'function' && define.amd) {
19
+ // AMD. Register as an anonymous module.
20
+ define(['jquery'], factory);
21
+ } else {
22
+ // Browser globals
23
+ factory(jQuery);
24
+ }
25
+ }(function ($) {
26
+ $.timeago = function(timestamp) {
27
+ if (timestamp instanceof Date) {
28
+ return inWords(timestamp);
29
+ } else if (typeof timestamp === "string") {
30
+ return inWords($.timeago.parse(timestamp));
31
+ } else if (typeof timestamp === "number") {
32
+ return inWords(new Date(timestamp));
33
+ } else {
34
+ return inWords($.timeago.datetime(timestamp));
35
+ }
36
+ };
37
+ var $t = $.timeago;
38
+
39
+ $.extend($.timeago, {
40
+ settings: {
41
+ refreshMillis: 60000,
42
+ allowPast: true,
43
+ allowFuture: false,
44
+ localeTitle: false,
45
+ cutoff: 0,
46
+ strings: {
47
+ prefixAgo: null,
48
+ prefixFromNow: null,
49
+ suffixAgo: "ago",
50
+ suffixFromNow: "from now",
51
+ inPast: 'any moment now',
52
+ seconds: "less than a minute",
53
+ minute: "about a minute",
54
+ minutes: "%d minutes",
55
+ hour: "about an hour",
56
+ hours: "about %d hours",
57
+ day: "a day",
58
+ days: "%d days",
59
+ month: "about a month",
60
+ months: "%d months",
61
+ year: "about a year",
62
+ years: "%d years",
63
+ wordSeparator: " ",
64
+ numbers: []
65
+ }
66
+ },
67
+
68
+ inWords: function(distanceMillis) {
69
+ if(!this.settings.allowPast && ! this.settings.allowFuture) {
70
+ throw 'timeago allowPast and allowFuture settings can not both be set to false.';
71
+ }
72
+
73
+ var $l = this.settings.strings;
74
+ var prefix = $l.prefixAgo;
75
+ var suffix = $l.suffixAgo;
76
+ if (this.settings.allowFuture) {
77
+ if (distanceMillis < 0) {
78
+ prefix = $l.prefixFromNow;
79
+ suffix = $l.suffixFromNow;
80
+ }
81
+ }
82
+
83
+ if(!this.settings.allowPast && distanceMillis >= 0) {
84
+ return this.settings.strings.inPast;
85
+ }
86
+
87
+ var seconds = Math.abs(distanceMillis) / 1000;
88
+ var minutes = seconds / 60;
89
+ var hours = minutes / 60;
90
+ var days = hours / 24;
91
+ var years = days / 365;
92
+
93
+ function substitute(stringOrFunction, number) {
94
+ var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction;
95
+ var value = ($l.numbers && $l.numbers[number]) || number;
96
+ return string.replace(/%d/i, value);
97
+ }
98
+
99
+ var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||
100
+ seconds < 90 && substitute($l.minute, 1) ||
101
+ minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||
102
+ minutes < 90 && substitute($l.hour, 1) ||
103
+ hours < 24 && substitute($l.hours, Math.round(hours)) ||
104
+ hours < 42 && substitute($l.day, 1) ||
105
+ days < 30 && substitute($l.days, Math.round(days)) ||
106
+ days < 45 && substitute($l.month, 1) ||
107
+ days < 365 && substitute($l.months, Math.round(days / 30)) ||
108
+ years < 1.5 && substitute($l.year, 1) ||
109
+ substitute($l.years, Math.round(years));
110
+
111
+ var separator = $l.wordSeparator || "";
112
+ if ($l.wordSeparator === undefined) { separator = " "; }
113
+ return $.trim([prefix, words, suffix].join(separator));
114
+ },
115
+
116
+ parse: function(iso8601) {
117
+ var s = $.trim(iso8601);
118
+ s = s.replace(/\.\d+/,""); // remove milliseconds
119
+ s = s.replace(/-/,"/").replace(/-/,"/");
120
+ s = s.replace(/T/," ").replace(/Z/," UTC");
121
+ s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400
122
+ s = s.replace(/([\+\-]\d\d)$/," $100"); // +09 -> +0900
123
+ return new Date(s);
124
+ },
125
+ datetime: function(elem) {
126
+ var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title");
127
+ return $t.parse(iso8601);
128
+ },
129
+ isTime: function(elem) {
130
+ // jQuery's `is()` doesn't play well with HTML5 in IE
131
+ return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time");
132
+ }
133
+ });
134
+
135
+ // functions that can be called via $(el).timeago('action')
136
+ // init is default when no action is given
137
+ // functions are called with context of a single element
138
+ var functions = {
139
+ init: function(){
140
+ var refresh_el = $.proxy(refresh, this);
141
+ refresh_el();
142
+ var $s = $t.settings;
143
+ if ($s.refreshMillis > 0) {
144
+ this._timeagoInterval = setInterval(refresh_el, $s.refreshMillis);
145
+ }
146
+ },
147
+ update: function(time){
148
+ var parsedTime = $t.parse(time);
149
+ $(this).data('timeago', { datetime: parsedTime });
150
+ if($t.settings.localeTitle) $(this).attr("title", parsedTime.toLocaleString());
151
+ refresh.apply(this);
152
+ },
153
+ updateFromDOM: function(){
154
+ $(this).data('timeago', { datetime: $t.parse( $t.isTime(this) ? $(this).attr("datetime") : $(this).attr("title") ) });
155
+ refresh.apply(this);
156
+ },
157
+ dispose: function () {
158
+ if (this._timeagoInterval) {
159
+ window.clearInterval(this._timeagoInterval);
160
+ this._timeagoInterval = null;
161
+ }
162
+ }
163
+ };
164
+
165
+ $.fn.timeago = function(action, options) {
166
+ var fn = action ? functions[action] : functions.init;
167
+ if(!fn){
168
+ throw new Error("Unknown function name '"+ action +"' for timeago");
169
+ }
170
+ // each over objects here and call the requested function
171
+ this.each(function(){
172
+ fn.call(this, options);
173
+ });
174
+ return this;
175
+ };
176
+
177
+ function refresh() {
178
+ var data = prepareData(this);
179
+ var $s = $t.settings;
180
+
181
+ if (!isNaN(data.datetime)) {
182
+ if ( $s.cutoff == 0 || Math.abs(distance(data.datetime)) < $s.cutoff) {
183
+ $(this).text(inWords(data.datetime));
184
+ }
185
+ }
186
+ return this;
187
+ }
188
+
189
+ function prepareData(element) {
190
+ element = $(element);
191
+ if (!element.data("timeago")) {
192
+ element.data("timeago", { datetime: $t.datetime(element) });
193
+ var text = $.trim(element.text());
194
+ if ($t.settings.localeTitle) {
195
+ element.attr("title", element.data('timeago').datetime.toLocaleString());
196
+ } else if (text.length > 0 && !($t.isTime(element) && element.attr("title"))) {
197
+ element.attr("title", text);
198
+ }
199
+ }
200
+ return element.data("timeago");
201
+ }
202
+
203
+ function inWords(date) {
204
+ return $t.inWords(distance(date));
205
+ }
206
+
207
+ function distance(date) {
208
+ return (new Date().getTime() - date.getTime());
209
+ }
210
+
211
+ // fix for IE6 suckage
212
+ document.createElement("abbr");
213
+ document.createElement("time");
214
+ }));
@@ -1,8 +1,211 @@
1
+ .group:after {
2
+ content: '';
3
+ display: table;
4
+ clear: both;
5
+ }
6
+
7
+ html {
8
+ overflow-y: scroll;
9
+ }
10
+
11
+ .project-header {
12
+ padding: 20px 0 20px 60px;
13
+ }
14
+
15
+ .logo {
16
+ float: left;
17
+ margin: 0;
18
+ }
19
+
20
+ .logo-link {
21
+ color: black;
22
+ text-decoration: none;
23
+ }
24
+
25
+ .project-nav {
26
+ float: left;
27
+ margin-left: 100px;
28
+ line-height: 2.5em;
29
+ }
30
+
31
+ .project-nav-item {
32
+ color: black;
33
+ margin-right: 40px;
34
+ text-decoration: none;
35
+ }
36
+
37
+ .chart-container {
38
+ max-width: 1000px;
39
+ margin: 0 auto;
40
+ }
41
+
42
+ .index-table {
43
+ width: 100%;
44
+ border-collapse: collapse;
45
+ table-layout: fixed;
46
+ }
47
+
48
+ .index-table th {
49
+ text-align: left;
50
+ padding: 8px 10px;
51
+ border-bottom: 1px solid silver;
52
+ font-size: 1.55em;
53
+ font-weight: normal;
54
+ background-color: white;
55
+ }
56
+
57
+ .index-table .circle {
58
+ width: 28px;
59
+ height: 28px;
60
+ }
61
+
62
+ .index-table .circled-rating {
63
+ display: inline-block;
64
+ line-height: 28px;
65
+ }
66
+
67
+ .sortable-table .headerSortUp,
68
+ .sortable-table .headerSortDown {
69
+ border: 1px solid silver;
70
+ border-bottom: 0;
71
+ }
72
+
73
+ .sortable-table th:hover {
74
+ background-color: #ECECEC;
75
+ cursor: pointer;
76
+ }
77
+
78
+ .index-table td {
79
+ padding: 12px 10px;
80
+ }
81
+
82
+ .index-table .first-cell {
83
+ padding-left: 60px;
84
+ }
85
+
86
+ .index-table .last-cell {
87
+ padding-right: 60px;
88
+ }
89
+
90
+ .index-table .numeric-cell {
91
+ text-align: right;
92
+ }
93
+
94
+ .index-table .centered-cell {
95
+ text-align: center;
96
+ }
97
+
98
+ .button {
99
+ margin: 0;
100
+ padding: 0.5em 1em;
101
+ border: 1px solid black;
102
+ font-size: 0.9em;
103
+ border-radius: 0.2em;
104
+ cursor: pointer;
105
+ transition-property: background-color;
106
+ -webkit-transition-duration: 0.5s;
107
+ transition-duration: 0.5s;
108
+ }
109
+
110
+ .circle {
111
+ display: block;
112
+ border-radius: 50%;
113
+ }
114
+
115
+ .circled-rating {
116
+ text-align: center;
117
+ color: white;
118
+ font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
119
+ font-weight: bold;
120
+ -webkit-user-select: none;
121
+ -moz-user-select: none;
122
+ -ms-user-select: none;
123
+ user-select: none;
124
+ cursor: default;
125
+ }
126
+
127
+ .file-header {
128
+ position: relative;
129
+ padding: 0 0 10px 60px;
130
+ border-bottom: 1px solid silver;
131
+ }
132
+
133
+ .file-header .circle {
134
+ width: 50px;
135
+ height: 50px;
136
+ }
137
+
138
+ .file-header .circled-rating {
139
+ float: left;
140
+ line-height: 50px;
141
+ font-size: 32px;
142
+ }
143
+
144
+ .rating-a {
145
+ background-color: #2ECC40;
146
+ }
147
+
148
+ .rating-b {
149
+ background-color: #2ECC40;
150
+ }
151
+
152
+ .rating-c {
153
+ background-color: #FFDC00;
154
+ }
155
+
156
+ .rating-d {
157
+ background-color: #FF851B;
158
+ }
159
+
160
+ .rating-f {
161
+ background-color: #FF4136;
162
+ }
163
+
164
+ .file-name {
165
+ float: left;
166
+ margin: 0 0 0 20px;
167
+ line-height: 50px;
168
+ font-weight: normal;
169
+ }
170
+
171
+ .file-committed-at {
172
+ float: left;
173
+ margin: 20px 0 0 28px;
174
+ font-size: 13px;
175
+ color: #666666;
176
+ }
177
+
178
+ .file-stats {
179
+ clear: both;
180
+ margin-left: 68px;
181
+ width: 300px;
182
+ }
183
+
184
+ .file-stat {
185
+ float: left;
186
+ margin: 3px;
187
+ width: 130px;
188
+ font-size: 12px;
189
+ white-space: nowrap;
190
+ }
191
+
192
+ .smells-toggle-button {
193
+ position: absolute;
194
+ right: 64px;
195
+ bottom: -17px;
196
+ border-color: silver;
197
+ background-color: #EEEBE9;
198
+ }
199
+
200
+ .smells-toggle-button:hover {
201
+ background-color: #D1CFCD;
202
+ }
203
+
1
204
  .smells {
2
205
  margin: 2px 0 22px 0;
3
206
  padding-left: 0;
4
207
  border: 1px solid #000;
5
- background-color: #DDD;
208
+ background-color: #EEEBE9;
6
209
  white-space: normal;
7
210
  list-style-type: disc;
8
211
  }
@@ -57,10 +57,7 @@
57
57
 
58
58
  /* Specify class=linenums on a pre to get line numbering */
59
59
  .prettyprint ol.linenums {
60
- margin-top: 0;
61
- margin-bottom: 0;
62
- background-color: #EEEBE9;
63
- padding-left: 66px;
60
+ padding-left: 60px;
64
61
  }
65
62
 
66
63
  .prettyprint li {
@@ -0,0 +1,49 @@
1
+ require "erb"
2
+ require "rubycritic/report_generators/view_helpers"
3
+
4
+ module Rubycritic
5
+ module Generator
6
+
7
+ class Base
8
+ def self.erb_template(template_path)
9
+ ERB.new(File.read(File.join(TEMPLATES_DIR, template_path)))
10
+ end
11
+
12
+ TEMPLATES_DIR = File.expand_path("../templates", __FILE__)
13
+ LAYOUT_TEMPLATE = erb_template(File.join("layouts", "application.html.erb"))
14
+
15
+ include ViewHelpers
16
+
17
+ def file_href
18
+ "file://#{file_pathname}"
19
+ end
20
+
21
+ def file_pathname
22
+ File.join(file_directory, file_name)
23
+ end
24
+
25
+ def file_directory
26
+ @file_directory ||= root_directory
27
+ end
28
+
29
+ def file_name
30
+ raise NotImplementedError.new("The #{self.class} class must implement the #{__method__} method.")
31
+ end
32
+
33
+ def render
34
+ raise NotImplementedError.new("The #{self.class} class must implement the #{__method__} method.")
35
+ end
36
+
37
+ private
38
+
39
+ def root_directory
40
+ @root_directory ||= Pathname.new(::Rubycritic.configuration.root)
41
+ end
42
+
43
+ def get_binding
44
+ binding
45
+ end
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,38 @@
1
+ require "rubycritic/report_generators/base"
2
+ require "rubycritic/report_generators/line"
3
+
4
+ module Rubycritic
5
+ module Generator
6
+
7
+ class CodeFile < Base
8
+ LINE_NUMBER_OFFSET = 1
9
+ TEMPLATE = erb_template("code_file.html.erb")
10
+
11
+ def initialize(analysed_file)
12
+ @analysed_file = analysed_file
13
+ @pathname = @analysed_file.pathname
14
+ end
15
+
16
+ def file_directory
17
+ @file_directory ||= root_directory + @pathname.dirname
18
+ end
19
+
20
+ def file_name
21
+ @pathname.basename.sub_ext(".html")
22
+ end
23
+
24
+ def render
25
+ file_code = ""
26
+ File.readlines(@pathname).each.with_index(LINE_NUMBER_OFFSET) do |line_text, line_number|
27
+ location = Location.new(@pathname, line_number)
28
+ line_smells = @analysed_file.smells_at_location(location)
29
+ file_code << Line.new(file_directory, line_text, line_smells).render
30
+ end
31
+
32
+ file_body = TEMPLATE.result(get_binding { file_code })
33
+ LAYOUT_TEMPLATE.result(get_binding { file_body })
34
+ end
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,24 @@
1
+ require "rubycritic/report_generators/base"
2
+
3
+ module Rubycritic
4
+ module Generator
5
+
6
+ class CodeIndex < Base
7
+ TEMPLATE = erb_template("code_index.html.erb")
8
+
9
+ def initialize(analysed_files)
10
+ @analysed_files = analysed_files
11
+ end
12
+
13
+ def file_name
14
+ "code_index.html"
15
+ end
16
+
17
+ def render
18
+ index_body = TEMPLATE.result(get_binding)
19
+ LAYOUT_TEMPLATE.result(get_binding { index_body })
20
+ end
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,17 @@
1
+ require "rubycritic/report_generators/code_file"
2
+
3
+ module Rubycritic
4
+ module Generator
5
+
6
+ class CurrentCodeFile < CodeFile
7
+ def file_directory
8
+ @file_directory ||= root_directory
9
+ end
10
+
11
+ def file_name
12
+ "current_file.html"
13
+ end
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,31 @@
1
+ require "rubycritic/report_generators/base"
2
+ require "cgi"
3
+
4
+ module Rubycritic
5
+ module Generator
6
+
7
+ class Line < Base
8
+ NORMAL_TEMPLATE = erb_template("line.html.erb")
9
+ SMELLY_TEMPLATE = erb_template("smelly_line.html.erb")
10
+
11
+ attr_reader :file_directory
12
+
13
+ def initialize(file_directory, text, smells)
14
+ @file_directory = file_directory
15
+ @text = CGI::escapeHTML(text.chomp)
16
+ @smells = smells
17
+ @template =
18
+ if @smells.empty?
19
+ NORMAL_TEMPLATE
20
+ else
21
+ SMELLY_TEMPLATE
22
+ end
23
+ end
24
+
25
+ def render
26
+ @template.result(binding).delete("\n") + "\n"
27
+ end
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,25 @@
1
+ require "rubycritic/report_generators/base"
2
+ require "rubycritic/turbulence"
3
+
4
+ module Rubycritic
5
+ module Generator
6
+
7
+ class Overview < Base
8
+ TEMPLATE = erb_template("overview.html.erb")
9
+
10
+ def initialize(analysed_files)
11
+ @turbulence_data = Turbulence.data(analysed_files)
12
+ end
13
+
14
+ def file_name
15
+ "overview.html"
16
+ end
17
+
18
+ def render
19
+ index_body = TEMPLATE.result(get_binding)
20
+ LAYOUT_TEMPLATE.result(get_binding { index_body })
21
+ end
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,24 @@
1
+ require "rubycritic/report_generators/base"
2
+
3
+ module Rubycritic
4
+ module Generator
5
+
6
+ class SmellsIndex < Base
7
+ TEMPLATE = erb_template("smells_index.html.erb")
8
+
9
+ def initialize(smells)
10
+ @smells = smells
11
+ end
12
+
13
+ def file_name
14
+ "smells_index.html"
15
+ end
16
+
17
+ def render
18
+ index_body = TEMPLATE.result(get_binding)
19
+ LAYOUT_TEMPLATE.result(get_binding { index_body })
20
+ end
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,36 @@
1
+ <div class="file-header group">
2
+ <span class="rating-<%= @analysed_file.rating.to_s.downcase %> circled-rating circle "><%= @analysed_file.rating %></span>
3
+ <h2 class="file-name"><%= @analysed_file.name %></h2>
4
+
5
+ <span class="file-committed-at">
6
+ <% if @analysed_file.committed_at %>
7
+ Updated <%= timeago_tag(@analysed_file.committed_at) %></span>
8
+ <% else %>
9
+ Never committed
10
+ <% end %>
11
+ </span>
12
+
13
+ <div class="file-stats group">
14
+ <div class="file-stat">
15
+ <%= @analysed_file.complexity %> complexity
16
+ </div>
17
+ <div class="file-stat">
18
+ <%= @analysed_file.complexity_per_method %> complexity per method
19
+ </div>
20
+ <div class="file-stat">
21
+ <%= @analysed_file.churn %> churn
22
+ </div>
23
+ <div class="file-stat">
24
+ <%= @analysed_file.methods_count %> methods
25
+ </div>
26
+ <div class="file-stat">
27
+ <%= @analysed_file.duplication %> duplication
28
+ </div>
29
+ </div>
30
+
31
+ <% if @analysed_file.has_smells? %>
32
+ <button id="js-toggle-smells" class="smells-toggle-button button">Toggle Smells</button>
33
+ <% end %>
34
+ </div>
35
+
36
+ <code class="prettyprint linenums lang-ruby file-code js-file-code"><%= yield %></code>