Class: CyclomaticComplexityAction

Inherits:
BuildAction show all
Defined in:
lib/kwala/actions/cyclomatic_complexity.rb

Overview

Copyright © 2006, Ubiquitous Business Technology (ubit.com) All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright
  notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above
  copyright notice, this list of conditions and the following
  disclaimer in the documentation and/or other materials provided
  with the distribution.

* Neither the name of Ubit nor the names of its
  contributors may be used to endorse or promote products derived
  from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Author

Zev Blut ([email protected])

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from BuildAction

command_line_action_name, command_line_action_names, create_action_from_command_line_name, #detailed_display, summary_template_file

Methods included from InheritanceTracker

#get_implementors

Constructor Details

#initializeCyclomaticComplexityAction

Returns a new instance of CyclomaticComplexityAction.



45
46
47
48
49
# File 'lib/kwala/actions/cyclomatic_complexity.rb', line 45

def initialize
  @limit = 11 # 1 more for header
  @cyclo_count = nil
  @bound = 0 # This should be methods instead of files.
end

Class Method Details

.detailed_template_fileObject



82
83
84
# File 'lib/kwala/actions/cyclomatic_complexity.rb', line 82

def self.detailed_template_file
  nil
end

Instance Method Details

#build_action(context) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/kwala/actions/cyclomatic_complexity.rb', line 51

def build_action(context)
  args = [ "-o #{context.output_directory}" ]
  args << [ "-c -t"]
  args << [ "-y 0 -w 11 -e 15"]
  args << [ "-k 0 -s 30 -d 35"]
  args << [ "-i #{context.project_directory}" ]

  stdout_data = stderr_data = Array.new
  system("/usr/bin/env saikuro #{args.join(" ")}")
  @cyclo_count = get_cyclo_violations(context)
  @bound = context.ruby_files.size + context.test_files.size
end

#count_violations(file) ⇒ Object

XXX: This is basically the same as get_summary_from_file, there should be a nice way to reuse the logic in a more clean way.



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/kwala/actions/cyclomatic_complexity.rb', line 128

def count_violations(file)
  if !File.exists?(file)
    return 0
  end

  data = IO.readlines(file).join
  errors = 0
  warnings = 0

  if m = /(<table.*?>)(.*)(<\/table>)/mi.match(data)
    data = m[2]
    while m = /(<tr>.*?<\/tr>)(.*)/mi.match(data)
      if /^<tr><th>/ !~ m[1]
        # Make sure not to count the header row.
        if /class=\"error\"/ =~ m[1]
          errors += 1
        elsif /class=\"warning\"/ =~ m[1]
          warnings += 1
        end
      end
      data = m[2]
    end
  end

  {
    :total => errors + warnings,
    :errors => errors,
    :warnings => warnings
  }
end

#get_cyclo_summary(context) ⇒ Object



86
87
88
# File 'lib/kwala/actions/cyclomatic_complexity.rb', line 86

def get_cyclo_summary(context)
  get_summary_from_file(context.output_directory + "/index_cyclo.html")
end

#get_cyclo_violations(context) ⇒ Object



94
95
96
# File 'lib/kwala/actions/cyclomatic_complexity.rb', line 94

def get_cyclo_violations(context)
  count_violations(context.output_directory + "/index_cyclo.html")
end

#get_summary_from_file(file) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/kwala/actions/cyclomatic_complexity.rb', line 102

def get_summary_from_file(file)
  if !File.exists?(file)
    STDERR.puts "Saikuro : Cannot find #{file}"
    return ""
  end
  data = IO.readlines(file).join
  res = ""
  if m = /(<table.*?>)(.*)(<\/table>)/mi.match(data)
    head = m[1]
    data = m[2]
    tail = m[3]
    rows = Array.new
    while rows.size < @limit && m = /(<tr>.*?<\/tr>)(.*)/mi.match(data)
      rows << m[1]
      data = m[2]
    end

    res = head.to_s + rows.join("\n") + tail.to_s
  end

  SanitizedString.new(res)
end

#get_token_summary(context) ⇒ Object



90
91
92
# File 'lib/kwala/actions/cyclomatic_complexity.rb', line 90

def get_token_summary(context)
  get_summary_from_file(context.output_directory + "/index_token.html")
end

#get_token_violations(context) ⇒ Object



98
99
100
# File 'lib/kwala/actions/cyclomatic_complexity.rb', line 98

def get_token_violations(context)
  count_violations(context.output_directory + "/index_token.html")
end

#scoreObject



77
78
79
80
# File 'lib/kwala/actions/cyclomatic_complexity.rb', line 77

def score
  # high complexity is probably one of the things that should weigh higher.
  score_scaling(( @cyclo_count[:errors] * 3 + @cyclo_count[:warnings]), @bound)
end

#summary_display(context) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/kwala/actions/cyclomatic_complexity.rb', line 64

def summary_display(context)
  template = TemplateFile.new(self.class.summary_template_file)
  context.amrita_data[:saikuro_metrics_summary] = {
    :cyclo_summary => get_cyclo_summary(context),
    :token_summary => get_token_summary(context),
    :cyclo_violations => get_cyclo_violations(context),
    :token_violations => get_token_violations(context),
    :cyclo_link => Amrita::e(:a, :href => "index_cyclo.html") { "Cyclomatic Complexity Details" },
    :token_link => Amrita::e(:a, :href => "index_token.html") { "Token Count Details" }
  }
  summary_expand(template, context)
end