snuffle 0.13.0 → 0.14.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/lib/snuffle.rb +1 -0
- data/lib/snuffle/args_clump.rb +46 -0
- data/lib/snuffle/cli.rb +0 -1
- data/lib/snuffle/elements/method_definition.rb +10 -0
- data/lib/snuffle/formatters/base.rb +1 -2
- data/lib/snuffle/formatters/templates/output.html.haml +9 -1
- data/lib/snuffle/latent_object.rb +3 -3
- data/lib/snuffle/node.rb +2 -3
- data/lib/snuffle/source_file.rb +5 -0
- data/lib/snuffle/summary.rb +2 -1
- data/lib/snuffle/version.rb +1 -1
- data/spec/fixtures/program_2.rb +18 -28
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: be82187f6d2b734240dd36555ab530cfbfe6e4be
|
4
|
+
data.tar.gz: eb57d17b6d4aba3c8114e55169b60b099715254a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 80457fff5e73a70dfbf62ce6fd3b7ae86f4076dfe1abc103f6b4f6be3f0623357063d13e2419861be4a4ab37ea958e93d8907e9a083c67997a6d0f301e35bb4d
|
7
|
+
data.tar.gz: aa36f7fc893adbf5c098fbea48226ce33947d074159a2a8751fb4ffd9c2565e1a94f21a77de8d11c7c9ab27e78daa7bfc7ef8d4f87580a178e9a7d23e734bcc4
|
data/lib/snuffle.rb
CHANGED
@@ -12,6 +12,7 @@ require_relative "snuffle/formatters/csv"
|
|
12
12
|
require_relative "snuffle/formatters/html"
|
13
13
|
require_relative "snuffle/formatters/html_index"
|
14
14
|
require_relative "snuffle/formatters/text"
|
15
|
+
require_relative "snuffle/args_clump"
|
15
16
|
require_relative "snuffle/latent_object"
|
16
17
|
require_relative "snuffle/line_of_code"
|
17
18
|
require_relative "snuffle/node"
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'pry'
|
2
|
+
module Snuffle
|
3
|
+
|
4
|
+
class ArgsClump
|
5
|
+
|
6
|
+
include PoroPlus
|
7
|
+
attr_accessor :element, :neighbors, :line_numbers
|
8
|
+
|
9
|
+
def self.from(nodes)
|
10
|
+
nodes = nodes.method_defs
|
11
|
+
clumps = Element::MethodDefinition.materialize(nodes.to_a).inject([]) do |clumps, element|
|
12
|
+
clump = ArgsClump.new(element: element, line_numbers: element.node.line_numbers.first )
|
13
|
+
if clump.values.count > 1 && clump.near_neighbors.any?
|
14
|
+
clumps << clump
|
15
|
+
end
|
16
|
+
clumps
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def has_near_neighbors?
|
21
|
+
near_neighbors.present?
|
22
|
+
end
|
23
|
+
|
24
|
+
def near_neighbors
|
25
|
+
@near_neighbors ||= neighbors.select{ |n| (n.values & values).size > 0 }
|
26
|
+
end
|
27
|
+
|
28
|
+
def neighbors
|
29
|
+
@neighbors ||= [element.node.siblings - [self.element.node]].flatten.map{|sibling| Element::MethodDefinition.materialize([sibling]).first}
|
30
|
+
end
|
31
|
+
|
32
|
+
def values
|
33
|
+
@values ||= self.element.values
|
34
|
+
end
|
35
|
+
|
36
|
+
def neighbor
|
37
|
+
Struct.new(:element, :distance)
|
38
|
+
end
|
39
|
+
|
40
|
+
def distance(primary_matrix, token_matrix)
|
41
|
+
Snuffle::Util::Correlation.distance(primary_matrix, token_matrix)
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
data/lib/snuffle/cli.rb
CHANGED
@@ -74,7 +74,7 @@
|
|
74
74
|
%div.column
|
75
75
|
%h3.indented.highlighted
|
76
76
|
Data Clumps:
|
77
|
-
-
|
77
|
+
- unless summary.cohorts.any? || summary.arg_clumps.any?
|
78
78
|
%p.indented
|
79
79
|
%em None
|
80
80
|
- else
|
@@ -87,6 +87,14 @@
|
|
87
87
|
(line
|
88
88
|
= ":#{cohorts.map(&:line_numbers).join(', :')}"
|
89
89
|
)
|
90
|
+
- summary.arg_clumps.group_by{|c| c.values.sort }.each do |args, clumps|
|
91
|
+
- if clumps.count > 0
|
92
|
+
%li
|
93
|
+
= args.map{|c| ".#{c}" }.join(", ")
|
94
|
+
%br
|
95
|
+
(line
|
96
|
+
= ":#{clumps.map(&:line_numbers).join(', :')}"
|
97
|
+
)
|
90
98
|
%div.column
|
91
99
|
%h3.indented.highlighted-method
|
92
100
|
Possible Latent Objects:
|
@@ -28,13 +28,13 @@ class Snuffle::LatentObject
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def self.potential_objects_with_methods(nodes, threshold=DUPLICATE_THRESHOLD)
|
31
|
-
method_candidates = Snuffle::Element::MethodDefinition.materialize(nodes.
|
31
|
+
method_candidates = Snuffle::Element::MethodDefinition.materialize(nodes.method_defs)
|
32
32
|
extract_candidates(method_candidates).select{|k,v| v.count > threshold }
|
33
33
|
end
|
34
34
|
|
35
|
-
def self.extract_candidates(
|
35
|
+
def self.extract_candidates(method_defs)
|
36
36
|
stemmer = UEAStemmer.new
|
37
|
-
|
37
|
+
method_defs.map(&:method_name).inject({}) do |words, method_name|
|
38
38
|
atoms = method_name.split('_') - STOPWORDS
|
39
39
|
atoms = atoms.map{|atom| stemmer.stem(atom.to_s)}
|
40
40
|
atoms.each{ |word| words[word] ||= []; words[word] << method_name }
|
data/lib/snuffle/node.rb
CHANGED
@@ -5,13 +5,12 @@ module Snuffle
|
|
5
5
|
include Ephemeral::Base
|
6
6
|
include PoroPlus
|
7
7
|
|
8
|
-
attr_accessor :id, :name, :type, :child_ids, :parent_id, :line_numbers
|
8
|
+
attr_accessor :id, :name, :type, :child_ids, :parent_id, :line_numbers, :args
|
9
9
|
|
10
|
-
scope :by_id, lambda{|id| where(:id => id)}
|
11
10
|
scope :by_type, lambda{|type| where(:type => type)}
|
12
11
|
scope :with_parent, lambda{|parent_id| where(parent_id: parent_id) }
|
13
12
|
scope :hashes, {type: :hash}
|
14
|
-
scope :
|
13
|
+
scope :method_defs, {is_method: true}
|
15
14
|
scope :non_sends, {is_send: false}
|
16
15
|
|
17
16
|
def self.nil
|
data/lib/snuffle/source_file.rb
CHANGED
@@ -19,6 +19,10 @@ module Snuffle
|
|
19
19
|
@nodes ||= extract_nodes_from(ast)
|
20
20
|
end
|
21
21
|
|
22
|
+
def arg_clumps
|
23
|
+
@arg_clumps ||= ArgsClump.from(self.nodes)
|
24
|
+
end
|
25
|
+
|
22
26
|
def cohorts
|
23
27
|
@cohorts ||= Cohort.from(self.nodes)
|
24
28
|
end
|
@@ -47,6 +51,7 @@ module Snuffle
|
|
47
51
|
path_to_file: self.path_to_file,
|
48
52
|
cohorts: cohorts,
|
49
53
|
latent_objects: latent_objects,
|
54
|
+
arg_clumps: arg_clumps,
|
50
55
|
source: self.source
|
51
56
|
)
|
52
57
|
end
|
data/lib/snuffle/summary.rb
CHANGED
@@ -3,9 +3,10 @@ module Snuffle
|
|
3
3
|
class Summary
|
4
4
|
include PoroPlus
|
5
5
|
attr_accessor :class_name, :path_to_file, :cohorts, :latent_objects, :source
|
6
|
+
attr_accessor :arg_clumps
|
6
7
|
|
7
8
|
def has_results?
|
8
|
-
self.cohorts.count != 0 || self.latent_objects.count != 0
|
9
|
+
self.cohorts.count != 0 || self.latent_objects.count != 0 || self.arg_clumps.count != 0
|
9
10
|
end
|
10
11
|
|
11
12
|
def path_to_results
|
data/lib/snuffle/version.rb
CHANGED
data/spec/fixtures/program_2.rb
CHANGED
@@ -2,51 +2,41 @@ class Customer
|
|
2
2
|
|
3
3
|
attr_accessor :customer_id, :customer_name, :company_name
|
4
4
|
attr_accessor :street_address_1, :street_address_2
|
5
|
-
|
5
|
+
attr_accessor :city, :state, :postal_code, :phone_number
|
6
6
|
|
7
7
|
MY_CONSTANT = "TheOtherZachIsThePrimaryZach"
|
8
8
|
|
9
9
|
def self.api_root
|
10
|
-
|
11
|
-
|
12
|
-
def my_condition
|
13
|
-
puts "MAGIC" if true == false
|
10
|
+
"http://localhost/api/"
|
14
11
|
end
|
15
12
|
|
16
13
|
def address_is_residence?
|
17
14
|
self.company_name.nil?
|
18
15
|
end
|
19
16
|
|
20
|
-
def get_coords_for_address
|
21
|
-
# fake_api_call(city: city, state: state, postal_code: postal_code)
|
22
|
-
end
|
23
|
-
|
24
17
|
def neighborhood
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
18
|
+
NeighborhoodApi.post(
|
19
|
+
state: self.state,
|
20
|
+
city: self.city,
|
21
|
+
postal_code: self.postal_code
|
22
|
+
).results[:neighborhood]
|
30
23
|
end
|
31
24
|
|
32
|
-
def
|
33
|
-
|
25
|
+
def verified_state
|
26
|
+
NeighborhoodApi.post(
|
27
|
+
city: self.city,
|
28
|
+
postal_code: self.postal_code
|
29
|
+
).results[:state]
|
34
30
|
end
|
35
31
|
|
36
|
-
def
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
def fake_neighborhood_api_call(args={})
|
41
|
-
"Probably River North"
|
42
|
-
end
|
43
|
-
|
44
|
-
def fake_api_call(args={})
|
45
|
-
[112.32, 124.11]
|
32
|
+
def verified_country
|
33
|
+
NeighborhoodApi.post(
|
34
|
+
state: self.state,
|
35
|
+
).results[:country]
|
46
36
|
end
|
47
37
|
|
48
38
|
def business_card_api_call
|
49
|
-
{name: customer_name, business: company_name}
|
39
|
+
{name: customer_name, business: company_name, phone: phone_number}
|
50
40
|
end
|
51
41
|
|
52
42
|
def letterhead_api_call
|
@@ -63,7 +53,7 @@ class Customer
|
|
63
53
|
string << self.company_name if address_is_residence?
|
64
54
|
string << self.street_address_1
|
65
55
|
string << self.street_address_2 if street_address_2.present?
|
66
|
-
|
56
|
+
string << "#{self.city}, #{self.state} #{self.postal_code}"
|
67
57
|
string.join", "
|
68
58
|
end
|
69
59
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: snuffle
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Coraline Ada Ehmke
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2015-04-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: parser
|
@@ -213,6 +213,7 @@ files:
|
|
213
213
|
- images/detail.png
|
214
214
|
- images/overview.png
|
215
215
|
- lib/snuffle.rb
|
216
|
+
- lib/snuffle/args_clump.rb
|
216
217
|
- lib/snuffle/cli.rb
|
217
218
|
- lib/snuffle/cohort.rb
|
218
219
|
- lib/snuffle/elements/hash.rb
|
@@ -266,7 +267,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
266
267
|
version: '0'
|
267
268
|
requirements: []
|
268
269
|
rubyforge_project:
|
269
|
-
rubygems_version: 2.
|
270
|
+
rubygems_version: 2.4.6
|
270
271
|
signing_key:
|
271
272
|
specification_version: 4
|
272
273
|
summary: Snuffle detects data clumps in your Ruby code.
|
@@ -284,3 +285,4 @@ test_files:
|
|
284
285
|
- spec/snuffle/source_file_spec.rb
|
285
286
|
- spec/snuffle/util/histogram_spec.rb
|
286
287
|
- spec/spec_helper.rb
|
288
|
+
has_rdoc:
|