reconn 0.1.0 → 1.0.0
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.
- checksums.yaml +4 -4
 - data/bin/reconn +1 -1
 - data/lib/reconn/analyzer.rb +35 -10
 - data/lib/reconn/analyzer/code_smell.rb +11 -11
 - data/lib/reconn/analyzer/project_elements/class.rb +7 -3
 - data/lib/reconn/analyzer/project_elements/method.rb +11 -3
 - data/lib/reconn/util/project_scanner.rb +22 -20
 - data/lib/reconn/version.rb +1 -1
 - data/lib/reconn/view/view.rb +7 -5
 - data/lib/reconn/visualizer.rb +149 -28
 - metadata +2 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 98a521e90dd569d2e385655e695c2b20b573c72a
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 68dea3d08b90bca2e6790d675970783886bab1d3
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 50359a392132d7e1bfff84fef8afc3fa4bd0dd8c8504a54dd4d7263630c6e38c0b90f0560142325417e18b4eb43511b2e300a4a6bddef5fc3788e085d5c20bc1
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: b2de99d4e108c48ecf5f0acc30f1080fd1639dbcf5cd74eb2a49f36ab70346436688c7d57a4c0d06d335bbed63b467b341ad82d86ae4a6cba3c38c3591690b99
         
     | 
    
        data/bin/reconn
    CHANGED
    
    
    
        data/lib/reconn/analyzer.rb
    CHANGED
    
    | 
         @@ -2,10 +2,8 @@ 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            require 'ruby_parser'
         
     | 
| 
       4 
4 
     | 
    
         
             
            require 'sexp_processor'
         
     | 
| 
       5 
     | 
    
         
            -
            require_relative 'util/project_scanner'
         
     | 
| 
       6 
     | 
    
         
            -
            require_relative 'analyzer/project_elements/class.rb'
         
     | 
| 
       7 
     | 
    
         
            -
            require_relative 'analyzer/project_elements/method.rb'
         
     | 
| 
       8 
5 
     | 
    
         | 
| 
      
 6 
     | 
    
         
            +
            module Reconn
         
     | 
| 
       9 
7 
     | 
    
         
             
            module Analyzer
         
     | 
| 
       10 
8 
     | 
    
         
             
              class Analyzer < MethodBasedSexpProcessor
         
     | 
| 
       11 
9 
     | 
    
         | 
| 
         @@ -43,9 +41,10 @@ module Analyzer 
     | 
|
| 
       43 
41 
     | 
    
         
             
                    klass.complexity = count_complexity_in_class(klass)
         
     | 
| 
       44 
42 
     | 
    
         
             
                  end
         
     | 
| 
       45 
43 
     | 
    
         
             
                  prune_dependencies
         
     | 
| 
      
 44 
     | 
    
         
            +
                  find_external_dependencies(paths)
         
     | 
| 
       46 
45 
     | 
    
         | 
| 
       47 
46 
     | 
    
         
             
                  # Deletes empty classes
         
     | 
| 
       48 
     | 
    
         
            -
                   
     | 
| 
      
 47 
     | 
    
         
            +
                  #@classes.delete(Class.new(:none))
         
     | 
| 
       49 
48 
     | 
    
         | 
| 
       50 
49 
     | 
    
         
             
                  @smells = find_code_smells
         
     | 
| 
       51 
50 
     | 
    
         | 
| 
         @@ -58,7 +57,7 @@ module Analyzer 
     | 
|
| 
       58 
57 
     | 
    
         
             
                def process_class(exp)
         
     | 
| 
       59 
58 
     | 
    
         
             
                  exp.shift
         
     | 
| 
       60 
59 
     | 
    
         
             
                  in_klass(exp.shift) do
         
     | 
| 
       61 
     | 
    
         
            -
                    @current_class = Class.new(klass_name)
         
     | 
| 
      
 60 
     | 
    
         
            +
                    @current_class = Class.new(klass_name, [@current_path.to_s])
         
     | 
| 
       62 
61 
     | 
    
         
             
                    @classes << @current_class
         
     | 
| 
       63 
62 
     | 
    
         
             
                    process_until_empty exp
         
     | 
| 
       64 
63 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -68,10 +67,10 @@ module Analyzer 
     | 
|
| 
       68 
67 
     | 
    
         
             
                end
         
     | 
| 
       69 
68 
     | 
    
         | 
| 
       70 
69 
     | 
    
         
             
                def process_defn(exp)
         
     | 
| 
       71 
     | 
    
         
            -
                  exp.shift
         
     | 
| 
      
 70 
     | 
    
         
            +
                  is_singleton = exp.shift.to_s == "defn" ? false : true
         
     | 
| 
       72 
71 
     | 
    
         
             
                  method_name = exp.shift.to_s
         
     | 
| 
       73 
72 
     | 
    
         
             
                  lines = count_lines_in_method(method_name)
         
     | 
| 
       74 
     | 
    
         
            -
                  @current_method = Method.new(method_name, @current_class.name, lines)
         
     | 
| 
      
 73 
     | 
    
         
            +
                  @current_method = Method.new(method_name, @current_path.to_s, @current_class.name, lines, is_singleton)
         
     | 
| 
       75 
74 
     | 
    
         
             
                  exp.shift
         
     | 
| 
       76 
75 
     | 
    
         
             
                  process_until_empty exp
         
     | 
| 
       77 
76 
     | 
    
         | 
| 
         @@ -163,8 +162,15 @@ module Analyzer 
     | 
|
| 
       163 
162 
     | 
    
         
             
                  @classes.each do |klass|
         
     | 
| 
       164 
163 
     | 
    
         
             
                    klass.dependencies =  klass.dependencies.map do |dep|
         
     | 
| 
       165 
164 
     | 
    
         
             
                      dep_split = dep.split('::')
         
     | 
| 
      
 165 
     | 
    
         
            +
                      if class_names.include?(dep)
         
     | 
| 
      
 166 
     | 
    
         
            +
                        next dep
         
     | 
| 
      
 167 
     | 
    
         
            +
                      end
         
     | 
| 
       166 
168 
     | 
    
         
             
                      klass_split = klass.name.split('::')
         
     | 
| 
       167 
     | 
    
         
            -
                      klass_split. 
     | 
| 
      
 169 
     | 
    
         
            +
                      if klass_split.size != dep_split.size
         
     | 
| 
      
 170 
     | 
    
         
            +
                        klass_split.pop(dep_split.size)
         
     | 
| 
      
 171 
     | 
    
         
            +
                      else
         
     | 
| 
      
 172 
     | 
    
         
            +
                        klass_split.pop(dep_split.size - 1)
         
     | 
| 
      
 173 
     | 
    
         
            +
                      end
         
     | 
| 
       168 
174 
     | 
    
         
             
                      (klass_split + dep_split).join('::')
         
     | 
| 
       169 
175 
     | 
    
         
             
                    end
         
     | 
| 
       170 
176 
     | 
    
         
             
                    klass.dependencies = klass.dependencies.uniq.keep_if {|dep| dep != klass.name && class_names.include?(dep)}
         
     | 
| 
         @@ -184,14 +190,32 @@ module Analyzer 
     | 
|
| 
       184 
190 
     | 
    
         
             
                  end
         
     | 
| 
       185 
191 
     | 
    
         
             
                end
         
     | 
| 
       186 
192 
     | 
    
         | 
| 
      
 193 
     | 
    
         
            +
                def find_external_dependencies(paths)
         
     | 
| 
      
 194 
     | 
    
         
            +
                  @classes.each do |klass|
         
     | 
| 
      
 195 
     | 
    
         
            +
                    external_deps = []
         
     | 
| 
      
 196 
     | 
    
         
            +
                    klass.filepaths.each do |path|
         
     | 
| 
      
 197 
     | 
    
         
            +
                      File.foreach(path) do |line|
         
     | 
| 
      
 198 
     | 
    
         
            +
                        line.strip!
         
     | 
| 
      
 199 
     | 
    
         
            +
                        if line =~ /^require .*$/
         
     | 
| 
      
 200 
     | 
    
         
            +
                          dep = line.split(" ")[1].gsub(/([\"\'])/, "")
         
     | 
| 
      
 201 
     | 
    
         
            +
                          external_deps << dep if !paths.find {|p| p.to_s =~ /.*#{dep}.*/}
         
     | 
| 
      
 202 
     | 
    
         
            +
                        else
         
     | 
| 
      
 203 
     | 
    
         
            +
                          next
         
     | 
| 
      
 204 
     | 
    
         
            +
                        end
         
     | 
| 
      
 205 
     | 
    
         
            +
                      end
         
     | 
| 
      
 206 
     | 
    
         
            +
                    end
         
     | 
| 
      
 207 
     | 
    
         
            +
                    klass.external_deps = external_deps
         
     | 
| 
      
 208 
     | 
    
         
            +
                  end
         
     | 
| 
      
 209 
     | 
    
         
            +
                end
         
     | 
| 
      
 210 
     | 
    
         
            +
             
     | 
| 
       187 
211 
     | 
    
         
             
                def find_code_smells
         
     | 
| 
       188 
212 
     | 
    
         
             
                  code_smells = []
         
     | 
| 
       189 
213 
     | 
    
         
             
                  @methods.each do |method|
         
     | 
| 
       190 
214 
     | 
    
         
             
                    if method.lines > MAX_METHOD_LENGTH
         
     | 
| 
       191 
     | 
    
         
            -
                      code_smells << CodeSmell.new(:too_big_method, method 
     | 
| 
      
 215 
     | 
    
         
            +
                      code_smells << CodeSmell.new(:too_big_method, method)
         
     | 
| 
       192 
216 
     | 
    
         
             
                    end
         
     | 
| 
       193 
217 
     | 
    
         
             
                    if method.complexity > MAX_COMPLEXITY
         
     | 
| 
       194 
     | 
    
         
            -
                      code_smells << CodeSmell.new(:too_complex_method, method 
     | 
| 
      
 218 
     | 
    
         
            +
                      code_smells << CodeSmell.new(:too_complex_method, method)
         
     | 
| 
       195 
219 
     | 
    
         
             
                    end
         
     | 
| 
       196 
220 
     | 
    
         
             
                  end
         
     | 
| 
       197 
221 
     | 
    
         
             
                  code_smells
         
     | 
| 
         @@ -199,3 +223,4 @@ module Analyzer 
     | 
|
| 
       199 
223 
     | 
    
         | 
| 
       200 
224 
     | 
    
         
             
              end
         
     | 
| 
       201 
225 
     | 
    
         
             
            end
         
     | 
| 
      
 226 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,16 +1,16 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            module  
     | 
| 
       2 
     | 
    
         
            -
               
     | 
| 
       3 
     | 
    
         
            -
                 
     | 
| 
      
 1 
     | 
    
         
            +
            module Reconn
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Analyzer
         
     | 
| 
      
 3 
     | 
    
         
            +
                class CodeSmell
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_reader :type, :method
         
     | 
| 
       4 
5 
     | 
    
         | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
                   
     | 
| 
       9 
     | 
    
         
            -
                end
         
     | 
| 
      
 6 
     | 
    
         
            +
                  def initialize(type, method)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    @type = type
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @method = method
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
                   
     | 
| 
      
 11 
     | 
    
         
            +
                  def to_s
         
     | 
| 
      
 12 
     | 
    
         
            +
                    "Smell: #{@type.to_s} in #{@method.to_s} in file: #{method.filepath}"
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
       14 
14 
     | 
    
         
             
                end
         
     | 
| 
       15 
15 
     | 
    
         
             
              end
         
     | 
| 
       16 
16 
     | 
    
         
             
            end
         
     | 
| 
         @@ -1,8 +1,9 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Reconn
         
     | 
| 
       1 
2 
     | 
    
         
             
            module Analyzer
         
     | 
| 
       2 
3 
     | 
    
         
             
              # Represents a class in the project
         
     | 
| 
       3 
4 
     | 
    
         
             
              class Class
         
     | 
| 
       4 
     | 
    
         
            -
                attr_reader :name, :methods
         
     | 
| 
       5 
     | 
    
         
            -
                attr_accessor :lines, :complexity, :dependencies
         
     | 
| 
      
 5 
     | 
    
         
            +
                attr_reader :name, :methods, :filepaths
         
     | 
| 
      
 6 
     | 
    
         
            +
                attr_accessor :lines, :complexity, :dependencies, :external_deps
         
     | 
| 
       6 
7 
     | 
    
         | 
| 
       7 
8 
     | 
    
         
             
                include Comparable
         
     | 
| 
       8 
9 
     | 
    
         | 
| 
         @@ -10,8 +11,9 @@ module Analyzer 
     | 
|
| 
       10 
11 
     | 
    
         
             
                  name == other.name
         
     | 
| 
       11 
12 
     | 
    
         
             
                end
         
     | 
| 
       12 
13 
     | 
    
         | 
| 
       13 
     | 
    
         
            -
                def initialize(name)
         
     | 
| 
      
 14 
     | 
    
         
            +
                def initialize(name, filepaths = [])
         
     | 
| 
       14 
15 
     | 
    
         
             
                  @name = name
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @filepaths = filepaths
         
     | 
| 
       15 
17 
     | 
    
         
             
                  @dependencies = []
         
     | 
| 
       16 
18 
     | 
    
         
             
                  @methods = []
         
     | 
| 
       17 
19 
     | 
    
         
             
                  @lines = 0
         
     | 
| 
         @@ -37,6 +39,7 @@ module Analyzer 
     | 
|
| 
       37 
39 
     | 
    
         
             
                    end
         
     | 
| 
       38 
40 
     | 
    
         
             
                  end
         
     | 
| 
       39 
41 
     | 
    
         
             
                  @dependencies += other.dependencies
         
     | 
| 
      
 42 
     | 
    
         
            +
                  @filepaths += other.filepaths
         
     | 
| 
       40 
43 
     | 
    
         
             
                  self
         
     | 
| 
       41 
44 
     | 
    
         
             
                end
         
     | 
| 
       42 
45 
     | 
    
         | 
| 
         @@ -46,3 +49,4 @@ module Analyzer 
     | 
|
| 
       46 
49 
     | 
    
         | 
| 
       47 
50 
     | 
    
         
             
              end
         
     | 
| 
       48 
51 
     | 
    
         
             
            end
         
     | 
| 
      
 52 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,7 +1,8 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Reconn
         
     | 
| 
       1 
2 
     | 
    
         
             
            module Analyzer
         
     | 
| 
       2 
3 
     | 
    
         
             
              # Represents a method in the project
         
     | 
| 
       3 
4 
     | 
    
         
             
              class Method
         
     | 
| 
       4 
     | 
    
         
            -
                attr_reader :name, :class_name, :lines, :complexity
         
     | 
| 
      
 5 
     | 
    
         
            +
                attr_reader :name, :class_name, :lines, :complexity, :filepath
         
     | 
| 
       5 
6 
     | 
    
         | 
| 
       6 
7 
     | 
    
         
             
                include Comparable
         
     | 
| 
       7 
8 
     | 
    
         | 
| 
         @@ -9,20 +10,27 @@ module Analyzer 
     | 
|
| 
       9 
10 
     | 
    
         
             
                  name == other.name && class_name == other.class_name
         
     | 
| 
       10 
11 
     | 
    
         
             
                end
         
     | 
| 
       11 
12 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
                def initialize(name, class_name = :none, lines = 0)
         
     | 
| 
      
 13 
     | 
    
         
            +
                def initialize(name, filepath = "", class_name = :none, lines = 0, is_singleton = false)
         
     | 
| 
       13 
14 
     | 
    
         
             
                  @name = name
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @filepath = filepath
         
     | 
| 
       14 
16 
     | 
    
         
             
                  @class_name = class_name
         
     | 
| 
       15 
17 
     | 
    
         
             
                  @lines = lines
         
     | 
| 
       16 
18 
     | 
    
         
             
                  @complexity = 1
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @is_singleton = is_singleton
         
     | 
| 
       17 
20 
     | 
    
         
             
                end
         
     | 
| 
       18 
21 
     | 
    
         | 
| 
       19 
22 
     | 
    
         
             
                def to_s
         
     | 
| 
       20 
     | 
    
         
            -
                  name.to_s
         
     | 
| 
      
 23 
     | 
    
         
            +
                  class_name.to_s + (is_singleton? ? "::" : "#")  + name.to_s
         
     | 
| 
       21 
24 
     | 
    
         
             
                end
         
     | 
| 
       22 
25 
     | 
    
         | 
| 
       23 
26 
     | 
    
         
             
                def incr_complexity
         
     | 
| 
       24 
27 
     | 
    
         
             
                  @complexity += 1
         
     | 
| 
       25 
28 
     | 
    
         
             
                end
         
     | 
| 
       26 
29 
     | 
    
         | 
| 
      
 30 
     | 
    
         
            +
                def is_singleton?
         
     | 
| 
      
 31 
     | 
    
         
            +
                  @is_singleton
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
       27 
34 
     | 
    
         
             
              end
         
     | 
| 
       28 
35 
     | 
    
         
             
            end
         
     | 
| 
      
 36 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,28 +1,30 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'find'
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
               
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
                 
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
                   
     | 
| 
       13 
     | 
    
         
            -
                     
     | 
| 
       14 
     | 
    
         
            -
                      if  
     | 
| 
       15 
     | 
    
         
            -
                         
     | 
| 
      
 3 
     | 
    
         
            +
            module Reconn
         
     | 
| 
      
 4 
     | 
    
         
            +
              class ProjectScanner
         
     | 
| 
      
 5 
     | 
    
         
            +
                # Scans the given directory and all its subdirectories for ruby files
         
     | 
| 
      
 6 
     | 
    
         
            +
                #
         
     | 
| 
      
 7 
     | 
    
         
            +
                # @param proj_path [String] path to the project directory
         
     | 
| 
      
 8 
     | 
    
         
            +
                # @return [Array<String>] paths to the ruby files
         
     | 
| 
      
 9 
     | 
    
         
            +
                # @raise [InvalidPathException] if it can't open the directory
         
     | 
| 
      
 10 
     | 
    
         
            +
                def self.scan(proj_path)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  paths = []
         
     | 
| 
      
 12 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 13 
     | 
    
         
            +
                    Find.find(proj_path) do |path|
         
     | 
| 
      
 14 
     | 
    
         
            +
                      if FileTest.directory?(path)
         
     | 
| 
      
 15 
     | 
    
         
            +
                        if File.basename(path)[0] == '.'
         
     | 
| 
      
 16 
     | 
    
         
            +
                          Find.prune
         
     | 
| 
      
 17 
     | 
    
         
            +
                        end
         
     | 
| 
      
 18 
     | 
    
         
            +
                      end
         
     | 
| 
      
 19 
     | 
    
         
            +
                      if File.extname(path) == '.rb'
         
     | 
| 
      
 20 
     | 
    
         
            +
                        paths << path
         
     | 
| 
       16 
21 
     | 
    
         
             
                      end
         
     | 
| 
       17 
22 
     | 
    
         
             
                    end
         
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
                    end
         
     | 
| 
      
 23 
     | 
    
         
            +
                  rescue
         
     | 
| 
      
 24 
     | 
    
         
            +
                    raise InvalidPathException, "Can't open the directory"
         
     | 
| 
       21 
25 
     | 
    
         
             
                  end
         
     | 
| 
       22 
     | 
    
         
            -
                rescue
         
     | 
| 
       23 
     | 
    
         
            -
                  raise InvalidPathException, "Can't open the directory"
         
     | 
| 
       24 
     | 
    
         
            -
                end
         
     | 
| 
       25 
26 
     | 
    
         | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
      
 27 
     | 
    
         
            +
                  paths
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
       27 
29 
     | 
    
         
             
              end
         
     | 
| 
       28 
30 
     | 
    
         
             
            end
         
     | 
    
        data/lib/reconn/version.rb
    CHANGED
    
    
    
        data/lib/reconn/view/view.rb
    CHANGED
    
    | 
         @@ -1,6 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require_relative '../analyzer.rb'
         
     | 
| 
       2 
2 
     | 
    
         
             
            require_relative '../visualizer.rb'
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
      
 4 
     | 
    
         
            +
            module Reconn
         
     | 
| 
       4 
5 
     | 
    
         
             
            class View
         
     | 
| 
       5 
6 
     | 
    
         | 
| 
       6 
7 
     | 
    
         
             
            	include GladeGUI
         
     | 
| 
         @@ -195,8 +196,8 @@ class View 
     | 
|
| 
       195 
196 
     | 
    
         
             
              end
         
     | 
| 
       196 
197 
     | 
    
         | 
| 
       197 
198 
     | 
    
         
             
              def build_method_diag_view
         
     | 
| 
       198 
     | 
    
         
            -
                diagrams = [ {title: "Lines of code", parameter: :lines} ]
         
     | 
| 
       199 
     | 
    
         
            -
                diagrams << {title: "Cyclomatic complexity", parameter: :complexity}
         
     | 
| 
      
 199 
     | 
    
         
            +
                diagrams = [ {title: "Lines of code", parameter: :lines, treshold: Analyzer::Analyzer::MAX_METHOD_LENGTH} ]
         
     | 
| 
      
 200 
     | 
    
         
            +
                diagrams << {title: "Cyclomatic complexity", parameter: :complexity, treshold: Analyzer::Analyzer::MAX_COMPLEXITY}
         
     | 
| 
       200 
201 
     | 
    
         
             
                build_diag_view(@methods, diagrams)
         
     | 
| 
       201 
202 
     | 
    
         
             
              end
         
     | 
| 
       202 
203 
     | 
    
         | 
| 
         @@ -209,7 +210,7 @@ class View 
     | 
|
| 
       209 
210 
     | 
    
         
             
                  title = diag[:title]
         
     | 
| 
       210 
211 
     | 
    
         | 
| 
       211 
212 
     | 
    
         
             
                  pie_chart = build_pie_chart(title, data)
         
     | 
| 
       212 
     | 
    
         
            -
                  bar_chart = build_bar_chart(title, data.first(10))
         
     | 
| 
      
 213 
     | 
    
         
            +
                  bar_chart = build_bar_chart(title, data.first(10), diag[:treshold])
         
     | 
| 
       213 
214 
     | 
    
         | 
| 
       214 
215 
     | 
    
         
             
                  container = Gtk::VBox.new(false, 4)
         
     | 
| 
       215 
216 
     | 
    
         
             
                  container = container.pack_end(pie_chart)
         
     | 
| 
         @@ -227,8 +228,8 @@ class View 
     | 
|
| 
       227 
228 
     | 
    
         
             
                chart_to_image(binary_chart)
         
     | 
| 
       228 
229 
     | 
    
         
             
              end
         
     | 
| 
       229 
230 
     | 
    
         | 
| 
       230 
     | 
    
         
            -
              def build_bar_chart(title, data)
         
     | 
| 
       231 
     | 
    
         
            -
                binary_chart = Visualizer.make_bar_chart(title, data)
         
     | 
| 
      
 231 
     | 
    
         
            +
              def build_bar_chart(title, data, treshold)
         
     | 
| 
      
 232 
     | 
    
         
            +
                binary_chart = Visualizer.make_bar_chart(title, data, treshold)
         
     | 
| 
       232 
233 
     | 
    
         
             
                chart_to_image(binary_chart)
         
     | 
| 
       233 
234 
     | 
    
         
             
              end
         
     | 
| 
       234 
235 
     | 
    
         | 
| 
         @@ -275,3 +276,4 @@ class View 
     | 
|
| 
       275 
276 
     | 
    
         
             
                :build_method_stats_view, :build_if_smell_view,
         
     | 
| 
       276 
277 
     | 
    
         
             
                :build_method_smell_view, :build_text_view
         
     | 
| 
       277 
278 
     | 
    
         
             
            end
         
     | 
| 
      
 279 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/reconn/visualizer.rb
    CHANGED
    
    | 
         @@ -1,44 +1,165 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'gruff'
         
     | 
| 
       2 
2 
     | 
    
         
             
            require 'ruby-graphviz'
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
               
     | 
| 
       6 
     | 
    
         
            -
                 
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
                   
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Reconn
         
     | 
| 
      
 5 
     | 
    
         
            +
              class Visualizer
         
     | 
| 
      
 6 
     | 
    
         
            +
                def self.make_pie_chart(title, data, items_number)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  chart = Gruff::Pie.new
         
     | 
| 
      
 8 
     | 
    
         
            +
                  chart.title = title.to_s
         
     | 
| 
      
 9 
     | 
    
         
            +
                  data = Array.new(data)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  data.first(items_number).each do |item|
         
     | 
| 
      
 11 
     | 
    
         
            +
                    chart.data(item[:label], item[:value])
         
     | 
| 
      
 12 
     | 
    
         
            +
                    data.delete(item)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  chart.data("other", data.map {|itm| itm[:value]}.inject(:+))
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  chart.to_blob
         
     | 
| 
       12 
18 
     | 
    
         
             
                end
         
     | 
| 
       13 
19 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
                 
     | 
| 
      
 20 
     | 
    
         
            +
                def self.make_bar_chart(title, data, additional_line_value = nil)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  chart = Gruff::Bar.new
         
     | 
| 
      
 22 
     | 
    
         
            +
                  chart.minimum_value = 0
         
     | 
| 
      
 23 
     | 
    
         
            +
                  chart.maximum_value = data.first[:value]
         
     | 
| 
      
 24 
     | 
    
         
            +
                  chart.additional_line_values = [additional_line_value] unless additional_line_value.nil?
         
     | 
| 
      
 25 
     | 
    
         
            +
                  chart.title = title.to_s
         
     | 
| 
      
 26 
     | 
    
         
            +
                  data.each do |item|
         
     | 
| 
      
 27 
     | 
    
         
            +
                    chart.data(item[:label], item[:value])
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  chart.to_blob
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
       15 
32 
     | 
    
         | 
| 
       16 
     | 
    
         
            -
                 
     | 
| 
      
 33 
     | 
    
         
            +
                def self.make_dependency_diagram(classes)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  diagram = GraphViz.new(:G, :type => :digraph)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  nodes = classes.map { |c| diagram.add_nodes(c.name) }
         
     | 
| 
      
 36 
     | 
    
         
            +
                  external_nodes = classes.map {|c| c.external_deps}.inject(:+).uniq.map {|n| diagram.add_nodes(n)}
         
     | 
| 
      
 37 
     | 
    
         
            +
                  classes.each do |klass|
         
     | 
| 
      
 38 
     | 
    
         
            +
                    classes.each do |other_klass|
         
     | 
| 
      
 39 
     | 
    
         
            +
                      if !klass.dependencies.index {|d| d == other_klass.name }.nil? || klass.dependencies.find_all {|d| other_klass.name =~ /^.*{0,}::#{d}$/}.size == 1
         
     | 
| 
      
 40 
     | 
    
         
            +
                        node, other_node = [klass, other_klass].map {|k| nodes.find {|n| n[:label].to_s.gsub('"', '') == k.name}}
         
     | 
| 
      
 41 
     | 
    
         
            +
                        diagram.add_edges(node, other_node)
         
     | 
| 
      
 42 
     | 
    
         
            +
                      end
         
     | 
| 
      
 43 
     | 
    
         
            +
                    end
         
     | 
| 
      
 44 
     | 
    
         
            +
                    external_nodes.each {|n| n.set {|_n| _n.color = "blue"}}
         
     | 
| 
      
 45 
     | 
    
         
            +
                    external_nodes.each do |ext_node|
         
     | 
| 
      
 46 
     | 
    
         
            +
                      if klass.external_deps.include?(ext_node[:label].to_s.gsub('"', ''))
         
     | 
| 
      
 47 
     | 
    
         
            +
                        node = nodes.find {|n| n[:label].to_s.gsub('"', '') == klass.name}
         
     | 
| 
      
 48 
     | 
    
         
            +
                        diagram.add_edges(node, ext_node)
         
     | 
| 
      
 49 
     | 
    
         
            +
                      end
         
     | 
| 
      
 50 
     | 
    
         
            +
                    end
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
                  diagram.output(:png => String)
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
       17 
54 
     | 
    
         
             
              end
         
     | 
| 
      
 55 
     | 
    
         
            +
            end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
            #Monkeypatching additional line drawing
         
     | 
| 
      
 58 
     | 
    
         
            +
            module Gruff
         
     | 
| 
      
 59 
     | 
    
         
            +
              class Bar
         
     | 
| 
      
 60 
     | 
    
         
            +
                def draw
         
     | 
| 
      
 61 
     | 
    
         
            +
                  @center_labels_over_point = (@labels.keys.length > @column_count ? true : false)
         
     | 
| 
      
 62 
     | 
    
         
            +
                  super
         
     | 
| 
      
 63 
     | 
    
         
            +
                  return unless @has_data
         
     | 
| 
       18 
64 
     | 
    
         | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
                chart.minimum_value = 0
         
     | 
| 
       22 
     | 
    
         
            -
                chart.maximum_value = data.first[:value]
         
     | 
| 
       23 
     | 
    
         
            -
                chart.title = title.to_s
         
     | 
| 
       24 
     | 
    
         
            -
                data.each do |item|
         
     | 
| 
       25 
     | 
    
         
            -
                  chart.data(item[:label], item[:value])
         
     | 
| 
      
 65 
     | 
    
         
            +
                  draw_bars
         
     | 
| 
      
 66 
     | 
    
         
            +
                  draw_additional_line
         
     | 
| 
       26 
67 
     | 
    
         
             
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
                def draw_bars
         
     | 
| 
      
 69 
     | 
    
         
            +
                  # Setup spacing.
         
     | 
| 
      
 70 
     | 
    
         
            +
                  #
         
     | 
| 
      
 71 
     | 
    
         
            +
                  # Columns sit side-by-side.
         
     | 
| 
      
 72 
     | 
    
         
            +
                 @bar_spacing ||= @spacing_factor # space between the bars
         
     | 
| 
      
 73 
     | 
    
         
            +
                  @bar_width = @graph_width / (@column_count * @data.length).to_f
         
     | 
| 
      
 74 
     | 
    
         
            +
                  padding = (@bar_width * (1 - @bar_spacing)) / 2
         
     | 
| 
       27 
75 
     | 
    
         | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
      
 76 
     | 
    
         
            +
                  @d = @d.stroke_opacity 0.0
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                  # Setup the BarConversion Object
         
     | 
| 
      
 79 
     | 
    
         
            +
                  conversion = Gruff::BarConversion.new()
         
     | 
| 
      
 80 
     | 
    
         
            +
                  conversion.graph_height = @graph_height
         
     | 
| 
      
 81 
     | 
    
         
            +
                  conversion.graph_top = @graph_top
         
     | 
| 
       30 
82 
     | 
    
         | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
     | 
    
         
            -
                   
     | 
| 
       36 
     | 
    
         
            -
                     
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
     | 
    
         
            -
                       
     | 
| 
      
 83 
     | 
    
         
            +
                  # Set up the right mode [1,2,3] see BarConversion for further explanation
         
     | 
| 
      
 84 
     | 
    
         
            +
                  if @minimum_value >= 0 then
         
     | 
| 
      
 85 
     | 
    
         
            +
                    # all bars go from zero to positiv
         
     | 
| 
      
 86 
     | 
    
         
            +
                    conversion.mode = 1
         
     | 
| 
      
 87 
     | 
    
         
            +
                  else
         
     | 
| 
      
 88 
     | 
    
         
            +
                    # all bars go from 0 to negativ
         
     | 
| 
      
 89 
     | 
    
         
            +
                    if @maximum_value <= 0 then
         
     | 
| 
      
 90 
     | 
    
         
            +
                      conversion.mode = 2
         
     | 
| 
      
 91 
     | 
    
         
            +
                    else
         
     | 
| 
      
 92 
     | 
    
         
            +
                      # bars either go from zero to negativ or to positiv
         
     | 
| 
      
 93 
     | 
    
         
            +
                      conversion.mode = 3
         
     | 
| 
      
 94 
     | 
    
         
            +
                      conversion.spread = @spread
         
     | 
| 
      
 95 
     | 
    
         
            +
                      conversion.minimum_value = @minimum_value
         
     | 
| 
      
 96 
     | 
    
         
            +
                      conversion.zero = -@minimum_value/@spread
         
     | 
| 
       39 
97 
     | 
    
         
             
                    end
         
     | 
| 
       40 
98 
     | 
    
         
             
                  end
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                  # iterate over all normalised data
         
     | 
| 
      
 101 
     | 
    
         
            +
                  @norm_data.each_with_index do |data_row, row_index|
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                    data_row[DATA_VALUES_INDEX].each_with_index do |data_point, point_index|
         
     | 
| 
      
 104 
     | 
    
         
            +
                      # Use incremented x and scaled y
         
     | 
| 
      
 105 
     | 
    
         
            +
                      # x
         
     | 
| 
      
 106 
     | 
    
         
            +
                      left_x = @graph_left + (@bar_width * (row_index + point_index + ((@data.length - 1) * point_index))) + padding
         
     | 
| 
      
 107 
     | 
    
         
            +
                      right_x = left_x + @bar_width * @bar_spacing
         
     | 
| 
      
 108 
     | 
    
         
            +
                      # y
         
     | 
| 
      
 109 
     | 
    
         
            +
                      conv = []
         
     | 
| 
      
 110 
     | 
    
         
            +
                      conversion.get_left_y_right_y_scaled( data_point, conv )
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                      # create new bar
         
     | 
| 
      
 113 
     | 
    
         
            +
                      @d = @d.fill data_row[DATA_COLOR_INDEX]
         
     | 
| 
      
 114 
     | 
    
         
            +
                      @d = @d.rectangle(left_x, conv[0], right_x, conv[1])
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                      # Calculate center based on bar_width and current row
         
     | 
| 
      
 117 
     | 
    
         
            +
                      label_center = @graph_left + 
         
     | 
| 
      
 118 
     | 
    
         
            +
                                  (@data.length * @bar_width * point_index) + 
         
     | 
| 
      
 119 
     | 
    
         
            +
                                  (@data.length * @bar_width / 2.0)
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
                      # Subtract half a bar width to center left if requested
         
     | 
| 
      
 122 
     | 
    
         
            +
                      draw_label(label_center - (@center_labels_over_point ? @bar_width / 2.0 : 0.0), point_index)
         
     | 
| 
      
 123 
     | 
    
         
            +
                      if @show_labels_for_bar_values
         
     | 
| 
      
 124 
     | 
    
         
            +
                        val = (@label_formatting || '%.2f') % @norm_data[row_index][3][point_index]
         
     | 
| 
      
 125 
     | 
    
         
            +
                        draw_value_label(left_x + (right_x - left_x)/2, conv[0]-30, val.commify, true)
         
     | 
| 
      
 126 
     | 
    
         
            +
                      end
         
     | 
| 
      
 127 
     | 
    
         
            +
                    end
         
     | 
| 
      
 128 
     | 
    
         
            +
                  end
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
      
 130 
     | 
    
         
            +
                  # Draw the last label if requested
         
     | 
| 
      
 131 
     | 
    
         
            +
                  draw_label(@graph_right, @column_count) if @center_labels_over_point
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
                  draw_additional_line
         
     | 
| 
      
 134 
     | 
    
         
            +
                  @d.draw(@base_image)
         
     | 
| 
      
 135 
     | 
    
         
            +
                end
         
     | 
| 
      
 136 
     | 
    
         
            +
                # Draws additional horizontal line
         
     | 
| 
      
 137 
     | 
    
         
            +
                def draw_additional_line
         
     | 
| 
      
 138 
     | 
    
         
            +
                   @additional_line_colors << '#f61100'
         
     | 
| 
      
 139 
     | 
    
         
            +
                   @d = @d.stroke_opacity 100.0
         
     | 
| 
      
 140 
     | 
    
         
            +
                   i = 0
         
     | 
| 
      
 141 
     | 
    
         
            +
                   @additional_line_values.each do |value|
         
     | 
| 
      
 142 
     | 
    
         
            +
                     @increment_scaled = @graph_height.to_f / (@maximum_value.to_f / value)
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
                     y = @graph_top + @graph_height - @increment_scaled
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
                     @d = @d.stroke(@additional_line_colors[i])
         
     | 
| 
      
 147 
     | 
    
         
            +
                     @d = @d.line(@graph_left, y, @graph_right, y)
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                     @d.fill = @additional_line_colors[i]
         
     | 
| 
      
 151 
     | 
    
         
            +
                     @d.font = @font if @font
         
     | 
| 
      
 152 
     | 
    
         
            +
                     @d.stroke('transparent')
         
     | 
| 
      
 153 
     | 
    
         
            +
                     @d.pointsize = scale_fontsize(@marker_font_size)
         
     | 
| 
      
 154 
     | 
    
         
            +
                     @d.gravity = EastGravity
         
     | 
| 
      
 155 
     | 
    
         
            +
                     @d = @d.annotate_scaled( @base_image,
         
     | 
| 
      
 156 
     | 
    
         
            +
                                             @graph_right - LABEL_MARGIN, 1.0,
         
     | 
| 
      
 157 
     | 
    
         
            +
                                             0.0, y - (@marker_font_size/2.0),
         
     | 
| 
      
 158 
     | 
    
         
            +
                                             label(value, value), @scale)
         
     | 
| 
      
 159 
     | 
    
         
            +
                     i += 1
         
     | 
| 
      
 160 
     | 
    
         
            +
                   end
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
                  @d = @d.stroke_antialias true
         
     | 
| 
       41 
163 
     | 
    
         
             
                end
         
     | 
| 
       42 
     | 
    
         
            -
                diagram.output(:png => String)
         
     | 
| 
       43 
164 
     | 
    
         
             
              end
         
     | 
| 
       44 
165 
     | 
    
         
             
            end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: reconn
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version:  
     | 
| 
      
 4 
     | 
    
         
            +
              version: 1.0.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Mateusz Czarnecki
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2015-01- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2015-01-29 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: vrlib
         
     |