File: gestalt_engine.rb

package info (click to toggle)
ohcount 3.0.0-6.1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 4,828 kB
  • sloc: ansic: 6,534; ruby: 2,560; perl: 2,041; erlang: 350; lisp: 272; sh: 244; pascal: 196; vhdl: 150; haskell: 149; asm: 127; cs: 124; awk: 98; java: 92; php: 73; tcl: 58; xml: 57; fortran: 54; makefile: 32; python: 31; ada: 30; objc: 30; jsp: 28; sql: 18; cobol: 13; ml: 9; cpp: 3
file content (131 lines) | stat: -rw-r--r-- 3,434 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
module Ohcount
  module Gestalt

    # smells is a general class that aggregates facts required to deduce
    # gestalts
    class GestaltEngine
      attr_reader :gestalts

      def initialize
        @language_facts = LanguageFacts.new
        @gestalts = []
        @source_file_rules = []
        @definitions = Definition.all_definitions.map do |d|
          new_definition = d.clone
          new_definition.top_level_or.each_rule do |r|
            @source_file_rules << r if r.is_a?(FileRule)
          end
          new_definition
        end
      end

      def process_source_file(source_file)
        @source_file_rules.each do |r|
          r.process_source_file(source_file)
        end
        @language_facts.process_source_file(source_file)
      end

      def process_source_files(source_file_list)
        source_file_list.each_source_file do |source_file|
          process_source_file source_file
        end
        self
      end

      def process(what)
        if what.is_a?(SourceFile)
          process_source_file(what)
        elsif what.is_a?(SourceFileList)
          process_source_file_list(what)
        else
          raise ArgumentError.new
        end
      end

      def calc_gestalts(definitions = nil)
        # since gestalts can depend on other gestalts, we perform an
        # iterative process and break when no new gestalts have been
        # detected.
        gestalt_count = 0

        while true do
          
          # collect what we can
          yank_definitions = []
          @definitions.each do |d|

            new_gestalts = d.gestalts(self)
            if new_gestalts.any?
              yank_definitions << d
              @gestalts += new_gestalts
            end
          end
          @definitions -= yank_definitions

          # did we make any progress?
          break if gestalt_count == @gestalts.size

          # nope, keep going
          gestalt_count = @gestalts.size
        end

        gestalts
      end

      def has_gestalt?(type,name)
        @gestalts.find do |g|
          g.type.to_s == type.to_s &&
            g.name == name
        end
      end

      def includes_language?(language, min_percent)
        @language_facts.includes_language?(language,min_percent)
      end
    end


    # keeps track of languages seen
    class LanguageFacts

      def initialize
        @language_counts ||= {}
      end

      def process_source_file(source_file)
        source_file.language_breakdowns.each do |lb|
          @language_counts[lb.name.intern] ||= 0
          @language_counts[lb.name.intern] += lb.code_count
        end
      end

      def includes_language?(language, min_percent = 0)
        return false unless @language_counts[language]
        language_percents[language] >= min_percent
      end

      # ignores markup languages (xml/html)
      def language_percents
        @language_percents ||= begin
          total = 0
          @language_counts.each_pair do |name,code_count|
						language = Ohcount.ohcount_hash_language_from_name(name.to_s)
						STDOUT.puts "Warning: Couldn't find #{name} in ohcount_hash_language_from_name" if language.nil?
						next if language.nil? || language.category == 1
            total += code_count
          end

          l = {}
          @language_counts.each do |k,v|
           l[k] = 100.0 * v.to_i / total
          end
          l

        end
      end
    end

  end
end