factory_trace 0.2.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 33c0207895ffee9e1ce968b396f9acf75a298664e9cd9dd7a8766031c8bfbcb9
4
- data.tar.gz: 4bb96700eefd658c71639b9423b058a604e8c8ad29cdc96a1569883e62d4c0c3
3
+ metadata.gz: 4437d507c038bcb203d04574fb49cbfd1f6986a75d8e114f06cd6447d282003a
4
+ data.tar.gz: 3d4cf49b2dd89104b9ec7d52e56c56f46317724e3d6fdb36001ef005aac13bea
5
5
  SHA512:
6
- metadata.gz: a590c9294896d635673d8a3f3864fcc09cf3fded38ace341d1d9874f190171809027218ec6331987b26235cd2a855a39a76fe8bfb4b0900453edf74c2a0d35c4
7
- data.tar.gz: 98237229d930694a1459a4c052d2221c6cf15bb5c85bf76124d9ea81c0c3d98ff620192e1f94b6b1286aad38f7f1d02301a8e9c15cb4abad2025d4767a4a790f
6
+ metadata.gz: 2feacb312890c6376e5bc89fa32f844fffd8add32f0730e96f81d51e655956905353d40050d3eda0e32073157be166111fba497a555d98bc821b22e5273a14bb
7
+ data.tar.gz: 4459f62ba40c6977f2338b67398c598557826a639acf7e5035b499b51d13d7ab5827efc990d1f6cee7151c52162abdf3fab15111c2368a545e80d57c92ab1e66
data/exe/factory_trace CHANGED
@@ -8,7 +8,7 @@ fail "You should pass at least one file with traced information.\nYou can genera
8
8
  config = FactoryTrace.configuration
9
9
  hash = FactoryTrace::Readers::TraceReader.read_from_files(*ARGV)
10
10
  reports = FactoryTrace::Processors::FindUnused.call(hash[:defined], hash[:used])
11
- code = reports.any? { |report| report[:code] == :unused } ? 1 : 0
11
+ code = reports.any? { |report| report[:code] == :unused && !report.key?(:value) } ? 1 : 0
12
12
 
13
13
  FactoryTrace::Writers::ReportWriter.new(config.out, config).write(reports)
14
14
  exit(code)
@@ -4,13 +4,12 @@ module FactoryTrace
4
4
  module_function
5
5
 
6
6
  # @param [FactoryBot::Trait] trait
7
- # @param [FactoryBot::Factory] owner
8
7
  #
9
8
  # @return [FactoryTrace::Structures::Trait]
10
- def trait(trait, owner = nil)
9
+ def trait(trait)
11
10
  FactoryTrace::Structures::Trait.new(
12
11
  trait.name.to_s,
13
- owner && owner.name.to_s
12
+ declaration_names: trait.definition.declarations.grep(FactoryBot::Declaration::Implicit).map(&:name).map(&:to_s)
14
13
  )
15
14
  end
16
15
 
@@ -19,10 +18,10 @@ module FactoryTrace
19
18
  # @return [FactoryTrace::Structures::Factory]
20
19
  def factory(factory)
21
20
  FactoryTrace::Structures::Factory.new(
22
- factory.name.to_s,
23
- factory.send(:parent).respond_to?(:name) ? factory.send(:parent).name.to_s : nil,
24
- factory.defined_traits.map(&:name).map(&:to_s),
25
- factory.names.map(&:to_s) - [factory.name.to_s]
21
+ factory.names.map(&:to_s),
22
+ factory.defined_traits.map(&method(:trait)),
23
+ parent_name: factory.send(:parent).respond_to?(:name) ? factory.send(:parent).name.to_s : nil,
24
+ declaration_names: factory.definition.declarations.grep(FactoryBot::Declaration::Implicit).map(&:name).map(&:to_s)
26
25
  )
27
26
  end
28
27
  end
@@ -0,0 +1,17 @@
1
+ module FactoryTrace
2
+ module Helpers
3
+ module Statusable
4
+ PRIORITY_ORDER = [:used, :indirectly_used, nil]
5
+
6
+ attr_reader :status
7
+
8
+ def status=(status)
9
+ @status = status unless has_prioritized_status?(status)
10
+ end
11
+
12
+ def has_prioritized_status?(status)
13
+ PRIORITY_ORDER.index(@status) <= PRIORITY_ORDER.index(status)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -10,7 +10,10 @@ module FactoryTrace
10
10
  collection = FactoryTrace::Structures::Collection.new
11
11
 
12
12
  trace.each do |factory_name, trait_names|
13
- collection.add(FactoryTrace::Structures::Factory.new(factory_name, nil, trait_names.to_a, []))
13
+ traits = trait_names.map { |trait_name| FactoryTrace::Structures::Trait.new(trait_name) }
14
+ factory = FactoryTrace::Structures::Factory.new([factory_name], traits)
15
+
16
+ collection.add(factory)
14
17
  end
15
18
 
16
19
  collection
@@ -8,111 +8,101 @@ module FactoryTrace
8
8
  #
9
9
  # @return [Array<Hash>]
10
10
  def self.call(defined, used)
11
- used_inherited_traits = used_inherited_traits(defined, used)
12
- used_child_factories = used_child_factories(defined, used)
11
+ mark_as_used(defined, used)
13
12
 
14
13
  output = []
15
14
 
16
15
  defined.factories.each do |factory|
17
- unless used.find(factory)
18
- if used_child_factories[factory.name]
19
- output << {code: :used_indirectly, factory_name: factory.name, child_factories_names: used_child_factories[factory.name]}
20
- else
21
- output << {code: :unused, factory_name: factory.name}
22
- end
23
- end
16
+ output << {code: :unused, factory_names: factory.names} unless factory.status
24
17
 
25
- factory.trait_names.each do |trait_name|
26
- unless trait_used?(used, factory, trait_name) || trait_used?(used_inherited_traits, factory, trait_name)
27
- output << {code: :unused, factory_name: factory.name, trait_name: trait_name}
28
- end
18
+ factory.traits.each do |trait|
19
+ output << {code: :unused, factory_names: factory.names, trait_name: trait.name} unless trait.status
29
20
  end
30
21
  end
31
22
 
32
23
  defined.traits.each do |trait|
33
- unless used_inherited_traits.find(trait)
34
- output << {code: :unused, trait_name: trait.name}
35
- next
36
- end
24
+ output << {code: :unused, trait_name: trait.name} unless trait.status
37
25
  end
38
26
 
39
- unused_count = output.count { |result| result[:code] == :unused }
40
- used_indirectly_count = output.count { |result| result[:code] == :used_indirectly }
41
-
42
- output.unshift(code: :unused, value: unused_count)
43
- output.unshift(code: :used_indirectly, value: used_indirectly_count)
44
- output.unshift(code: :used, value: defined.total - unused_count - used_indirectly_count)
27
+ output.unshift(code: :unused, value: output.size)
28
+ output.unshift(code: :used, value: defined.total - (output.size - 1))
45
29
 
46
30
  output
47
31
  end
48
32
 
49
33
  private
50
34
 
51
- # Checks if factory of the collection contains a trait
52
- #
53
- # @param [FactoryTrace::Structures::Collection] collection
54
- # @param [FactoryTrace::Structures::Factory] factory
55
- # @param [String] trait_name
56
- #
57
- # @return [Boolean]
58
- def self.trait_used?(collection, factory, trait_name)
59
- factory = collection.find(factory)
60
- factory && factory.trait_names.include?(trait_name)
35
+ # @param [FactoryTrace::Structures::Collection] defined
36
+ # @param [FactoryTrace::Structures::Collection] used
37
+ def self.mark_as_used(defined, used)
38
+ used.factories.each do |used_factory|
39
+ defined_factory = defined.find_factory_by_names(used_factory.names)
40
+ mark_factory(defined_factory, defined, status: :used)
41
+
42
+ used_factory.traits.each do |used_trait|
43
+ trait_owner, defined_trait = defined_trait_by_name(defined, used_factory, used_trait.name)
44
+ mark_trait(defined_trait, trait_owner, defined, status: :used)
45
+ end
46
+ end
61
47
  end
62
48
 
63
- # Returns a new collection where traits which were used moved to their owner factory
64
- #
65
49
  # @param [FactoryTrace::Structures::Collection] defined
66
- # @param [FactoryTrace::Structures::Collection] used
50
+ # @param [FactoryTrace::Structures::Factory|nil] factory
51
+ # @param [String] trait_name
67
52
  #
68
- # @return [FactoryTrace::Structures::Collection]
69
- def self.used_inherited_traits(defined, used)
70
- collection = FactoryTrace::Structures::Collection.new
53
+ # @return [Array<Object>]
54
+ def self.defined_trait_by_name(defined, factory, trait_name)
55
+ if factory
56
+ possible_owner = defined.find_factory_by_names(factory.names)
57
+
58
+ while possible_owner
59
+ if (trait = possible_owner.traits.find { |t| t.name == trait_name })
60
+ return [possible_owner, trait]
61
+ end
62
+ possible_owner = defined.find_factory_by_names([possible_owner.parent_name])
63
+ end
64
+ end
71
65
 
72
- used.factories.each do |factory|
73
- factory.trait_names.each do |trait_name|
74
- possible_owner_name = factory.name
75
66
 
76
- while possible_owner_name
77
- break if defined.find_factory_by_names(possible_owner_name).trait_names.include?(trait_name)
78
- possible_owner_name = defined.find_factory_by_names(possible_owner_name).parent_name
79
- end
67
+ [nil, defined.find_trait_by_name(trait_name)]
68
+ end
80
69
 
81
- if possible_owner_name
82
- factory = collection.find_factory_by_names(possible_owner_name)
83
- factory ||= collection.add(FactoryTrace::Structures::Factory.new(possible_owner_name, nil, [], []))
70
+ # @param [FactoryTrace::Structures::Factory] factory
71
+ # @param [FactoryTrace::Structures::Collection] collection
72
+ # @param [Symbol] status
73
+ def self.mark_factory(factory, collection, status:)
74
+ return if factory.has_prioritized_status?(status)
84
75
 
85
- factory.trait_names << trait_name unless factory.trait_names.include?(trait_name)
86
- else
87
- collection.add(FactoryTrace::Structures::Trait.new(trait_name, nil))
88
- end
89
- end
76
+ factory.status = status
77
+ if (parent = collection.find_factory_by_names([factory.parent_name]))
78
+ mark_factory(parent, collection, status: :indirectly_used)
90
79
  end
91
-
92
- collection
80
+ mark_declarations(factory.declaration_names, factory, collection, status: :indirectly_used)
93
81
  end
94
82
 
95
- # Returns a hash:
96
- # - key is factory name
97
- # - value is factory names which where used and are children of the factory
98
- #
99
- # @param [FactoryTrace::Structures::Collection] defined
100
- # @param [FactoryTrace::Structures::Collection] used
101
- #
102
- # @return [Hash<String, Array<String>]
103
- def self.used_child_factories(defined, used)
104
- hash = {}
83
+ # @param [FactoryTrace::Structures::Trait] trait
84
+ # @param [FactoryTrace::Structures::Factory|nil] factory which trait belongs to
85
+ # @param [FactoryTrace::Structures::Collection] collection
86
+ # @param [Symbol] status
87
+ def self.mark_trait(trait, factory, collection, status:)
88
+ return if trait.has_prioritized_status?(status)
105
89
 
106
- used.factories.each do |factory|
107
- parent_name = defined.find(factory).parent_name
90
+ trait.status = status
91
+ mark_declarations(trait.declaration_names, factory, collection, status: :indirectly_used)
92
+ end
108
93
 
109
- if parent_name
110
- hash[parent_name] ||= []
111
- hash[parent_name] << factory.name
94
+ # @param [Array<String>] declaration_names
95
+ # @param [FactoryTrace::Structures::Factory|nil] factory
96
+ # @param [FactoryTrace::Structures::Collection] collection
97
+ # @param [Symbol] status
98
+ def self.mark_declarations(declaration_names, factory, collection, status:)
99
+ declaration_names.each do |declaration_name|
100
+ if (declaration_factory = collection.find_factory_by_names([declaration_name]))
101
+ mark_factory(declaration_factory, collection, status: status)
102
+ elsif (declaration_factory, declaration_trait = defined_trait_by_name(collection, factory, declaration_name))
103
+ mark_trait(declaration_trait, declaration_factory, collection, status: status)
112
104
  end
113
105
  end
114
-
115
- hash
116
106
  end
117
107
  end
118
108
  end
@@ -13,8 +13,8 @@ module FactoryTrace
13
13
  File.open(file_name, 'r') do |file|
14
14
  data = new(file, configuration: configuration).read
15
15
 
16
- result.each do |key, collection|
17
- collection.merge!(data[key])
16
+ [:defined, :used].each do |key|
17
+ result[key].merge!(data[key])
18
18
  end
19
19
  end
20
20
  end
@@ -41,15 +41,28 @@ module FactoryTrace
41
41
 
42
42
  private
43
43
 
44
+ def parse_trait(hash)
45
+ FactoryTrace::Structures::Trait.new(hash['name'], declaration_names: hash['declaration_names'])
46
+ end
47
+
48
+ def parse_factory(hash)
49
+ FactoryTrace::Structures::Factory.new(
50
+ hash['names'],
51
+ hash['traits'].map(&method(:parse_trait)),
52
+ parent_name: hash['parent_name'],
53
+ declaration_names: hash['declaration_names']
54
+ )
55
+ end
56
+
44
57
  def parse_collection(hash)
45
58
  collection = FactoryTrace::Structures::Collection.new
46
59
 
47
60
  hash['factories'].each do |h|
48
- collection.add(FactoryTrace::Structures::Factory.new(h['name'], h['parent_name'], h['trait_names'], h['alias_names']))
61
+ collection.add(parse_factory(h))
49
62
  end
50
63
 
51
64
  hash['traits'].each do |h|
52
- collection.add(FactoryTrace::Structures::Trait.new(h['name'], h['owner_name']))
65
+ collection.add(parse_trait(h))
53
66
  end
54
67
 
55
68
  collection
@@ -10,15 +10,13 @@ module FactoryTrace
10
10
  @traits = traits
11
11
  end
12
12
 
13
- # @param [FactoryTrace::Structures::Factory, FactoryTrace::Structures::Trait] element
13
+ # @param [FactoryTrace::Structures::Factory|FactoryTrace::Structures::Trait] element
14
14
  #
15
- # @return [FactoryTrace::Structures::Factory, FactoryTrace::Structures::Trait]
15
+ # @return [FactoryTrace::Structures::Factory|FactoryTrace::Structures::Trait]
16
16
  def add(element)
17
17
  case element
18
18
  when FactoryTrace::Structures::Factory then factories << element
19
19
  when FactoryTrace::Structures::Trait then traits << element
20
- else
21
- fail "Unknown element: #{element.inspect}"
22
20
  end
23
21
 
24
22
  element
@@ -27,61 +25,47 @@ module FactoryTrace
27
25
  # @param [Array<String>] names
28
26
  #
29
27
  # @return [FactoryTrace::Structures::Factory|nil]
30
- def find_factory_by_names(*names)
31
- factories.find { |factory| names.include?(factory.name) || (names & factory.alias_names).size > 0 }
28
+ def find_factory_by_names(names)
29
+ factories.find { |factory| (names & factory.names).size > 0 }
32
30
  end
33
31
 
34
- # @param [Array<String>] names
32
+ # @param [String] name
35
33
  #
36
34
  # @return [FactoryTrace::Structures::Trait|nil]
37
- def find_trait_by_names(*names)
38
- traits.find { |trait| names.include?(trait.name) }
35
+ def find_trait_by_name(name)
36
+ traits.find { |trait| name == trait.name }
39
37
  end
40
38
 
41
- # @param [FactoryTrace::Structures::Factory|FactoryTrace::Structures::Trait]
42
- #
43
- # @return [FactoryTrace::Structures::Factory|FactoryTrace::Structures::Trait]
44
- def find(element)
45
- case element
46
- when FactoryTrace::Structures::Factory then find_factory_by_names(element.name, *element.alias_names)
47
- when FactoryTrace::Structures::Trait then find_trait_by_names(element.name)
48
- else
49
- fail "Unknown element: #{element.inspect}"
50
- end
39
+ # @return [Hash]
40
+ def to_h
41
+ {
42
+ factories: factories.map(&:to_h),
43
+ traits: traits.map(&:to_h)
44
+ }
51
45
  end
52
46
 
53
47
  # Merge passed collection into self
54
48
  #
55
49
  # @param [FactoryTrace::Structures::Collection]
56
- #
57
- # @return [FactoryTrace::Structures::Collection]
58
50
  def merge!(collection)
59
51
  collection.factories.each do |factory|
60
- if (persisted = find(factory))
52
+ if (persisted = find_factory_by_names(factory.names))
61
53
  persisted.merge!(factory)
62
54
  else
63
- add(FactoryTrace::Structures::Factory.new(factory.name, factory.parent_name, factory.trait_names, factory.alias_names))
55
+ add(factory)
64
56
  end
65
57
  end
66
58
 
67
59
  collection.traits.each do |trait|
68
- add(FactoryTrace::Structures::Trait.new(trait.name, trait.owner_name)) unless find(trait)
60
+ add(trait) unless find_trait_by_name(trait.name)
69
61
  end
70
62
  end
71
63
 
72
- # @return [Hash]
73
- def to_h
74
- {
75
- factories: factories.map(&:to_h),
76
- traits: traits.map(&:to_h)
77
- }
78
- end
79
-
80
64
  # Total number of factories and traits
81
65
  #
82
66
  # @return [Integer]
83
67
  def total
84
- traits.size + factories.size + factories.sum { |factory| factory.trait_names.size }
68
+ traits.size + factories.size + factories.sum { |factory| factory.traits.size }
85
69
  end
86
70
 
87
71
  # @return [Boolean]
@@ -1,46 +1,48 @@
1
1
  module FactoryTrace
2
2
  module Structures
3
3
  class Factory
4
- attr_reader :name, :parent_name, :trait_names, :alias_names
4
+ include Helpers::Statusable
5
5
 
6
- # @param [String] name
7
- # @param [String, nil] parent_name
8
- # @param [Array<String>] trait_names
9
- # @param [Array<String>] alias_names
10
- def initialize(name, parent_name, trait_names, alias_names)
11
- @name = name
6
+ attr_reader :names, :parent_name, :traits, :declaration_names
7
+
8
+ # @param [Array<String>] names
9
+ # @param [Array<FactoryTrace::Structure::Trait>] traits
10
+ # @param [String|nil] parent_name
11
+ # @param [Array<String>] declaration_names
12
+ def initialize(names, traits, parent_name: nil, declaration_names: [])
13
+ @names = names
14
+ @traits = traits
12
15
  @parent_name = parent_name
13
- @trait_names = trait_names
14
- @alias_names = alias_names
16
+ @declaration_names = declaration_names
15
17
  end
16
18
 
17
- # @return [Hash<Symbol, String>]
19
+ # @return [Hash<Symbol, Object>]
18
20
  def to_h
19
21
  {
20
- name: name,
22
+ names: names,
23
+ traits: traits.map(&:to_h),
21
24
  parent_name: parent_name,
22
- trait_names: trait_names,
23
- alias_names: alias_names
25
+ declaration_names: declaration_names
24
26
  }
25
27
  end
26
28
 
27
29
  # Merge passed factory into self
28
30
  #
29
31
  # @param [FactoryTrace::Structures::Factory]
30
- #
31
- # @return [FactoryTrace::Structures::Factory]
32
32
  def merge!(factory)
33
- @trait_names = (trait_names + factory.trait_names).uniq
33
+ factory.traits.each do |trait|
34
+ traits << trait unless traits.any? { |t| t.name == trait.name }
35
+ end
34
36
  end
35
37
 
36
38
  # @return [Boolean]
37
39
  def ==(factory)
38
40
  return false unless factory.is_a?(FactoryTrace::Structures::Factory)
39
41
 
40
- name == factory.name &&
42
+ names == factory.names &&
43
+ traits == factory.traits &&
41
44
  parent_name == factory.parent_name &&
42
- trait_names == factory.trait_names &&
43
- alias_names == factory.alias_names
45
+ declaration_names == factory.declaration_names
44
46
  end
45
47
  end
46
48
  end
@@ -1,20 +1,22 @@
1
1
  module FactoryTrace
2
2
  module Structures
3
3
  class Trait
4
- attr_reader :name, :owner_name
4
+ include Helpers::Statusable
5
+
6
+ attr_reader :name, :declaration_names
5
7
 
6
8
  # @param [String] name
7
- # @param [String, nil] owner_name
8
- def initialize(name, owner_name)
9
+ # @param [Array<String>] declaration_names
10
+ def initialize(name, declaration_names: [])
9
11
  @name = name
10
- @owner_name = owner_name
12
+ @declaration_names = declaration_names
11
13
  end
12
14
 
13
- # @return [Hash<Symbol, String>]
15
+ # @return [Hash<Symbol, Object>]
14
16
  def to_h
15
17
  {
16
18
  name: name,
17
- owner_name: owner_name
19
+ declaration_names: declaration_names
18
20
  }
19
21
  end
20
22
 
@@ -22,7 +24,7 @@ module FactoryTrace
22
24
  def ==(trait)
23
25
  return false unless trait.is_a?(FactoryTrace::Structures::Trait)
24
26
 
25
- name == trait.name && owner_name == trait.owner_name
27
+ name == trait.name && declaration_names == trait.declaration_names
26
28
  end
27
29
  end
28
30
  end
@@ -1,3 +1,3 @@
1
1
  module FactoryTrace
2
- VERSION = '0.2.4'
2
+ VERSION = '0.3.0'
3
3
  end
@@ -40,8 +40,8 @@ module FactoryTrace
40
40
  colorize(total_color, "total number of unique #{humanize_code(result[:code])} factories & traits: #{result[:value]}")
41
41
  when result[:factory_name] && result[:trait_name]
42
42
  "#{humanize_code(result[:code])} trait #{colorize(:blue, result[:trait_name])} of factory #{colorize(:blue, result[:factory_name])}"
43
- when result[:factory_name] && result[:child_factories_names]
44
- "#{humanize_code(result[:code])} factory #{colorize(:blue, result[:factory_name])} as parent for #{list(result[:child_factories_names])}"
43
+ when result[:factory_name] && result[:factories_names]
44
+ "#{humanize_code(result[:code])} factory #{colorize(:blue, result[:factory_name])} as parent for #{list(result[:factories_names])}"
45
45
  when result[:factory_name]
46
46
  "#{humanize_code(result[:code])} factory #{colorize(:blue, result[:factory_name])}"
47
47
  else
data/lib/factory_trace.rb CHANGED
@@ -6,6 +6,7 @@ require 'set'
6
6
  require 'factory_trace/configuration'
7
7
  require 'factory_trace/version'
8
8
  require 'factory_trace/helpers/converter'
9
+ require 'factory_trace/helpers/statusable'
9
10
  require 'factory_trace/tracker'
10
11
 
11
12
  require 'factory_trace/structures/factory'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: factory_trace
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - djezzzl
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-06-02 00:00:00.000000000 Z
11
+ date: 2019-06-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: factory_bot
@@ -78,6 +78,7 @@ files:
78
78
  - lib/factory_trace.rb
79
79
  - lib/factory_trace/configuration.rb
80
80
  - lib/factory_trace/helpers/converter.rb
81
+ - lib/factory_trace/helpers/statusable.rb
81
82
  - lib/factory_trace/preprocessors/extract_defined.rb
82
83
  - lib/factory_trace/preprocessors/extract_used.rb
83
84
  - lib/factory_trace/processors/find_unused.rb