factory_trace 0.2.4 → 0.3.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 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