saikuro 1.2.0 → 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/bin/saikuro +0 -2
- data/lib/saikuro.rb +13 -268
- data/lib/saikuro/base_formater.rb +33 -0
- data/lib/saikuro/cli.rb +1 -5
- data/lib/saikuro/html_style_sheet.rb +85 -0
- data/lib/saikuro/html_token_counter_formater.rb +48 -0
- data/lib/saikuro/parse_state_formater.rb +30 -0
- data/lib/saikuro/result_index_generator.rb +69 -68
- data/lib/saikuro/state_html_complexity_formater.rb +41 -0
- data/lib/saikuro/token_counter_formater.rb +37 -0
- data/lib/saikuro/version.rb +1 -1
- data/saikuro.gemspec +1 -1
- metadata +9 -3
data/bin/saikuro
CHANGED
data/lib/saikuro.rb
CHANGED
@@ -1,6 +1,15 @@
|
|
1
1
|
require "saikuro/version"
|
2
2
|
|
3
|
+
require "saikuro/html_style_sheet"
|
4
|
+
|
3
5
|
require "saikuro/result_index_generator"
|
6
|
+
|
7
|
+
require "saikuro/base_formater"
|
8
|
+
require "saikuro/token_counter_formater"
|
9
|
+
require "saikuro/parse_state_formater"
|
10
|
+
require "saikuro/html_token_counter_formater"
|
11
|
+
require "saikuro/state_html_complexity_formater"
|
12
|
+
|
4
13
|
require "saikuro/cli"
|
5
14
|
|
6
15
|
require 'irb/ruby-lex'
|
@@ -23,9 +32,9 @@ def get_ruby_files(path)
|
|
23
32
|
files = Array.new
|
24
33
|
Find.find(path) do |f|
|
25
34
|
if !FileTest.directory?(f)
|
26
|
-
if f =~ /rb$/
|
27
|
-
|
28
|
-
end
|
35
|
+
if f =~ /rb$/
|
36
|
+
files<< f
|
37
|
+
end
|
29
38
|
end
|
30
39
|
end
|
31
40
|
files
|
@@ -190,7 +199,7 @@ class ParseState
|
|
190
199
|
end
|
191
200
|
@last_token_line_and_char<< [@lexer.line_no.to_i, @lexer.char_no.to_i, tok]
|
192
201
|
if $VERBOSE
|
193
|
-
|
202
|
+
puts "DEBUG: #{@lexer.line_no} #{tok.class}:#{tok.name if tok.respond_to?(:name)}"
|
194
203
|
end
|
195
204
|
@@token_counter.count_token(@lexer.line_no, tok) if count_tokens?
|
196
205
|
parse_token(tok)
|
@@ -603,270 +612,6 @@ class Filter
|
|
603
612
|
|
604
613
|
end
|
605
614
|
|
606
|
-
|
607
|
-
class BaseFormater
|
608
|
-
attr_accessor :warnings, :errors, :current
|
609
|
-
|
610
|
-
def initialize(out, filter = nil)
|
611
|
-
@out = out
|
612
|
-
@filter = filter
|
613
|
-
reset_data
|
614
|
-
end
|
615
|
-
|
616
|
-
def warn_error?(num, marker)
|
617
|
-
klass = ""
|
618
|
-
|
619
|
-
if @filter.error?(num)
|
620
|
-
klass = ' class="error"'
|
621
|
-
@errors<< [@current, marker, num]
|
622
|
-
elsif @filter.warn?(num)
|
623
|
-
klass = ' class="warning"'
|
624
|
-
@warnings<< [@current, marker, num]
|
625
|
-
end
|
626
|
-
|
627
|
-
klass
|
628
|
-
end
|
629
|
-
|
630
|
-
def reset_data
|
631
|
-
@warnings = Array.new
|
632
|
-
@errors = Array.new
|
633
|
-
@current = ""
|
634
|
-
end
|
635
|
-
|
636
|
-
end
|
637
|
-
|
638
|
-
class TokenCounterFormater < BaseFormater
|
639
|
-
|
640
|
-
def start(new_out=nil)
|
641
|
-
reset_data
|
642
|
-
@out = new_out if new_out
|
643
|
-
@out.puts "Token Count"
|
644
|
-
end
|
645
|
-
|
646
|
-
def start_count(number_of_files)
|
647
|
-
@out.puts "Counting tokens for #{number_of_files} files."
|
648
|
-
end
|
649
|
-
|
650
|
-
def start_file(file_name)
|
651
|
-
@current = file_name
|
652
|
-
@out.puts "File:#{file_name}"
|
653
|
-
end
|
654
|
-
|
655
|
-
def line_token_count(line_number,number_of_tokens)
|
656
|
-
return if @filter.ignore?(number_of_tokens)
|
657
|
-
warn_error?(number_of_tokens, line_number)
|
658
|
-
@out.puts "Line:#{line_number} ; Tokens : #{number_of_tokens}"
|
659
|
-
end
|
660
|
-
|
661
|
-
def end_file
|
662
|
-
@out.puts ""
|
663
|
-
end
|
664
|
-
|
665
|
-
def end_count
|
666
|
-
end
|
667
|
-
|
668
|
-
def end
|
669
|
-
end
|
670
|
-
|
671
|
-
end
|
672
|
-
|
673
|
-
module HTMLStyleSheet
|
674
|
-
def HTMLStyleSheet.style_sheet
|
675
|
-
out = StringIO.new
|
676
|
-
|
677
|
-
out.puts "<style>"
|
678
|
-
out.puts 'body {'
|
679
|
-
out.puts ' margin: 20px;'
|
680
|
-
out.puts ' padding: 0;'
|
681
|
-
out.puts ' font-size: 12px;'
|
682
|
-
out.puts ' font-family: bitstream vera sans, verdana, arial, sans serif;'
|
683
|
-
out.puts ' background-color: #efefef;'
|
684
|
-
out.puts '}'
|
685
|
-
out.puts ''
|
686
|
-
out.puts 'table { '
|
687
|
-
out.puts ' border-collapse: collapse;'
|
688
|
-
out.puts ' /*border-spacing: 0;*/'
|
689
|
-
out.puts ' border: 1px solid #666;'
|
690
|
-
out.puts ' background-color: #fff;'
|
691
|
-
out.puts ' margin-bottom: 20px;'
|
692
|
-
out.puts '}'
|
693
|
-
out.puts ''
|
694
|
-
out.puts 'table, th, th+th, td, td+td {'
|
695
|
-
out.puts ' border: 1px solid #ccc;'
|
696
|
-
out.puts '}'
|
697
|
-
out.puts ''
|
698
|
-
out.puts 'table th {'
|
699
|
-
out.puts ' font-size: 12px;'
|
700
|
-
out.puts ' color: #fc0;'
|
701
|
-
out.puts ' padding: 4px 0;'
|
702
|
-
out.puts ' background-color: #336;'
|
703
|
-
out.puts '}'
|
704
|
-
out.puts ''
|
705
|
-
out.puts 'th, td {'
|
706
|
-
out.puts ' padding: 4px 10px;'
|
707
|
-
out.puts '}'
|
708
|
-
out.puts ''
|
709
|
-
out.puts 'td { '
|
710
|
-
out.puts ' font-size: 13px;'
|
711
|
-
out.puts '}'
|
712
|
-
out.puts ''
|
713
|
-
out.puts '.class_name {'
|
714
|
-
out.puts ' font-size: 17px;'
|
715
|
-
out.puts ' margin: 20px 0 0;'
|
716
|
-
out.puts '}'
|
717
|
-
out.puts ''
|
718
|
-
out.puts '.class_complexity {'
|
719
|
-
out.puts 'margin: 0 auto;'
|
720
|
-
out.puts '}'
|
721
|
-
out.puts ''
|
722
|
-
out.puts '.class_complexity>.class_complexity {'
|
723
|
-
out.puts ' margin: 0;'
|
724
|
-
out.puts '}'
|
725
|
-
out.puts ''
|
726
|
-
out.puts '.class_total_complexity, .class_total_lines, .start_token_count, .file_count {'
|
727
|
-
out.puts ' font-size: 13px;'
|
728
|
-
out.puts ' font-weight: bold;'
|
729
|
-
out.puts '}'
|
730
|
-
out.puts ''
|
731
|
-
out.puts '.class_total_complexity, .class_total_lines {'
|
732
|
-
out.puts ' color: #c00;'
|
733
|
-
out.puts '}'
|
734
|
-
out.puts ''
|
735
|
-
out.puts '.start_token_count, .file_count {'
|
736
|
-
out.puts ' color: #333;'
|
737
|
-
out.puts '}'
|
738
|
-
out.puts ''
|
739
|
-
out.puts '.warning {'
|
740
|
-
out.puts ' background-color: yellow;'
|
741
|
-
out.puts '}'
|
742
|
-
out.puts ''
|
743
|
-
out.puts '.error {'
|
744
|
-
out.puts ' background-color: #f00;'
|
745
|
-
out.puts '}'
|
746
|
-
out.puts "</style>"
|
747
|
-
|
748
|
-
out.string
|
749
|
-
end
|
750
|
-
|
751
|
-
def style_sheet
|
752
|
-
HTMLStyleSheet.style_sheet
|
753
|
-
end
|
754
|
-
end
|
755
|
-
|
756
|
-
|
757
|
-
class HTMLTokenCounterFormater < TokenCounterFormater
|
758
|
-
include HTMLStyleSheet
|
759
|
-
|
760
|
-
def start(new_out=nil)
|
761
|
-
reset_data
|
762
|
-
@out = new_out if new_out
|
763
|
-
@out.puts "<html>"
|
764
|
-
@out.puts style_sheet
|
765
|
-
@out.puts "<body>"
|
766
|
-
end
|
767
|
-
|
768
|
-
def start_count(number_of_files)
|
769
|
-
@out.puts "<div class=\"start_token_count\">"
|
770
|
-
@out.puts "Number of files: #{number_of_files}"
|
771
|
-
@out.puts "</div>"
|
772
|
-
end
|
773
|
-
|
774
|
-
def start_file(file_name)
|
775
|
-
@current = file_name
|
776
|
-
@out.puts "<div class=\"file_count\">"
|
777
|
-
@out.puts "<p class=\"file_name\">"
|
778
|
-
@out.puts "File: #{file_name}"
|
779
|
-
@out.puts "</p>"
|
780
|
-
@out.puts "<table width=\"100%\" border=\"1\">"
|
781
|
-
@out.puts "<tr><th>Line</th><th>Tokens</th></tr>"
|
782
|
-
end
|
783
|
-
|
784
|
-
def line_token_count(line_number,number_of_tokens)
|
785
|
-
return if @filter.ignore?(number_of_tokens)
|
786
|
-
klass = warn_error?(number_of_tokens, line_number)
|
787
|
-
@out.puts "<tr><td>#{line_number}</td><td#{klass}>#{number_of_tokens}</td></tr>"
|
788
|
-
end
|
789
|
-
|
790
|
-
def end_file
|
791
|
-
@out.puts "</table>"
|
792
|
-
end
|
793
|
-
|
794
|
-
def end_count
|
795
|
-
end
|
796
|
-
|
797
|
-
def end
|
798
|
-
@out.puts "</body>"
|
799
|
-
@out.puts "</html>"
|
800
|
-
end
|
801
|
-
end
|
802
|
-
|
803
|
-
class ParseStateFormater < BaseFormater
|
804
|
-
|
805
|
-
def start(new_out=nil)
|
806
|
-
reset_data
|
807
|
-
@out = new_out if new_out
|
808
|
-
end
|
809
|
-
|
810
|
-
def end
|
811
|
-
end
|
812
|
-
|
813
|
-
def start_class_compute_state(type_name,name,complexity,lines)
|
814
|
-
@current = name
|
815
|
-
@out.puts "-- START #{name} --"
|
816
|
-
@out.puts "Type:#{type_name} Name:#{name} Complexity:#{complexity} Lines:#{lines}"
|
817
|
-
end
|
818
|
-
|
819
|
-
def end_class_compute_state(name)
|
820
|
-
@out.puts "-- END #{name} --"
|
821
|
-
end
|
822
|
-
|
823
|
-
def def_compute_state(name,complexity,lines)
|
824
|
-
return if @filter.ignore?(complexity)
|
825
|
-
warn_error?(complexity, name)
|
826
|
-
@out.puts "Type:Def Name:#{name} Complexity:#{complexity} Lines:#{lines}"
|
827
|
-
end
|
828
|
-
|
829
|
-
end
|
830
|
-
|
831
|
-
class StateHTMLComplexityFormater < ParseStateFormater
|
832
|
-
include HTMLStyleSheet
|
833
|
-
|
834
|
-
def start(new_out=nil)
|
835
|
-
reset_data
|
836
|
-
@out = new_out if new_out
|
837
|
-
@out.puts "<html><head><title>Cyclometric Complexity</title></head>"
|
838
|
-
@out.puts style_sheet
|
839
|
-
@out.puts "<body>"
|
840
|
-
end
|
841
|
-
|
842
|
-
def end
|
843
|
-
@out.puts "</body>"
|
844
|
-
@out.puts "</html>"
|
845
|
-
end
|
846
|
-
|
847
|
-
def start_class_compute_state(type_name,name,complexity,lines)
|
848
|
-
@current = name
|
849
|
-
@out.puts "<div class=\"class_complexity\">"
|
850
|
-
@out.puts "<h2 class=\"class_name\">#{type_name} : #{name}</h2>"
|
851
|
-
@out.puts "<div class=\"class_total_complexity\">Total Complexity: #{complexity}</div>"
|
852
|
-
@out.puts "<div class=\"class_total_lines\">Total Lines: #{lines}</div>"
|
853
|
-
@out.puts "<table width=\"100%\" border=\"1\">"
|
854
|
-
@out.puts "<tr><th>Method</th><th>Complexity</th><th># Lines</th></tr>"
|
855
|
-
end
|
856
|
-
|
857
|
-
def end_class_compute_state(name)
|
858
|
-
@out.puts "</table>"
|
859
|
-
@out.puts "</div>"
|
860
|
-
end
|
861
|
-
|
862
|
-
def def_compute_state(name, complexity, lines)
|
863
|
-
return if @filter.ignore?(complexity)
|
864
|
-
klass = warn_error?(complexity, name)
|
865
|
-
@out.puts "<tr><td>#{name}</td><td#{klass}>#{complexity}</td><td>#{lines}</td></tr>"
|
866
|
-
end
|
867
|
-
|
868
|
-
end
|
869
|
-
|
870
615
|
module Saikuro
|
871
616
|
def Saikuro.analyze(files, state_formater, token_count_formater, output_dir)
|
872
617
|
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Saikuro
|
2
|
+
class BaseFormater
|
3
|
+
attr_accessor :warnings, :errors, :current
|
4
|
+
|
5
|
+
def initialize(out, filter = nil)
|
6
|
+
@out = out
|
7
|
+
@filter = filter
|
8
|
+
reset_data
|
9
|
+
end
|
10
|
+
|
11
|
+
def warn_error?(num, marker)
|
12
|
+
klass = ""
|
13
|
+
|
14
|
+
if @filter.error?(num)
|
15
|
+
klass = ' class="error"'
|
16
|
+
@errors<< [@current, marker, num]
|
17
|
+
elsif @filter.warn?(num)
|
18
|
+
klass = ' class="warning"'
|
19
|
+
@warnings<< [@current, marker, num]
|
20
|
+
end
|
21
|
+
|
22
|
+
klass
|
23
|
+
end
|
24
|
+
|
25
|
+
def reset_data
|
26
|
+
@warnings = Array.new
|
27
|
+
@errors = Array.new
|
28
|
+
@current = ""
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
data/lib/saikuro/cli.rb
CHANGED
@@ -9,7 +9,6 @@ module Saikuro
|
|
9
9
|
|
10
10
|
include ResultIndexGenerator
|
11
11
|
|
12
|
-
|
13
12
|
def run
|
14
13
|
|
15
14
|
files = Array.new
|
@@ -86,10 +85,7 @@ module Saikuro
|
|
86
85
|
state_formater = nil if !comp_state
|
87
86
|
token_count_formater = nil if !comp_token
|
88
87
|
|
89
|
-
idx_states, idx_tokens = Saikuro.analyze(files,
|
90
|
-
state_formater,
|
91
|
-
token_count_formater,
|
92
|
-
output_dir)
|
88
|
+
idx_states, idx_tokens = Saikuro.analyze(files, state_formater, token_count_formater, output_dir)
|
93
89
|
|
94
90
|
write_cyclo_index(idx_states, output_dir)
|
95
91
|
write_token_index(idx_tokens, output_dir)
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module Saikuro
|
2
|
+
module HTMLStyleSheet
|
3
|
+
def HTMLStyleSheet.style_sheet
|
4
|
+
out = StringIO.new
|
5
|
+
|
6
|
+
out.puts "<style>"
|
7
|
+
out.puts 'body {'
|
8
|
+
out.puts ' margin: 20px;'
|
9
|
+
out.puts ' padding: 0;'
|
10
|
+
out.puts ' font-size: 12px;'
|
11
|
+
out.puts ' font-family: bitstream vera sans, verdana, arial, sans serif;'
|
12
|
+
out.puts ' background-color: #efefef;'
|
13
|
+
out.puts '}'
|
14
|
+
out.puts ''
|
15
|
+
out.puts 'table { '
|
16
|
+
out.puts ' border-collapse: collapse;'
|
17
|
+
out.puts ' /*border-spacing: 0;*/'
|
18
|
+
out.puts ' border: 1px solid #666;'
|
19
|
+
out.puts ' background-color: #fff;'
|
20
|
+
out.puts ' margin-bottom: 20px;'
|
21
|
+
out.puts '}'
|
22
|
+
out.puts ''
|
23
|
+
out.puts 'table, th, th+th, td, td+td {'
|
24
|
+
out.puts ' border: 1px solid #ccc;'
|
25
|
+
out.puts '}'
|
26
|
+
out.puts ''
|
27
|
+
out.puts 'table th {'
|
28
|
+
out.puts ' font-size: 12px;'
|
29
|
+
out.puts ' color: #fc0;'
|
30
|
+
out.puts ' padding: 4px 0;'
|
31
|
+
out.puts ' background-color: #336;'
|
32
|
+
out.puts '}'
|
33
|
+
out.puts ''
|
34
|
+
out.puts 'th, td {'
|
35
|
+
out.puts ' padding: 4px 10px;'
|
36
|
+
out.puts '}'
|
37
|
+
out.puts ''
|
38
|
+
out.puts 'td { '
|
39
|
+
out.puts ' font-size: 13px;'
|
40
|
+
out.puts '}'
|
41
|
+
out.puts ''
|
42
|
+
out.puts '.class_name {'
|
43
|
+
out.puts ' font-size: 17px;'
|
44
|
+
out.puts ' margin: 20px 0 0;'
|
45
|
+
out.puts '}'
|
46
|
+
out.puts ''
|
47
|
+
out.puts '.class_complexity {'
|
48
|
+
out.puts 'margin: 0 auto;'
|
49
|
+
out.puts '}'
|
50
|
+
out.puts ''
|
51
|
+
out.puts '.class_complexity>.class_complexity {'
|
52
|
+
out.puts ' margin: 0;'
|
53
|
+
out.puts '}'
|
54
|
+
out.puts ''
|
55
|
+
out.puts '.class_total_complexity, .class_total_lines, .start_token_count, .file_count {'
|
56
|
+
out.puts ' font-size: 13px;'
|
57
|
+
out.puts ' font-weight: bold;'
|
58
|
+
out.puts '}'
|
59
|
+
out.puts ''
|
60
|
+
out.puts '.class_total_complexity, .class_total_lines {'
|
61
|
+
out.puts ' color: #c00;'
|
62
|
+
out.puts '}'
|
63
|
+
out.puts ''
|
64
|
+
out.puts '.start_token_count, .file_count {'
|
65
|
+
out.puts ' color: #333;'
|
66
|
+
out.puts '}'
|
67
|
+
out.puts ''
|
68
|
+
out.puts '.warning {'
|
69
|
+
out.puts ' background-color: yellow;'
|
70
|
+
out.puts '}'
|
71
|
+
out.puts ''
|
72
|
+
out.puts '.error {'
|
73
|
+
out.puts ' background-color: #f00;'
|
74
|
+
out.puts '}'
|
75
|
+
out.puts "</style>"
|
76
|
+
|
77
|
+
out.string
|
78
|
+
end
|
79
|
+
|
80
|
+
def style_sheet
|
81
|
+
HTMLStyleSheet.style_sheet
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Saikuro
|
2
|
+
class HTMLTokenCounterFormater < TokenCounterFormater
|
3
|
+
include HTMLStyleSheet
|
4
|
+
|
5
|
+
def start(new_out=nil)
|
6
|
+
reset_data
|
7
|
+
@out = new_out if new_out
|
8
|
+
@out.puts "<html>"
|
9
|
+
@out.puts style_sheet
|
10
|
+
@out.puts "<body>"
|
11
|
+
end
|
12
|
+
|
13
|
+
def start_count(number_of_files)
|
14
|
+
@out.puts "<div class=\"start_token_count\">"
|
15
|
+
@out.puts "Number of files: #{number_of_files}"
|
16
|
+
@out.puts "</div>"
|
17
|
+
end
|
18
|
+
|
19
|
+
def start_file(file_name)
|
20
|
+
@current = file_name
|
21
|
+
@out.puts "<div class=\"file_count\">"
|
22
|
+
@out.puts "<p class=\"file_name\">"
|
23
|
+
@out.puts "File: #{file_name}"
|
24
|
+
@out.puts "</p>"
|
25
|
+
@out.puts "<table width=\"100%\" border=\"1\">"
|
26
|
+
@out.puts "<tr><th>Line</th><th>Tokens</th></tr>"
|
27
|
+
end
|
28
|
+
|
29
|
+
def line_token_count(line_number,number_of_tokens)
|
30
|
+
return if @filter.ignore?(number_of_tokens)
|
31
|
+
klass = warn_error?(number_of_tokens, line_number)
|
32
|
+
@out.puts "<tr><td>#{line_number}</td><td#{klass}>#{number_of_tokens}</td></tr>"
|
33
|
+
end
|
34
|
+
|
35
|
+
def end_file
|
36
|
+
@out.puts "</table>"
|
37
|
+
end
|
38
|
+
|
39
|
+
def end_count
|
40
|
+
end
|
41
|
+
|
42
|
+
def end
|
43
|
+
@out.puts "</body>"
|
44
|
+
@out.puts "</html>"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Saikuro
|
2
|
+
class ParseStateFormater < BaseFormater
|
3
|
+
|
4
|
+
def start(new_out=nil)
|
5
|
+
reset_data
|
6
|
+
@out = new_out if new_out
|
7
|
+
end
|
8
|
+
|
9
|
+
def end
|
10
|
+
end
|
11
|
+
|
12
|
+
def start_class_compute_state(type_name,name,complexity,lines)
|
13
|
+
@current = name
|
14
|
+
@out.puts "-- START #{name} --"
|
15
|
+
@out.puts "Type:#{type_name} Name:#{name} Complexity:#{complexity} Lines:#{lines}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def end_class_compute_state(name)
|
19
|
+
@out.puts "-- END #{name} --"
|
20
|
+
end
|
21
|
+
|
22
|
+
def def_compute_state(name,complexity,lines)
|
23
|
+
return if @filter.ignore?(complexity)
|
24
|
+
warn_error?(complexity, name)
|
25
|
+
@out.puts "Type:Def Name:#{name} Complexity:#{complexity} Lines:#{lines}"
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
@@ -1,88 +1,89 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
module Saikuro
|
2
|
+
module ResultIndexGenerator
|
3
|
+
def summarize_errors_and_warnings(enw, header)
|
4
|
+
return "" if enw.empty?
|
5
|
+
f = StringIO.new
|
6
|
+
erval = Hash.new { |h,k| h[k] = Array.new }
|
7
|
+
wval = Hash.new { |h,k| h[k] = Array.new }
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
enw.each do |fname, warnings, errors|
|
10
|
+
errors.each do |c,m,v|
|
11
|
+
erval[v] << [fname, c, m]
|
12
|
+
end
|
13
|
+
warnings.each do |c,m,v|
|
14
|
+
wval[v] << [fname, c, m]
|
15
|
+
end
|
11
16
|
end
|
12
|
-
warnings.each do |c,m,v|
|
13
|
-
wval[v] << [fname, c, m]
|
14
|
-
end
|
15
|
-
end
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
f.puts "<h2 class=\"class_name\">Errors and Warnings</h2>"
|
19
|
+
f.puts "<table width=\"100%\" border=\"1\">"
|
20
|
+
f.puts header
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
f.puts print_summary_table_rows(erval, "error")
|
23
|
+
f.puts print_summary_table_rows(wval, "warning")
|
24
|
+
f.puts "</table>"
|
24
25
|
|
25
|
-
|
26
|
-
|
26
|
+
f.string
|
27
|
+
end
|
27
28
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
29
|
+
def print_summary_table_rows(ewvals, klass_type)
|
30
|
+
f = StringIO.new
|
31
|
+
ewvals.sort { |a,b| b <=> a}.each do |v, vals|
|
32
|
+
vals.sort.each do |fname, c, m|
|
33
|
+
f.puts "<tr><td><a href=\"./#{fname}\">#{c}</a></td><td>#{m}</td>"
|
34
|
+
f.puts "<td class=\"#{klass_type}\">#{v}</td></tr>"
|
35
|
+
end
|
34
36
|
end
|
37
|
+
f.string
|
35
38
|
end
|
36
|
-
f.string
|
37
|
-
end
|
38
39
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
40
|
+
def list_analyzed_files(files)
|
41
|
+
f = StringIO.new
|
42
|
+
f.puts "<h2 class=\"class_name\">Analyzed Files</h2>"
|
43
|
+
f.puts "<ul>"
|
44
|
+
files.each do |fname, warnings, errors|
|
45
|
+
readname = fname.split("_")[0...-1].join("_")
|
46
|
+
f.puts "<li>"
|
47
|
+
f.puts "<p class=\"file_name\"><a href=\"./#{fname}\">#{readname}</a>"
|
48
|
+
f.puts "</li>"
|
49
|
+
end
|
50
|
+
f.puts "</ul>"
|
51
|
+
f.string
|
48
52
|
end
|
49
|
-
f.puts "</ul>"
|
50
|
-
f.string
|
51
|
-
end
|
52
53
|
|
53
|
-
|
54
|
-
|
54
|
+
def write_index(files, filename, title, header)
|
55
|
+
return if files.empty?
|
55
56
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
57
|
+
File.open(filename,"w") do |f|
|
58
|
+
f.puts "<html><head><title>#{title}</title></head>"
|
59
|
+
f.puts "#{HTMLStyleSheet.style_sheet}\n<body>"
|
60
|
+
f.puts "<h1>#{title}</h1>"
|
60
61
|
|
61
|
-
|
62
|
+
enw = files.find_all { |fn,w,e| (!w.empty? || !e.empty?) }
|
62
63
|
|
63
|
-
|
64
|
+
f.puts summarize_errors_and_warnings(enw, header)
|
64
65
|
|
65
|
-
|
66
|
-
|
67
|
-
|
66
|
+
f.puts "<hr/>"
|
67
|
+
f.puts list_analyzed_files(files)
|
68
|
+
f.puts "</body></html>"
|
69
|
+
end
|
68
70
|
end
|
69
|
-
end
|
70
71
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
72
|
+
def write_cyclo_index(files, output_dir)
|
73
|
+
header = "<tr><th>Class</th><th>Method</th><th>Complexity</th></tr>"
|
74
|
+
write_index(files,
|
75
|
+
"#{output_dir}/index_cyclo.html",
|
76
|
+
"Index for cyclomatic complexity",
|
77
|
+
header)
|
78
|
+
end
|
78
79
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
80
|
+
def write_token_index(files, output_dir)
|
81
|
+
header = "<tr><th>File</th><th>Line #</th><th>Tokens</th></tr>"
|
82
|
+
write_index(files,
|
83
|
+
"#{output_dir}/index_token.html",
|
84
|
+
"Index for tokens per line",
|
85
|
+
header)
|
86
|
+
end
|
86
87
|
|
88
|
+
end
|
87
89
|
end
|
88
|
-
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Saikuro
|
2
|
+
class StateHTMLComplexityFormater < ParseStateFormater
|
3
|
+
include HTMLStyleSheet
|
4
|
+
|
5
|
+
def start(new_out=nil)
|
6
|
+
reset_data
|
7
|
+
@out = new_out if new_out
|
8
|
+
@out.puts "<html><head><title>Cyclometric Complexity</title></head>"
|
9
|
+
@out.puts style_sheet
|
10
|
+
@out.puts "<body>"
|
11
|
+
end
|
12
|
+
|
13
|
+
def end
|
14
|
+
@out.puts "</body>"
|
15
|
+
@out.puts "</html>"
|
16
|
+
end
|
17
|
+
|
18
|
+
def start_class_compute_state(type_name,name,complexity,lines)
|
19
|
+
@current = name
|
20
|
+
@out.puts "<div class=\"class_complexity\">"
|
21
|
+
@out.puts "<h2 class=\"class_name\">#{type_name} : #{name}</h2>"
|
22
|
+
@out.puts "<div class=\"class_total_complexity\">Total Complexity: #{complexity}</div>"
|
23
|
+
@out.puts "<div class=\"class_total_lines\">Total Lines: #{lines}</div>"
|
24
|
+
@out.puts "<table width=\"100%\" border=\"1\">"
|
25
|
+
@out.puts "<tr><th>Method</th><th>Complexity</th><th># Lines</th></tr>"
|
26
|
+
end
|
27
|
+
|
28
|
+
def end_class_compute_state(name)
|
29
|
+
@out.puts "</table>"
|
30
|
+
@out.puts "</div>"
|
31
|
+
end
|
32
|
+
|
33
|
+
def def_compute_state(name, complexity, lines)
|
34
|
+
return if @filter.ignore?(complexity)
|
35
|
+
klass = warn_error?(complexity, name)
|
36
|
+
@out.puts "<tr><td>#{name}</td><td#{klass}>#{complexity}</td><td>#{lines}</td></tr>"
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Saikuro
|
2
|
+
class TokenCounterFormater < BaseFormater
|
3
|
+
|
4
|
+
def start(new_out=nil)
|
5
|
+
reset_data
|
6
|
+
@out = new_out if new_out
|
7
|
+
@out.puts "Token Count"
|
8
|
+
end
|
9
|
+
|
10
|
+
def start_count(number_of_files)
|
11
|
+
@out.puts "Counting tokens for #{number_of_files} files."
|
12
|
+
end
|
13
|
+
|
14
|
+
def start_file(file_name)
|
15
|
+
@current = file_name
|
16
|
+
@out.puts "File:#{file_name}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def line_token_count(line_number,number_of_tokens)
|
20
|
+
return if @filter.ignore?(number_of_tokens)
|
21
|
+
warn_error?(number_of_tokens, line_number)
|
22
|
+
@out.puts "Line:#{line_number} ; Tokens : #{number_of_tokens}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def end_file
|
26
|
+
@out.puts ""
|
27
|
+
end
|
28
|
+
|
29
|
+
def end_count
|
30
|
+
end
|
31
|
+
|
32
|
+
def end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
data/lib/saikuro/version.rb
CHANGED
data/saikuro.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.email = ["zb@ubit.com", "romanvbabenko@gmail.com"]
|
10
10
|
s.homepage = ""
|
11
11
|
s.summary = %q{Saikuro is a Ruby cyclomatic complexity analyzer}
|
12
|
-
s.description
|
12
|
+
s.description = %q{When given Ruby source code Saikuro will generate a report listing the cyclomatic complexity of each method found. In addition, Saikuro counts the number of lines per method and can generate a listing of the number of tokens on each line of code.}
|
13
13
|
|
14
14
|
s.rubyforge_project = "saikuro"
|
15
15
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: saikuro
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 29
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 1.2.
|
9
|
+
- 1
|
10
|
+
version: 1.2.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Zev Blut
|
@@ -37,8 +37,14 @@ files:
|
|
37
37
|
- examples/large_example.rb
|
38
38
|
- examples/samples.rb
|
39
39
|
- lib/saikuro.rb
|
40
|
+
- lib/saikuro/base_formater.rb
|
40
41
|
- lib/saikuro/cli.rb
|
42
|
+
- lib/saikuro/html_style_sheet.rb
|
43
|
+
- lib/saikuro/html_token_counter_formater.rb
|
44
|
+
- lib/saikuro/parse_state_formater.rb
|
41
45
|
- lib/saikuro/result_index_generator.rb
|
46
|
+
- lib/saikuro/state_html_complexity_formater.rb
|
47
|
+
- lib/saikuro/token_counter_formater.rb
|
42
48
|
- lib/saikuro/version.rb
|
43
49
|
- saikuro.gemspec
|
44
50
|
homepage: ""
|