atoulme-Saikuro 1.1.2 → 1.2.1
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/README.rdoc +10 -22
- data/bin/saikuro +2 -1
- data/lib/saikuro.rb +113 -130
- metadata +8 -9
- data/lib/saikuro/usage.rb +0 -39
data/README.rdoc
CHANGED
@@ -1,29 +1,15 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
Saikuro:
|
1
|
+
=Saikuro
|
4
2
|
Saikuro is a Ruby cyclomatic complexity analyzer. When given Ruby
|
5
3
|
source code Saikuro will generate a report listing the cyclomatic
|
6
4
|
complexity of each method found. In addition, Saikuro counts the
|
7
5
|
number of lines per method and can generate a listing of the number of
|
8
6
|
tokens on each line of code.
|
9
7
|
|
10
|
-
License:
|
11
|
-
Saikuro uses the BSD license.
|
12
|
-
|
13
|
-
Installation:
|
14
|
-
Option 1: Using setup.rb
|
15
|
-
* login as root
|
16
|
-
* run "ruby setup.rb all"
|
17
|
-
|
18
|
-
Option 2: The manual way
|
19
|
-
Saikuro is a single Ruby file that is executable. You can run it where
|
20
|
-
you unpacked it or you can move it your preferred location such as
|
21
|
-
"/usr/local/bin" or "~/bin".
|
8
|
+
==License:
|
9
|
+
Saikuro uses the BSD license. See attached LICENSE file.
|
22
10
|
|
23
|
-
|
24
|
-
|
25
|
-
running. If you are using 1.8.5 please apply this patch :
|
26
|
-
http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/ruby/lib/rdoc/ri/ri_options.rb.diff?r1=1.2.2.13;r2=1.2.2.14
|
11
|
+
==Installation:
|
12
|
+
Install atoulme-Saikuro using gem install and have at it.
|
27
13
|
|
28
14
|
|
29
15
|
=Usage:
|
@@ -31,7 +17,7 @@ http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/ruby/lib/rdoc/ri/ri_options.rb.diff?
|
|
31
17
|
Running "saikuro -h" will output a usage statement describing all
|
32
18
|
the various arguments you can pass to it.
|
33
19
|
|
34
|
-
|
20
|
+
saikuro -c -p tests/samples.rb
|
35
21
|
|
36
22
|
The above command is a simple example that generates a cyclomatic
|
37
23
|
complexity report on the samples.rb file, using the default filter,
|
@@ -40,7 +26,7 @@ directory.
|
|
40
26
|
|
41
27
|
|
42
28
|
A more detailed example is
|
43
|
-
|
29
|
+
saikuro -c -t -i tests -y 0 -w 11 -e 16 -o out/
|
44
30
|
|
45
31
|
This will analyze all Ruby files found in the "tests/" directory.
|
46
32
|
Saikuro will generate a token count report and a cyclomatic complexity
|
@@ -108,7 +94,7 @@ currently do not contribute to a method's complexity, although
|
|
108
94
|
McCabe's paper listed above suggests doing so.
|
109
95
|
|
110
96
|
|
111
|
-
#Example for "and" operator handling:
|
97
|
+
#Example for "and" operator handling:
|
112
98
|
|
113
99
|
# Starting values for case 1 and 2
|
114
100
|
x = false
|
@@ -145,6 +131,8 @@ please report them.
|
|
145
131
|
=Contact:
|
146
132
|
Saikuro is written by
|
147
133
|
Zev Blut (zb at ubit dot com)
|
134
|
+
Morton Jonuschat
|
135
|
+
Antoine Toulme (antoine at lunar-ocean.com)
|
148
136
|
|
149
137
|
=Acknowledgments:
|
150
138
|
Thanks to Elbert Corpuz for writing the CSS for the HTML output!
|
data/bin/saikuro
CHANGED
data/lib/saikuro.rb
CHANGED
@@ -1,55 +1,8 @@
|
|
1
|
-
# $Id$
|
2
|
-
# == Usage
|
3
|
-
#
|
4
|
-
# saikuro [ -h ] [-o output_directory] [-f type] [ -c, -t ]
|
5
|
-
# [ -y, -w, -e, -k, -s, -d - number ] ( -p file | -i directory )
|
6
|
-
#
|
7
|
-
# == Help
|
8
|
-
#
|
9
|
-
# -o, --output_directory (directory) : A directory to ouput the results in.
|
10
|
-
# The current directory is used if this option is not passed.
|
11
|
-
#
|
12
|
-
# -h, --help : This help message.
|
13
|
-
#
|
14
|
-
# -f, --formater (html | text) : The format to output the results in.
|
15
|
-
# The default is html
|
16
|
-
#
|
17
|
-
# -c, --cyclo : Compute the cyclomatic complexity of the input.
|
18
|
-
#
|
19
|
-
# -t, --token : Count the number of tokens per line of the input.
|
20
|
-
#
|
21
|
-
# -y, --filter_cyclo (number) : Filter the output to only include methods
|
22
|
-
# whose cyclomatic complexity are greater than the passed number.
|
23
|
-
#
|
24
|
-
# -w, --warn_cyclo (number) : Highlight with a warning methods whose
|
25
|
-
# cyclomatic complexity are greather than or equal to the passed number.
|
26
|
-
#
|
27
|
-
#
|
28
|
-
# -e, --error_cyclo (number) : Highligh with an error methods whose
|
29
|
-
# cyclomatic complexity are greather than or equal to the passed number.
|
30
|
-
#
|
31
|
-
#
|
32
|
-
# -k, --filter_token (number) : Filter the output to only include lines
|
33
|
-
# whose token count are greater than the passed number.
|
34
|
-
#
|
35
|
-
#
|
36
|
-
# -s, --warn_token (number) : Highlight with a warning lines whose
|
37
|
-
# token count are greater than or equal to the passed number.
|
38
|
-
#
|
39
|
-
#
|
40
|
-
# -d, --error_token (number) : Highlight with an error lines whose
|
41
|
-
# token count are greater than or equal to the passed number.
|
42
|
-
#
|
43
|
-
#
|
44
|
-
# -p, --parse_file (file) : A file to use as input.
|
45
|
-
#
|
46
|
-
# -i, --input_directory (directory) : All ruby files found recursively
|
47
|
-
# inside the directory are passed as input.
|
48
|
-
|
49
|
-
|
50
1
|
# Saikruo uses the BSD license.
|
51
2
|
#
|
52
3
|
# Copyright (c) 2005, Ubiquitous Business Technology (http://ubit.com)
|
4
|
+
# Copyright (c) 2010, Morton Jonuschat (http://www.github.com/yabawock)
|
5
|
+
# Copyright (c) 2010, Antoine Toulme (http://www.lunar-ocean.com)
|
53
6
|
# All rights reserved.
|
54
7
|
#
|
55
8
|
# Redistribution and use in source and binary forms, with or without
|
@@ -85,6 +38,8 @@
|
|
85
38
|
#
|
86
39
|
# == Author
|
87
40
|
# Zev Blut (zb@ubit.com)
|
41
|
+
# Morton Jonuschat
|
42
|
+
# Antoine Toulme (antoine@lunar-ocean.com)
|
88
43
|
|
89
44
|
require 'irb/ruby-lex'
|
90
45
|
require 'yaml'
|
@@ -419,8 +374,8 @@ class ParseState
|
|
419
374
|
def end_debug
|
420
375
|
STDOUT.puts "got an end: #{@name} in #{self.class.name}" if $VERBOSE
|
421
376
|
if @parent.nil?
|
422
|
-
STDOUT.puts "DEBUG: Line #{@lexer.line_no}"
|
423
|
-
STDOUT.puts "DEBUG: #{@name}; #{self.class}"
|
377
|
+
STDOUT.puts "DEBUG: Line #{@lexer.line_no}" if $VERBOSE
|
378
|
+
STDOUT.puts "DEBUG: #{@name}; #{self.class}" if $VERBOSE
|
424
379
|
# to_yaml can cause an infinite loop?
|
425
380
|
#STDOUT.puts "TOP: #{@@top_state.to_yaml}"
|
426
381
|
#STDOUT.puts "TOP: #{@@top_state.inspect}"
|
@@ -1098,17 +1053,10 @@ end
|
|
1098
1053
|
|
1099
1054
|
class SaikuroCMDLineRunner
|
1100
1055
|
require 'stringio'
|
1101
|
-
require '
|
1056
|
+
require 'optparse'
|
1102
1057
|
require 'fileutils'
|
1103
1058
|
require 'find'
|
1104
1059
|
|
1105
|
-
def initialize
|
1106
|
-
# modification to RDoc.usage that allows main_program_file to be set
|
1107
|
-
# for RDoc.usage
|
1108
|
-
require 'saikuro/usage'
|
1109
|
-
RDoc::main_program_file = __FILE__
|
1110
|
-
end
|
1111
|
-
|
1112
1060
|
include ResultIndexGenerator
|
1113
1061
|
|
1114
1062
|
def get_ruby_files(path)
|
@@ -1122,91 +1070,126 @@ class SaikuroCMDLineRunner
|
|
1122
1070
|
end
|
1123
1071
|
files
|
1124
1072
|
end
|
1073
|
+
|
1074
|
+
def parse(args)
|
1075
|
+
# Set up reasonable defaults for options.
|
1076
|
+
options = {}
|
1077
|
+
options[:files] = Array.new
|
1078
|
+
options[:output_dir] = './'
|
1079
|
+
options[:formater] = 'html'
|
1080
|
+
options[:state_filter] = Filter.new(5)
|
1081
|
+
options[:token_filter] = Filter.new(10, 25, 50)
|
1082
|
+
options[:comp_state] = false
|
1083
|
+
options[:comp_token] = false
|
1084
|
+
|
1085
|
+
# Parse the command-line arguments.
|
1086
|
+
@opts = OptionParser.new do |opts|
|
1087
|
+
opts.banner = 'Usage: saikuro [ -h ] [-o output_directory] [-f type] [ -c, -t ] [ -y, -w, -e, -k, -s, -d - number ] ( -p file | -i directory )'
|
1088
|
+
|
1089
|
+
opts.separator ''
|
1090
|
+
opts.separator 'Specific options:'
|
1091
|
+
|
1092
|
+
opts.on('-v', '--verbose', 'Verbose output.') do
|
1093
|
+
options[:verbose] = true
|
1094
|
+
$VERBOSE = true
|
1095
|
+
end
|
1125
1096
|
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
formater = "html"
|
1130
|
-
state_filter = Filter.new(5)
|
1131
|
-
token_filter = Filter.new(10, 25, 50)
|
1132
|
-
comp_state = comp_token = false
|
1133
|
-
begin
|
1134
|
-
opt = GetoptLong.new(
|
1135
|
-
["-o","--output_directory", GetoptLong::REQUIRED_ARGUMENT],
|
1136
|
-
["-h","--help", GetoptLong::NO_ARGUMENT],
|
1137
|
-
["-f","--formater", GetoptLong::REQUIRED_ARGUMENT],
|
1138
|
-
["-c","--cyclo", GetoptLong::NO_ARGUMENT],
|
1139
|
-
["-t","--token", GetoptLong::NO_ARGUMENT],
|
1140
|
-
["-y","--filter_cyclo", GetoptLong::REQUIRED_ARGUMENT],
|
1141
|
-
["-k","--filter_token", GetoptLong::REQUIRED_ARGUMENT],
|
1142
|
-
["-w","--warn_cyclo", GetoptLong::REQUIRED_ARGUMENT],
|
1143
|
-
["-s","--warn_token", GetoptLong::REQUIRED_ARGUMENT],
|
1144
|
-
["-e","--error_cyclo", GetoptLong::REQUIRED_ARGUMENT],
|
1145
|
-
["-d","--error_token", GetoptLong::REQUIRED_ARGUMENT],
|
1146
|
-
["-p","--parse_file", GetoptLong::REQUIRED_ARGUMENT],
|
1147
|
-
["-i","--input_directory", GetoptLong::REQUIRED_ARGUMENT],
|
1148
|
-
["-v","--verbose", GetoptLong::NO_ARGUMENT]
|
1149
|
-
)
|
1150
|
-
|
1151
|
-
opt.each do |arg,val|
|
1152
|
-
case arg
|
1153
|
-
when "-o"
|
1154
|
-
output_dir = val
|
1155
|
-
when "-h"
|
1156
|
-
RDoc.usage('help')
|
1157
|
-
when "-f"
|
1158
|
-
formater = val
|
1159
|
-
when "-c"
|
1160
|
-
comp_state = true
|
1161
|
-
when "-t"
|
1162
|
-
comp_token = true
|
1163
|
-
when "-k"
|
1164
|
-
token_filter.limit = val.to_i
|
1165
|
-
when "-s"
|
1166
|
-
token_filter.warn = val.to_i
|
1167
|
-
when "-d"
|
1168
|
-
token_filter.error = val.to_i
|
1169
|
-
when "-y"
|
1170
|
-
state_filter.limit = val.to_i
|
1171
|
-
when "-w"
|
1172
|
-
state_filter.warn = val.to_i
|
1173
|
-
when "-e"
|
1174
|
-
state_filter.error = val.to_i
|
1175
|
-
when "-p"
|
1176
|
-
files<< val
|
1177
|
-
when "-i"
|
1178
|
-
files.concat(get_ruby_files(val))
|
1179
|
-
when "-v"
|
1180
|
-
STDOUT.puts "Verbose mode on"
|
1181
|
-
$VERBOSE = true
|
1182
|
-
end
|
1097
|
+
opts.on('-o', '--output_directory DIRECTORY', 'A directory to ouput the results in. The current directory is used if this option is not passed.') do |output_dir|
|
1098
|
+
options[:output_dir] = output_dir
|
1099
|
+
end
|
1183
1100
|
|
1101
|
+
opts.on('-f', '--formater (html | text)', 'The format to output the results in. The default is html') do |formater|
|
1102
|
+
options[:formater] = formater
|
1103
|
+
end
|
1104
|
+
|
1105
|
+
opts.on('-c', '--cyclo', 'Compute the cyclomatic complexity of the input.') do
|
1106
|
+
options[:comp_state] = true
|
1107
|
+
end
|
1108
|
+
|
1109
|
+
opts.on('-t', '--token', 'Count the number of tokens per line of the input.') do
|
1110
|
+
options[:comp_token] = true
|
1111
|
+
end
|
1112
|
+
|
1113
|
+
opts.on('-y', '--filter_cyclo NUMBER', 'Filter the output to only include methods whose cyclomatic complexity are greater than the passed number.') do |number|
|
1114
|
+
options[:state_filter].limit = number.to_i
|
1115
|
+
end
|
1116
|
+
|
1117
|
+
opts.on('-w', '--warn_cyclo NUMBER', 'Highlight with a warning methods whose cyclomatic complexity are greather than or equal to the passed number.') do |number|
|
1118
|
+
options[:state_filter].warn = number.to_i
|
1119
|
+
end
|
1120
|
+
|
1121
|
+
opts.on('-e', '--error_cyclo NUMBER', 'Highlight with a error methods whose cyclomatic complexity are greather than or equal to the passed number.') do |number|
|
1122
|
+
options[:state_filter].error = number.to_i
|
1123
|
+
end
|
1124
|
+
|
1125
|
+
opts.on('-k', '--filter_token NUMBER', 'Filter the output to only include lines whose token count are greater than the passed number.') do |number|
|
1126
|
+
options[:token_filter].limit = number.to_i
|
1127
|
+
end
|
1128
|
+
|
1129
|
+
opts.on('-s', '--warn_token NUMBER', 'Highlight with a warning lines whose token count are greather than or equal to the passed number.') do |number|
|
1130
|
+
options[:token_filter].warn = number.to_i
|
1131
|
+
end
|
1132
|
+
|
1133
|
+
opts.on('-d', '--error_token NUMBER', 'Highlight with a error lines whose token count are greather than or equal to the passed number.') do |number|
|
1134
|
+
options[:token_filter].error = number.to_i
|
1135
|
+
end
|
1136
|
+
|
1137
|
+
opts.on('-p', '--parse_file FILE', 'A file to use as input.') do |file|
|
1138
|
+
options[:files] << file
|
1139
|
+
end
|
1140
|
+
|
1141
|
+
opts.on('-i', '--input_directory DIRECTORY', 'All ruby files found recursively inside the directory are passed as input.') do |directory|
|
1142
|
+
options[:files].concat(get_ruby_files(directory))
|
1143
|
+
end
|
1144
|
+
|
1145
|
+
opts.separator ''
|
1146
|
+
|
1147
|
+
# No argument, shows at tail. This will print an options summary.
|
1148
|
+
# Try it and see!
|
1149
|
+
opts.on_tail('-h', '--help', 'Show this message') do
|
1150
|
+
puts opts
|
1151
|
+
exit
|
1184
1152
|
end
|
1185
|
-
RDoc.usage if !comp_state && !comp_token
|
1186
|
-
rescue => err
|
1187
|
-
RDoc.usage
|
1188
1153
|
end
|
1189
1154
|
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1155
|
+
@opts.parse! args
|
1156
|
+
options
|
1157
|
+
end
|
1158
|
+
|
1159
|
+
def initialize(args="-h")
|
1160
|
+
@options = parse(args)
|
1161
|
+
show_help_message("No input files specified") if @options[:files].empty?
|
1162
|
+
show_help_message('Please choose token or cyclo mode') if !@options[:comp_state] && !@options[:comp_token]
|
1163
|
+
end
|
1164
|
+
|
1165
|
+
def run!
|
1166
|
+
if @options[:formater] =~ /html/i
|
1167
|
+
state_formater = StateHTMLComplexityFormater.new(STDOUT,@options[:state_filter])
|
1168
|
+
token_count_formater = HTMLTokenCounterFormater.new(STDOUT,@options[:token_filter])
|
1193
1169
|
else
|
1194
|
-
state_formater = ParseStateFormater.new(STDOUT
|
1195
|
-
token_count_formater = TokenCounterFormater.new(STDOUT
|
1170
|
+
state_formater = ParseStateFormater.new(STDOUT,@options[:state_filter])
|
1171
|
+
token_count_formater = TokenCounterFormater.new(STDOUT,@options[:token_filter])
|
1196
1172
|
end
|
1197
1173
|
|
1198
|
-
state_formater = nil if
|
1199
|
-
token_count_formater = nil if
|
1174
|
+
state_formater = nil if !@options[:comp_state]
|
1175
|
+
token_count_formater = nil if !@options[:comp_token]
|
1200
1176
|
|
1201
|
-
idx_states, idx_tokens = Saikuro.analyze(files,
|
1177
|
+
idx_states, idx_tokens = Saikuro.analyze(@options[:files],
|
1202
1178
|
state_formater,
|
1203
1179
|
token_count_formater,
|
1204
|
-
output_dir)
|
1180
|
+
@options[:output_dir])
|
1205
1181
|
|
1206
|
-
write_cyclo_index(idx_states, output_dir)
|
1207
|
-
write_token_index(idx_tokens, output_dir)
|
1182
|
+
write_cyclo_index(idx_states, @options[:output_dir])
|
1183
|
+
write_token_index(idx_tokens, @options[:output_dir])
|
1208
1184
|
end
|
1209
1185
|
|
1186
|
+
private
|
1187
|
+
|
1188
|
+
def show_help_message(msg)
|
1189
|
+
puts "Error starting script: #{msg}\n\n"
|
1190
|
+
puts @opts.help
|
1191
|
+
exit
|
1192
|
+
end
|
1210
1193
|
end
|
1211
1194
|
|
1212
1195
|
#
|
metadata
CHANGED
@@ -1,26 +1,26 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: atoulme-Saikuro
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 29
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
- 1
|
9
8
|
- 2
|
10
|
-
|
9
|
+
- 1
|
10
|
+
version: 1.2.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
|
-
- Zev Blut, Antoine Toulme
|
13
|
+
- Zev Blut, Morton Jonuschat, Antoine Toulme
|
14
14
|
autorequire:
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-07-
|
18
|
+
date: 2010-07-24 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
22
22
|
description:
|
23
|
-
email:
|
23
|
+
email: antoine@lunar-ocean.com
|
24
24
|
executables:
|
25
25
|
- saikuro
|
26
26
|
extensions: []
|
@@ -29,13 +29,12 @@ extra_rdoc_files:
|
|
29
29
|
- README.rdoc
|
30
30
|
files:
|
31
31
|
- bin/saikuro
|
32
|
-
- lib/saikuro/usage.rb
|
33
32
|
- lib/saikuro.rb
|
34
33
|
- tests/large_example.rb
|
35
34
|
- tests/samples.rb
|
36
35
|
- README.rdoc
|
37
36
|
has_rdoc: true
|
38
|
-
homepage: http://
|
37
|
+
homepage: http://www.github.com/atoulme/Saikuro
|
39
38
|
licenses: []
|
40
39
|
|
41
40
|
post_install_message:
|
@@ -63,7 +62,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
63
62
|
version: "0"
|
64
63
|
requirements: []
|
65
64
|
|
66
|
-
rubyforge_project:
|
65
|
+
rubyforge_project:
|
67
66
|
rubygems_version: 1.3.7
|
68
67
|
signing_key:
|
69
68
|
specification_version: 3
|
data/lib/saikuro/usage.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
# This is a patch to RDoc so that when saikuro is installed as a
|
2
|
-
# RubyGem usage will read the proper file.
|
3
|
-
|
4
|
-
require 'rdoc/usage'
|
5
|
-
|
6
|
-
module RDoc
|
7
|
-
|
8
|
-
def RDoc.main_program_file=(file)
|
9
|
-
@@main_program_file = file
|
10
|
-
end
|
11
|
-
|
12
|
-
# Display usage
|
13
|
-
def RDoc.usage_no_exit(*args)
|
14
|
-
@@main_program_file ||= caller[-1].sub(/:\d+$/, '')
|
15
|
-
comment = File.open(@@main_program_file) do |file|
|
16
|
-
find_comment(file)
|
17
|
-
end
|
18
|
-
|
19
|
-
comment = comment.gsub(/^\s*#/, '')
|
20
|
-
|
21
|
-
markup = SM::SimpleMarkup.new
|
22
|
-
flow_convertor = SM::ToFlow.new
|
23
|
-
|
24
|
-
flow = markup.convert(comment, flow_convertor)
|
25
|
-
|
26
|
-
format = "plain"
|
27
|
-
|
28
|
-
unless args.empty?
|
29
|
-
flow = extract_sections(flow, args)
|
30
|
-
end
|
31
|
-
|
32
|
-
options = RI::Options.instance
|
33
|
-
if args = ENV["RI"]
|
34
|
-
options.parse(args.split)
|
35
|
-
end
|
36
|
-
formatter = options.formatter.new(options, "")
|
37
|
-
formatter.display_flow(flow)
|
38
|
-
end
|
39
|
-
end
|