ruby_codex 0.0.3 → 0.0.4a

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.
Files changed (3) hide show
  1. data/lib/ruby_codex.rb +65 -38
  2. metadata +8 -7
  3. checksums.yaml +0 -15
data/lib/ruby_codex.rb CHANGED
@@ -2,10 +2,10 @@ load 'data_node.rb'
2
2
 
3
3
  class Codex
4
4
 
5
- attr_accessor :block, :func, :func_chain, :cond, :ident
6
-
7
- def initialize(db,agg_db)
5
+ attr_reader :nodes
8
6
 
7
+ def initialize(db,agg_db)
8
+ @nodes = {}
9
9
  # helper procs
10
10
  info = Proc.new do |node|
11
11
  normal_node(node) do |n, norm|
@@ -52,7 +52,7 @@ class Codex
52
52
  :func_info => Proc.new { |v| v.first[:func_info] }
53
53
  }
54
54
 
55
- @block = DataNode.new(
55
+ @nodes[:block] = DataNode.new(
56
56
  db, agg_db,
57
57
  Proc.new { |x| x.type == :block},
58
58
  key.merge({
@@ -83,18 +83,17 @@ class Codex
83
83
  query_count = query.nil? ? 0 : query.count
84
84
  blocks = db.where(:type => keys[:type], :func => keys[:func]).sum(:count)
85
85
  rets = db.where(:type => keys[:type], :ret_val => keys[:ret_val]).sum(:count)
86
- if query_count <= 0
87
- { :keys => keys,
88
- :message =>
89
- "We've seen #{keys[:func]} blocks returning #{keys[:ret_val]} only #{query_count.to_s} " +
90
- "times, though we've seen #{keys[:func]} blocks #{blocks.to_s} times and #{keys[:ret_val]} " +
91
- "returned #{rets.to_s} times."
92
- } if blocks > 0 && rets > 0
93
- end
86
+ { :keys => keys,
87
+ :message =>
88
+ "We've seen #{keys[:func]} blocks returning the #{keys[:ret_val]} type #{query_count.to_s} " +
89
+ "times, and we've seen #{keys[:func]} blocks #{blocks.to_s} times and #{keys[:ret_val]} " +
90
+ "returned #{rets.to_s} times.",
91
+ :unlikely => Proc.new { |gt=1,bt = 0,rt = 0| query_count < gt && blocks > bt && rets > rt}
92
+ }
94
93
  }
95
94
  )
96
95
 
97
- @func = DataNode.new(
96
+ @nodes[:func] = DataNode.new(
98
97
  db, agg_db,
99
98
  Proc.new { |x| x.type == :send},
100
99
  key.merge({
@@ -111,13 +110,14 @@ class Codex
111
110
  alt_count = func.nil? ? 0 : func.count
112
111
  { :keys => keys,
113
112
  :message =>
114
- "Function call #{keys[:norm_code]} has appeared #{query_count.to_s} times, but " +
115
- "#{func.norm_code} has appeared #{alt_count.to_s} times."
116
- } if alt_count > 10 * (query_count + 1)
113
+ "Function call #{keys[:norm_code]} has appeared #{query_count.to_s} times, and the most " +
114
+ "common alternative #{func.norm_code} has appeared #{alt_count.to_s} times.",
115
+ :unlikely => Proc.new { |t=10| alt_count > t * (query_count + 1)}
116
+ }
117
117
  }
118
118
  )
119
119
 
120
- @func_chain = func = DataNode.new(
120
+ @nodes[:func_chain] = DataNode.new(
121
121
  db, agg_db,
122
122
  Proc.new { |x| x.type == :send && type.call(x.children.first) == "send" },
123
123
  key.merge({
@@ -132,19 +132,19 @@ class Codex
132
132
  combine,
133
133
  Proc.new do |db,keys,data|
134
134
  query = db.where(keys).first
135
- if query.nil? || query.count <= 0
136
- fs = [:f1,:f2].map { |f| db.where(:type => "send", :func => keys[f]).size }
137
- { :keys => keys,
138
- :message =>
139
- "Function #{keys[:f1]} has appeared #{fs[0].to_s} times " +
140
- "and #{keys[:f2]} has appeared #{fs[1].to_s} times, but " +
141
- "they haven't appeared together."
142
- } unless fs[0] <= 0 || fs[1] <= 0
143
- end
135
+ query_count = query.nil? ? 0 : query.count
136
+ fs = [:f1,:f2].map { |f| db.where(:type => "send", :func => keys[f]).size }
137
+ { :keys => keys,
138
+ :message =>
139
+ "Function #{keys[:f1]} has appeared #{fs[0].to_s} times " +
140
+ "and #{keys[:f2]} has appeared #{fs[1].to_s} times, and " +
141
+ "they've appeared #{query_count} times together.",
142
+ :unlikely => Proc.new { |gt=1, t=10| query_count < gt && fs[0] > t && fs[1] > t }
143
+ }
144
144
  end
145
145
  )
146
146
 
147
- @cond = DataNode.new(
147
+ @nodes[:cond] = DataNode.new(
148
148
  db, agg_db,
149
149
  Proc.new { |x| x.type == :if },
150
150
  key.merge({
@@ -157,7 +157,7 @@ class Codex
157
157
  combine
158
158
  )
159
159
 
160
- @ident = DataNode.new(
160
+ @nodes[:ident] = DataNode.new(
161
161
  db, agg_db,
162
162
  Proc.new { |x| [:lvasgn, :ivasgn, :cvasgn, :gvasgn].include?(x.type) },
163
163
  key.merge({
@@ -177,21 +177,48 @@ class Codex
177
177
  if query
178
178
  types = query.ident_types.select { |k,v| ["str","int","float","array","hash"].include? k }
179
179
  types.default = 0
180
- pp types
181
- first, second = types.sort_by{ |k,v| v*-1 }.take(2)
182
- if (first && second.nil?) || (first[1] > 10 * (second[1] + 1))
183
- { :keys => keys,
184
- :message =>
185
- "The identifier #{keys[:ident]} has appeared #{first[1].to_s} " +
186
- "times as #{first[0].to_s}, but only #{types[data[:ident_type]].to_s} " +
187
- "times as #{data[:ident_type].to_s}"
188
- } unless first[0].to_s == data[:ident_type]
189
- end
180
+ best = types.select { |k,v| k != data[:ident_type] }.sort_by{ |k,v| v*-1 }.first
181
+ { :keys => keys,
182
+ :message =>
183
+ "The identifier #{keys[:ident]} has appeared #{types[data[:ident_type]].to_s} " +
184
+ "times as #{data[:ident_type].to_s} and #{best[1].to_s} times as #{best[0].to_s}",
185
+ :unlikely => Proc.new { |t=5| best[1] > t * (types[keys[:ident_type]] + 1) }
186
+ }
187
+ else
188
+ { :message => "Never Seen", :unlikely => Proc.new { false } }
190
189
  end
191
190
  }
192
191
  )
193
192
  end
194
193
 
194
+ def add_ast(ast, file, project, &block)
195
+ @nodes.each do |k,v|
196
+ v.add_ast(ast, file, project, &block)
197
+ end
198
+ end
199
+
200
+ def save_all!
201
+ @nodes.each do |k,v|
202
+ v.save!
203
+ end
204
+ end
205
+
206
+ def query(ast)
207
+ @nodes.each do |k,v|
208
+ yield k, v.query(ast)
209
+ end
210
+ end
211
+
212
+ def is_unlikely(ast, options = Hash.new([]))
213
+ unlikely = []
214
+ query(ast) do |k, message|
215
+ if message && message[:unlikely].call(*options[k])
216
+ unlikely.push(message)
217
+ end
218
+ end
219
+ unlikely
220
+ end
221
+
195
222
  def without_caller(node)
196
223
  node.updated(nil, node.children.map.with_index do |x,i|
197
224
  i == 0 ? nil : x
metadata CHANGED
@@ -1,7 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_codex
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4a
5
+ prerelease: 5
5
6
  platform: ruby
6
7
  authors:
7
8
  - Ethan Fast
@@ -22,26 +23,26 @@ files:
22
23
  homepage: http://rubygems.org/gems/ruby-codex
23
24
  licenses:
24
25
  - MIT
25
- metadata: {}
26
26
  post_install_message:
27
27
  rdoc_options: []
28
28
  require_paths:
29
29
  - lib
30
30
  required_ruby_version: !ruby/object:Gem::Requirement
31
+ none: false
31
32
  requirements:
32
33
  - - ! '>='
33
34
  - !ruby/object:Gem::Version
34
35
  version: '0'
35
36
  required_rubygems_version: !ruby/object:Gem::Requirement
37
+ none: false
36
38
  requirements:
37
- - - ! '>='
39
+ - - ! '>'
38
40
  - !ruby/object:Gem::Version
39
- version: '0'
41
+ version: 1.3.1
40
42
  requirements: []
41
43
  rubyforge_project:
42
- rubygems_version: 2.0.5
44
+ rubygems_version: 1.8.25
43
45
  signing_key:
44
- specification_version: 4
46
+ specification_version: 3
45
47
  summary: Analyze ruby ASTs with Codex
46
48
  test_files: []
47
- has_rdoc:
checksums.yaml DELETED
@@ -1,15 +0,0 @@
1
- ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- MmQ3MDg3YzBkZjZmMmM5ZmI2ODEyMTMxYWI0MWU4MGI3N2VmMDBjMQ==
5
- data.tar.gz: !binary |-
6
- ZjEzZThiNmI4M2RjYjM5MGUwZmQzYzAzOWI0MjNmODRmN2Y0YzZiYQ==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- MWJjZTliOTQzMzU3NDM3OTRlYjI0OGRiMzMyZjA5YWM5MjBmYWMyMDcxNDI3
10
- ZWM3OWE5ODhjZTU2YTBiNjlmMzI1YzQzMTMwODZlMTk3ZjljYzAyYzA2ZDQx
11
- ZjUzMzNhZjk0ZjI0YjFiOGFmMWYzYTNkZTE4NmYzMzI0Y2E1MzE=
12
- data.tar.gz: !binary |-
13
- NWQwMTBjNmY3NjAwZTNiOWYyNDliYmE3YjM4MWE4MDk2YmI2N2IxYTk1ZTE0
14
- NzA1YzZhNjQwYjBiMzI4MmE1NTViODg0YWJkMTA3NTBlODFiMzAzZjc2ZDA4
15
- Y2VlYzFiNDdhYmFkN2E3YzdmNDMzZmQxZThlMjFiNTA1ZDk4ODk=