atoulme-Saikuro 1.1.2 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|