hashira 0.4.0 → 0.5.1

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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +86 -0
  3. data/README.md +90 -30
  4. data/lib/hashira/analysis/finding.rb +2 -2
  5. data/lib/hashira/analysis/syntax.rb +6 -2
  6. data/lib/hashira/churn.rb +1 -1
  7. data/lib/hashira/ci/ratchet.rb +5 -9
  8. data/lib/hashira/cli/command_line.rb +10 -49
  9. data/lib/hashira/cli/fail_on.rb +9 -5
  10. data/lib/hashira/cli/flag.rb +29 -0
  11. data/lib/hashira/cli/flags.rb +50 -0
  12. data/lib/hashira/cli/format.rb +13 -0
  13. data/lib/hashira/cli/options.rb +2 -0
  14. data/lib/hashira/cli/run.rb +8 -4
  15. data/lib/hashira/cli/usage.rb +20 -21
  16. data/lib/hashira/cli.rb +1 -1
  17. data/lib/hashira/complexity/boolean_run.rb +5 -3
  18. data/lib/hashira/complexity/cognitive_score.rb +21 -14
  19. data/lib/hashira/complexity/if_chain.rb +14 -14
  20. data/lib/hashira/complexity/method_finding.rb +4 -19
  21. data/lib/hashira/complexity/rescue_scan.rb +9 -9
  22. data/lib/hashira/complexity/{analyzer.rb → scores.rb} +6 -5
  23. data/lib/hashira/coupling/audiences.rb +49 -0
  24. data/lib/hashira/{analysis → coupling}/catalog.rb +3 -3
  25. data/lib/hashira/{analysis → coupling}/census.rb +17 -8
  26. data/lib/hashira/{analysis → coupling}/constant_registry.rb +11 -6
  27. data/lib/hashira/coupling/cycle_findings.rb +31 -0
  28. data/lib/hashira/{analysis → coupling}/cycle_search.rb +1 -1
  29. data/lib/hashira/{analysis → coupling}/cycles.rb +2 -2
  30. data/lib/hashira/{analysis → coupling}/definition.rb +6 -2
  31. data/lib/hashira/{analysis → coupling}/definitions.rb +5 -2
  32. data/lib/hashira/{analysis → coupling}/edge.rb +1 -1
  33. data/lib/hashira/{analysis → coupling}/edge_map.rb +10 -10
  34. data/lib/hashira/{analysis → coupling}/folder_placement.rb +2 -2
  35. data/lib/hashira/{analysis → coupling}/folding.rb +4 -2
  36. data/lib/hashira/{analysis → coupling}/graph.rb +18 -8
  37. data/lib/hashira/{analysis → coupling}/metric.rb +1 -1
  38. data/lib/hashira/coupling/mixed_audience_findings.rb +32 -0
  39. data/lib/hashira/{analysis → coupling}/namespace_placement.rb +3 -3
  40. data/lib/hashira/{analysis → coupling}/namespace_prefix.rb +1 -1
  41. data/lib/hashira/{analysis → coupling}/naming.rb +2 -2
  42. data/lib/hashira/{analysis → coupling}/no_folding.rb +1 -1
  43. data/lib/hashira/{analysis → coupling}/placement.rb +3 -3
  44. data/lib/hashira/coupling/references.rb +55 -0
  45. data/lib/hashira/coupling/report.rb +28 -0
  46. data/lib/hashira/coupling/roll_call.rb +45 -0
  47. data/lib/hashira/coupling/roll_call_findings.rb +30 -0
  48. data/lib/hashira/{analysis → coupling}/roster.rb +6 -2
  49. data/lib/hashira/{analysis → coupling}/rule.rb +1 -1
  50. data/lib/hashira/{analysis/resolver.rb → coupling/scope.rb} +7 -3
  51. data/lib/hashira/{analysis → coupling}/sdp_check.rb +1 -1
  52. data/lib/hashira/coupling/sdp_violation_findings.rb +25 -0
  53. data/lib/hashira/coupling/wide_edge_findings.rb +25 -0
  54. data/lib/hashira/coupling/words.rb +29 -0
  55. data/lib/hashira/diagram/{renderer.rb → source.rb} +2 -2
  56. data/lib/hashira/duplication/{analyzer.rb → clones.rb} +3 -3
  57. data/lib/hashira/duplication/{clusterer.rb → clusters.rb} +3 -3
  58. data/lib/hashira/duplication/delta.rb +6 -14
  59. data/lib/hashira/duplication/duplication_finding.rb +8 -10
  60. data/lib/hashira/duplication/{extractor.rb → harvest.rb} +1 -1
  61. data/lib/hashira/duplication/sequence.rb +3 -1
  62. data/lib/hashira/duplication/similarity.rb +5 -1
  63. data/lib/hashira/duplication/variance.rb +3 -3
  64. data/lib/hashira/hotspots/rollup.rb +1 -1
  65. data/lib/hashira/pipeline.rb +18 -10
  66. data/lib/hashira/report/complexity_table.rb +1 -1
  67. data/lib/hashira/report/finding_lines.rb +1 -1
  68. data/lib/hashira/report/json.rb +5 -3
  69. data/lib/hashira/report/phrases.rb +98 -0
  70. data/lib/hashira/report/smell_phrases.rb +68 -0
  71. data/lib/hashira/smells/census.rb +32 -0
  72. data/lib/hashira/smells/check.rb +34 -0
  73. data/lib/hashira/smells/conditions.rb +44 -0
  74. data/lib/hashira/smells/contexts.rb +64 -0
  75. data/lib/hashira/smells/control_parameter.rb +22 -0
  76. data/lib/hashira/smells/data_clump.rb +32 -0
  77. data/lib/hashira/smells/duplicate_method_call.rb +54 -0
  78. data/lib/hashira/smells/feature_envy.rb +17 -0
  79. data/lib/hashira/smells/instance_variable_assumption.rb +46 -0
  80. data/lib/hashira/smells/manual_dispatch.rb +16 -0
  81. data/lib/hashira/smells/module_initialize.rb +11 -0
  82. data/lib/hashira/smells/nil_check.rb +32 -0
  83. data/lib/hashira/smells/param_check.rb +51 -0
  84. data/lib/hashira/smells/refs.rb +53 -0
  85. data/lib/hashira/smells/repeated_conditional.rb +31 -0
  86. data/lib/hashira/smells/report.rb +34 -0
  87. data/lib/hashira/smells/scope.rb +29 -0
  88. data/lib/hashira/smells/too_many_instance_variables.rb +26 -0
  89. data/lib/hashira/smells/utility_function.rb +13 -0
  90. data/lib/hashira/smells/visibility.rb +64 -0
  91. data/lib/hashira/version.rb +1 -1
  92. data/lib/hashira.rb +68 -30
  93. metadata +63 -31
  94. data/lib/hashira/analysis/cycle_findings.rb +0 -38
  95. data/lib/hashira/analysis/references.rb +0 -40
  96. data/lib/hashira/analysis/sdp_violation_findings.rb +0 -29
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "prism"
4
+
5
+ class Hashira::Smells::ManualDispatch < Hashira::Smells::Check
6
+ private
7
+
8
+ def smelly? = sightings.any?
9
+
10
+ def sightings
11
+ @sightings ||= Hashira::Smells::Scope.inside(subject.node)
12
+ .select { it.is_a?(Prism::CallNode) && it.name == :respond_to? }
13
+ end
14
+
15
+ def detail = { site: spots(sightings) }
16
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Hashira::Smells::ModuleInitialize < Hashira::Smells::Check
4
+ def self.judge? = true
5
+
6
+ private
7
+
8
+ def smelly? = subject.kind == :module && flagged
9
+
10
+ def flagged = subject.owned.any? { it.node.name == :initialize }
11
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "prism"
4
+
5
+ class Hashira::Smells::NilCheck < Hashira::Smells::Check
6
+ EQUALITY = %i[== ===].freeze
7
+
8
+ private
9
+
10
+ def smelly? = checks.any?
11
+
12
+ def checks = @checks ||= Hashira::Smells::Scope.inside(subject.node).select { check?(it) }
13
+
14
+ def check?(node)
15
+ case node
16
+ when Prism::CallNode then query?(node)
17
+ when Prism::WhenNode then node.conditions.any?(Prism::NilNode)
18
+ else false
19
+ end
20
+ end
21
+
22
+ def query?(node)
23
+ name = node.name
24
+ name == :nil? || (EQUALITY.include?(name) && equated?(node))
25
+ end
26
+
27
+ def equated?(node) = sides(node).any?(Prism::NilNode)
28
+
29
+ def sides(node) = [node.receiver] + (node.arguments&.arguments || [])
30
+
31
+ def detail = { site: spots(checks) }
32
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "prism"
4
+
5
+ class Hashira::Smells::ParamCheck
6
+ COMPARISONS = %i[== != =~].freeze
7
+
8
+ def initialize(node, name)
9
+ @node = node
10
+ @name = name
11
+ end
12
+
13
+ def matches
14
+ return [] if legitimate?
15
+ nested.flat_map(&:matches) + tested
16
+ end
17
+
18
+ def legitimate?
19
+ absolved? || working? || nested.any?(&:legitimate?)
20
+ end
21
+
22
+ private
23
+
24
+ def nested
25
+ @nested ||= Hashira::Smells::Conditions.nested(branches).map { self.class.new(it, @name) }
26
+ end
27
+
28
+ def branches = Hashira::Smells::Conditions.branches(@node)
29
+
30
+ def predicate
31
+ @predicate ||= spread(Hashira::Smells::Conditions.condition(@node))
32
+ end
33
+
34
+ def spread(condition) = condition ? Hashira::Analysis::NodeWalk.collect(condition) : []
35
+
36
+ def tested = reads(predicate)
37
+
38
+ def working?
39
+ reads(branches.compact.flat_map { Hashira::Smells::Conditions.plain(it) }).any?
40
+ end
41
+
42
+ def absolved?
43
+ predicate.grep(Prism::CallNode).any? { absolves?(it) }
44
+ end
45
+
46
+ def absolves?(call)
47
+ !COMPARISONS.include?(call.name) && reads(Hashira::Analysis::NodeWalk.collect(call)).any?
48
+ end
49
+
50
+ def reads(nodes) = nodes.grep(Prism::LocalVariableReadNode).select { it.name == @name }
51
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "prism"
4
+
5
+ class Hashira::Smells::Refs
6
+ SELVES = [
7
+ Prism::SelfNode, Prism::SuperNode, Prism::ForwardingSuperNode,
8
+ Prism::InstanceVariableReadNode, Prism::InstanceVariableWriteNode,
9
+ Prism::InstanceVariableOrWriteNode, Prism::InstanceVariableAndWriteNode,
10
+ Prism::InstanceVariableOperatorWriteNode, Prism::InstanceVariableTargetNode
11
+ ].freeze
12
+
13
+ def initialize(def_node)
14
+ @tallies = {}
15
+ Hashira::Smells::Scope.inside(def_node).each { record(it) }
16
+ end
17
+
18
+ def ego = lines(:self).size
19
+
20
+ def lines(name) = @tallies.fetch(name, [])
21
+
22
+ def envious
23
+ peak = @tallies.values.map(&:size).max
24
+ names = @tallies.filter_map { |name, sightings| name if sightings.size == peak }
25
+ names.include?(:self) ? [] : names
26
+ end
27
+
28
+ private
29
+
30
+ def record(node)
31
+ return note(:self, node) if selfish?(node)
32
+ case node
33
+ when Prism::CallNode then named(node)
34
+ when Prism::LocalVariableOperatorWriteNode then note(node.name, node)
35
+ end
36
+ end
37
+
38
+ def selfish?(node)
39
+ SELVES.include?(node.class) || implicit?(node)
40
+ end
41
+
42
+ def implicit?(node) = node.is_a?(Prism::CallNode) && !node.receiver
43
+
44
+ def named(node)
45
+ case (receiver = node.receiver)
46
+ when Prism::SelfNode then note(:self, node)
47
+ when Prism::LocalVariableReadNode, Prism::LocalVariableWriteNode
48
+ note(receiver.name, node) unless node.name == :new
49
+ end
50
+ end
51
+
52
+ def note(name, node) = (@tallies[name] ||= []) << node.location.start_line
53
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "prism"
4
+
5
+ class Hashira::Smells::RepeatedConditional < Hashira::Smells::Check
6
+ LIMIT = 2
7
+
8
+ def self.judge? = true
9
+
10
+ private
11
+
12
+ def smelly? = subject.kind == :class && repeats.any?
13
+
14
+ def repeats
15
+ @repeats ||= predicates.group_by(&:slice).except("block_given?").select { |_test, nodes| nodes.size > LIMIT }
16
+ end
17
+
18
+ def predicates = Hashira::Smells::Scope.sweep(subject.node).filter_map { predicate(it) }
19
+
20
+ def predicate(node)
21
+ node.predicate if node.is_a?(Prism::IfNode) || node.is_a?(Prism::UnlessNode) || node.is_a?(Prism::CaseNode)
22
+ end
23
+
24
+ def detail = { site:, count: repeats.values.map(&:size).max }
25
+
26
+ def evidence = repeats.map { |test, nodes| row(test, nodes) }
27
+
28
+ def row(test, nodes)
29
+ "#{test} × #{nodes.size} (lines #{nodes.map { |node| node.location.start_line }.join(", ")})"
30
+ end
31
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "check"
4
+ require_relative "control_parameter"
5
+ require_relative "data_clump"
6
+ require_relative "duplicate_method_call"
7
+ require_relative "feature_envy"
8
+ require_relative "instance_variable_assumption"
9
+ require_relative "manual_dispatch"
10
+ require_relative "module_initialize"
11
+ require_relative "nil_check"
12
+ require_relative "repeated_conditional"
13
+ require_relative "too_many_instance_variables"
14
+ require_relative "utility_function"
15
+
16
+ class Hashira::Smells::Report
17
+ CHECKS = Hashira::Smells::Check.subclasses.sort_by(&:name).freeze
18
+
19
+ JUDGES = CHECKS.select(&:judge?).freeze
20
+
21
+ PROBES = CHECKS.reject(&:judge?).freeze
22
+
23
+ def initialize(project, trees)
24
+ @types = Hashira::Smells::Census.new(project, trees).types
25
+ end
26
+
27
+ def findings = @findings ||= sniff(@types, JUDGES) + sniff(@types.flat_map(&:defs), PROBES)
28
+
29
+ private
30
+
31
+ def sniff(subjects, checks) = subjects.flat_map { |subject| verdicts(subject, checks) }
32
+
33
+ def verdicts(subject, checks) = checks.filter_map { |check| check.new(subject).finding }
34
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "prism"
4
+
5
+ module Hashira::Smells::Scope
6
+ TYPES = [Prism::ClassNode, Prism::ModuleNode, Prism::SingletonClassNode].freeze
7
+
8
+ FENCES = (TYPES + [Prism::DefNode]).freeze
9
+
10
+ module_function
11
+
12
+ def inside(node) = below(node, FENCES)
13
+
14
+ def sweep(node) = below(node, TYPES)
15
+
16
+ def below(root, fences)
17
+ found = []
18
+ visit(root, fences) { found << it }
19
+ found
20
+ end
21
+
22
+ def visit(root, fences, &)
23
+ root.compact_child_nodes.each do |child|
24
+ next if fences.include?(child.class)
25
+ yield(child)
26
+ visit(child, fences, &)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "prism"
4
+
5
+ class Hashira::Smells::TooManyInstanceVariables < Hashira::Smells::Check
6
+ LIMIT = 4
7
+
8
+ COUNTED = [
9
+ Prism::InstanceVariableWriteNode, Prism::InstanceVariableAndWriteNode,
10
+ Prism::InstanceVariableOperatorWriteNode, Prism::InstanceVariableTargetNode
11
+ ].freeze
12
+
13
+ def self.judge? = true
14
+
15
+ private
16
+
17
+ def smelly? = subject.kind == :class && names.size > LIMIT
18
+
19
+ def names
20
+ @names ||= Hashira::Smells::Scope.sweep(subject.node).select { COUNTED.include?(it.class) }.map(&:name).uniq.sort
21
+ end
22
+
23
+ def detail = { site:, count: names.size }
24
+
25
+ def evidence = names.map(&:to_s)
26
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "prism"
4
+
5
+ class Hashira::Smells::UtilityFunction < Hashira::Smells::Check
6
+ private
7
+
8
+ def smelly? = subject.public? && calls? && refs.ego.zero?
9
+
10
+ def refs = Hashira::Smells::Refs.new(subject.node)
11
+
12
+ def calls? = Hashira::Smells::Scope.inside(subject.node).any?(Prism::CallNode)
13
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "prism"
4
+
5
+ class Hashira::Smells::Visibility
6
+ MARKERS = %i[public private protected module_function].freeze
7
+
8
+ def initialize(type_node)
9
+ @section = :public
10
+ @overrides = {}
11
+ @found = []
12
+ scan(statements(type_node))
13
+ end
14
+
15
+ def entries = @found.map { |node, section| [node, @overrides.fetch(node.name, section)] }
16
+
17
+ private
18
+
19
+ def statements(node)
20
+ body = node.body
21
+ body.is_a?(Prism::StatementsNode) ? body.body : []
22
+ end
23
+
24
+ def scan(nodes) = nodes.each { classify(it) }
25
+
26
+ def classify(node)
27
+ case node
28
+ when Prism::DefNode then @found << [node, @section]
29
+ when Prism::CallNode then heed(node)
30
+ else descend(node)
31
+ end
32
+ end
33
+
34
+ def descend(node)
35
+ case node
36
+ when Prism::SingletonClassNode then shadow(node)
37
+ when Prism::ClassNode, Prism::ModuleNode, Prism::ConstantWriteNode then nil
38
+ else scan(node.compact_child_nodes)
39
+ end
40
+ end
41
+
42
+ def heed(node)
43
+ bare?(node) ? switch(node.name, node.arguments) : scan(node.compact_child_nodes)
44
+ end
45
+
46
+ def bare?(node) = MARKERS.include?(node.name) && !node.receiver
47
+
48
+ def switch(name, arguments)
49
+ arguments ? tag(name, arguments.arguments) : (@section = name)
50
+ end
51
+
52
+ def tag(section, arguments) = arguments.each { note(it, section) }
53
+
54
+ def note(argument, section)
55
+ case argument
56
+ when Prism::DefNode then @found << [argument, section]
57
+ when Prism::SymbolNode then @overrides[argument.unescaped.to_sym] = section
58
+ end
59
+ end
60
+
61
+ def shadow(node)
62
+ statements(node).each { @found << [it, :singleton] if it.is_a?(Prism::DefNode) }
63
+ end
64
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Hashira
4
- VERSION = "0.4.0"
4
+ VERSION = "0.5.1"
5
5
  end
data/lib/hashira.rb CHANGED
@@ -7,6 +7,9 @@ module Hashira
7
7
  module CI
8
8
  end
9
9
 
10
+ module Coupling
11
+ end
12
+
10
13
  module Complexity
11
14
  end
12
15
 
@@ -21,35 +24,13 @@ module Hashira
21
24
 
22
25
  module Report
23
26
  end
27
+
28
+ module Smells
29
+ end
24
30
  end
25
31
 
26
- require_relative "hashira/analysis/catalog"
27
- require_relative "hashira/analysis/census"
28
- require_relative "hashira/analysis/constant_registry"
29
- require_relative "hashira/analysis/cycle_findings"
30
- require_relative "hashira/analysis/cycle_search"
31
- require_relative "hashira/analysis/cycles"
32
- require_relative "hashira/analysis/definition"
33
- require_relative "hashira/analysis/definitions"
34
- require_relative "hashira/analysis/edge"
35
- require_relative "hashira/analysis/edge_map"
36
32
  require_relative "hashira/analysis/finding"
37
- require_relative "hashira/analysis/folder_placement"
38
- require_relative "hashira/analysis/folding"
39
- require_relative "hashira/analysis/graph"
40
- require_relative "hashira/analysis/metric"
41
- require_relative "hashira/analysis/namespace_placement"
42
- require_relative "hashira/analysis/namespace_prefix"
43
- require_relative "hashira/analysis/naming"
44
- require_relative "hashira/analysis/no_folding"
45
33
  require_relative "hashira/analysis/node_walk"
46
- require_relative "hashira/analysis/placement"
47
- require_relative "hashira/analysis/references"
48
- require_relative "hashira/analysis/resolver"
49
- require_relative "hashira/analysis/roster"
50
- require_relative "hashira/analysis/rule"
51
- require_relative "hashira/analysis/sdp_check"
52
- require_relative "hashira/analysis/sdp_violation_findings"
53
34
  require_relative "hashira/analysis/syntax"
54
35
  require_relative "hashira/analysis/type_walk"
55
36
  require_relative "hashira/churn"
@@ -66,12 +47,14 @@ require_relative "hashira/cli"
66
47
  require_relative "hashira/cli/arguments"
67
48
  require_relative "hashira/cli/command_line"
68
49
  require_relative "hashira/cli/fail_on"
50
+ require_relative "hashira/cli/flag"
51
+ require_relative "hashira/cli/flags"
52
+ require_relative "hashira/cli/format"
69
53
  require_relative "hashira/cli/options"
70
54
  require_relative "hashira/cli/package_by"
71
55
  require_relative "hashira/cli/run"
72
56
  require_relative "hashira/cli/skip"
73
57
  require_relative "hashira/cli/usage"
74
- require_relative "hashira/complexity/analyzer"
75
58
  require_relative "hashira/complexity/boolean_run"
76
59
  require_relative "hashira/complexity/cognitive_score"
77
60
  require_relative "hashira/complexity/if_chain"
@@ -79,17 +62,50 @@ require_relative "hashira/complexity/method_finding"
79
62
  require_relative "hashira/complexity/method_score"
80
63
  require_relative "hashira/complexity/rescue_scan"
81
64
  require_relative "hashira/complexity/rollup"
65
+ require_relative "hashira/complexity/scores"
66
+ require_relative "hashira/coupling/audiences"
67
+ require_relative "hashira/coupling/catalog"
68
+ require_relative "hashira/coupling/census"
69
+ require_relative "hashira/coupling/constant_registry"
70
+ require_relative "hashira/coupling/cycle_findings"
71
+ require_relative "hashira/coupling/cycle_search"
72
+ require_relative "hashira/coupling/cycles"
73
+ require_relative "hashira/coupling/definition"
74
+ require_relative "hashira/coupling/definitions"
75
+ require_relative "hashira/coupling/edge"
76
+ require_relative "hashira/coupling/edge_map"
77
+ require_relative "hashira/coupling/folder_placement"
78
+ require_relative "hashira/coupling/folding"
79
+ require_relative "hashira/coupling/graph"
80
+ require_relative "hashira/coupling/metric"
81
+ require_relative "hashira/coupling/mixed_audience_findings"
82
+ require_relative "hashira/coupling/namespace_placement"
83
+ require_relative "hashira/coupling/namespace_prefix"
84
+ require_relative "hashira/coupling/naming"
85
+ require_relative "hashira/coupling/no_folding"
86
+ require_relative "hashira/coupling/placement"
87
+ require_relative "hashira/coupling/references"
88
+ require_relative "hashira/coupling/report"
89
+ require_relative "hashira/coupling/roll_call"
90
+ require_relative "hashira/coupling/roll_call_findings"
91
+ require_relative "hashira/coupling/roster"
92
+ require_relative "hashira/coupling/rule"
93
+ require_relative "hashira/coupling/scope"
94
+ require_relative "hashira/coupling/sdp_check"
95
+ require_relative "hashira/coupling/sdp_violation_findings"
96
+ require_relative "hashira/coupling/wide_edge_findings"
97
+ require_relative "hashira/coupling/words"
82
98
  require_relative "hashira/diagram/dot"
83
99
  require_relative "hashira/diagram/mermaid"
84
- require_relative "hashira/diagram/renderer"
85
- require_relative "hashira/duplication/analyzer"
100
+ require_relative "hashira/diagram/source"
101
+ require_relative "hashira/duplication/clones"
86
102
  require_relative "hashira/duplication/cluster"
87
- require_relative "hashira/duplication/clusterer"
103
+ require_relative "hashira/duplication/clusters"
88
104
  require_relative "hashira/duplication/delta"
89
105
  require_relative "hashira/duplication/duplication_finding"
90
- require_relative "hashira/duplication/extractor"
91
106
  require_relative "hashira/duplication/fragment"
92
107
  require_relative "hashira/duplication/grouping"
108
+ require_relative "hashira/duplication/harvest"
93
109
  require_relative "hashira/duplication/index"
94
110
  require_relative "hashira/duplication/maximal"
95
111
  require_relative "hashira/duplication/near_miss"
@@ -109,6 +125,28 @@ require_relative "hashira/report/graph_payload"
109
125
  require_relative "hashira/report/hotspot_table"
110
126
  require_relative "hashira/report/json"
111
127
  require_relative "hashira/report/metrics_table"
128
+ require_relative "hashira/report/phrases"
129
+ require_relative "hashira/report/smell_phrases"
112
130
  require_relative "hashira/report/text"
113
131
  require_relative "hashira/report/view"
132
+ require_relative "hashira/smells/census"
133
+ require_relative "hashira/smells/check"
134
+ require_relative "hashira/smells/conditions"
135
+ require_relative "hashira/smells/contexts"
136
+ require_relative "hashira/smells/control_parameter"
137
+ require_relative "hashira/smells/data_clump"
138
+ require_relative "hashira/smells/duplicate_method_call"
139
+ require_relative "hashira/smells/feature_envy"
140
+ require_relative "hashira/smells/instance_variable_assumption"
141
+ require_relative "hashira/smells/manual_dispatch"
142
+ require_relative "hashira/smells/module_initialize"
143
+ require_relative "hashira/smells/nil_check"
144
+ require_relative "hashira/smells/param_check"
145
+ require_relative "hashira/smells/refs"
146
+ require_relative "hashira/smells/repeated_conditional"
147
+ require_relative "hashira/smells/report"
148
+ require_relative "hashira/smells/scope"
149
+ require_relative "hashira/smells/too_many_instance_variables"
150
+ require_relative "hashira/smells/utility_function"
151
+ require_relative "hashira/smells/visibility"
114
152
  require_relative "hashira/version"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hashira
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Giacomo GK
@@ -26,33 +26,8 @@ files:
26
26
  - README.md
27
27
  - exe/hashira
28
28
  - lib/hashira.rb
29
- - lib/hashira/analysis/catalog.rb
30
- - lib/hashira/analysis/census.rb
31
- - lib/hashira/analysis/constant_registry.rb
32
- - lib/hashira/analysis/cycle_findings.rb
33
- - lib/hashira/analysis/cycle_search.rb
34
- - lib/hashira/analysis/cycles.rb
35
- - lib/hashira/analysis/definition.rb
36
- - lib/hashira/analysis/definitions.rb
37
- - lib/hashira/analysis/edge.rb
38
- - lib/hashira/analysis/edge_map.rb
39
29
  - lib/hashira/analysis/finding.rb
40
- - lib/hashira/analysis/folder_placement.rb
41
- - lib/hashira/analysis/folding.rb
42
- - lib/hashira/analysis/graph.rb
43
- - lib/hashira/analysis/metric.rb
44
- - lib/hashira/analysis/namespace_placement.rb
45
- - lib/hashira/analysis/namespace_prefix.rb
46
- - lib/hashira/analysis/naming.rb
47
- - lib/hashira/analysis/no_folding.rb
48
30
  - lib/hashira/analysis/node_walk.rb
49
- - lib/hashira/analysis/placement.rb
50
- - lib/hashira/analysis/references.rb
51
- - lib/hashira/analysis/resolver.rb
52
- - lib/hashira/analysis/roster.rb
53
- - lib/hashira/analysis/rule.rb
54
- - lib/hashira/analysis/sdp_check.rb
55
- - lib/hashira/analysis/sdp_violation_findings.rb
56
31
  - lib/hashira/analysis/syntax.rb
57
32
  - lib/hashira/analysis/type_walk.rb
58
33
  - lib/hashira/churn.rb
@@ -69,12 +44,14 @@ files:
69
44
  - lib/hashira/cli/arguments.rb
70
45
  - lib/hashira/cli/command_line.rb
71
46
  - lib/hashira/cli/fail_on.rb
47
+ - lib/hashira/cli/flag.rb
48
+ - lib/hashira/cli/flags.rb
49
+ - lib/hashira/cli/format.rb
72
50
  - lib/hashira/cli/options.rb
73
51
  - lib/hashira/cli/package_by.rb
74
52
  - lib/hashira/cli/run.rb
75
53
  - lib/hashira/cli/skip.rb
76
54
  - lib/hashira/cli/usage.rb
77
- - lib/hashira/complexity/analyzer.rb
78
55
  - lib/hashira/complexity/boolean_run.rb
79
56
  - lib/hashira/complexity/cognitive_score.rb
80
57
  - lib/hashira/complexity/if_chain.rb
@@ -82,17 +59,50 @@ files:
82
59
  - lib/hashira/complexity/method_score.rb
83
60
  - lib/hashira/complexity/rescue_scan.rb
84
61
  - lib/hashira/complexity/rollup.rb
62
+ - lib/hashira/complexity/scores.rb
63
+ - lib/hashira/coupling/audiences.rb
64
+ - lib/hashira/coupling/catalog.rb
65
+ - lib/hashira/coupling/census.rb
66
+ - lib/hashira/coupling/constant_registry.rb
67
+ - lib/hashira/coupling/cycle_findings.rb
68
+ - lib/hashira/coupling/cycle_search.rb
69
+ - lib/hashira/coupling/cycles.rb
70
+ - lib/hashira/coupling/definition.rb
71
+ - lib/hashira/coupling/definitions.rb
72
+ - lib/hashira/coupling/edge.rb
73
+ - lib/hashira/coupling/edge_map.rb
74
+ - lib/hashira/coupling/folder_placement.rb
75
+ - lib/hashira/coupling/folding.rb
76
+ - lib/hashira/coupling/graph.rb
77
+ - lib/hashira/coupling/metric.rb
78
+ - lib/hashira/coupling/mixed_audience_findings.rb
79
+ - lib/hashira/coupling/namespace_placement.rb
80
+ - lib/hashira/coupling/namespace_prefix.rb
81
+ - lib/hashira/coupling/naming.rb
82
+ - lib/hashira/coupling/no_folding.rb
83
+ - lib/hashira/coupling/placement.rb
84
+ - lib/hashira/coupling/references.rb
85
+ - lib/hashira/coupling/report.rb
86
+ - lib/hashira/coupling/roll_call.rb
87
+ - lib/hashira/coupling/roll_call_findings.rb
88
+ - lib/hashira/coupling/roster.rb
89
+ - lib/hashira/coupling/rule.rb
90
+ - lib/hashira/coupling/scope.rb
91
+ - lib/hashira/coupling/sdp_check.rb
92
+ - lib/hashira/coupling/sdp_violation_findings.rb
93
+ - lib/hashira/coupling/wide_edge_findings.rb
94
+ - lib/hashira/coupling/words.rb
85
95
  - lib/hashira/diagram/dot.rb
86
96
  - lib/hashira/diagram/mermaid.rb
87
- - lib/hashira/diagram/renderer.rb
88
- - lib/hashira/duplication/analyzer.rb
97
+ - lib/hashira/diagram/source.rb
98
+ - lib/hashira/duplication/clones.rb
89
99
  - lib/hashira/duplication/cluster.rb
90
- - lib/hashira/duplication/clusterer.rb
100
+ - lib/hashira/duplication/clusters.rb
91
101
  - lib/hashira/duplication/delta.rb
92
102
  - lib/hashira/duplication/duplication_finding.rb
93
- - lib/hashira/duplication/extractor.rb
94
103
  - lib/hashira/duplication/fragment.rb
95
104
  - lib/hashira/duplication/grouping.rb
105
+ - lib/hashira/duplication/harvest.rb
96
106
  - lib/hashira/duplication/index.rb
97
107
  - lib/hashira/duplication/maximal.rb
98
108
  - lib/hashira/duplication/near_miss.rb
@@ -112,8 +122,30 @@ files:
112
122
  - lib/hashira/report/hotspot_table.rb
113
123
  - lib/hashira/report/json.rb
114
124
  - lib/hashira/report/metrics_table.rb
125
+ - lib/hashira/report/phrases.rb
126
+ - lib/hashira/report/smell_phrases.rb
115
127
  - lib/hashira/report/text.rb
116
128
  - lib/hashira/report/view.rb
129
+ - lib/hashira/smells/census.rb
130
+ - lib/hashira/smells/check.rb
131
+ - lib/hashira/smells/conditions.rb
132
+ - lib/hashira/smells/contexts.rb
133
+ - lib/hashira/smells/control_parameter.rb
134
+ - lib/hashira/smells/data_clump.rb
135
+ - lib/hashira/smells/duplicate_method_call.rb
136
+ - lib/hashira/smells/feature_envy.rb
137
+ - lib/hashira/smells/instance_variable_assumption.rb
138
+ - lib/hashira/smells/manual_dispatch.rb
139
+ - lib/hashira/smells/module_initialize.rb
140
+ - lib/hashira/smells/nil_check.rb
141
+ - lib/hashira/smells/param_check.rb
142
+ - lib/hashira/smells/refs.rb
143
+ - lib/hashira/smells/repeated_conditional.rb
144
+ - lib/hashira/smells/report.rb
145
+ - lib/hashira/smells/scope.rb
146
+ - lib/hashira/smells/too_many_instance_variables.rb
147
+ - lib/hashira/smells/utility_function.rb
148
+ - lib/hashira/smells/visibility.rb
117
149
  - lib/hashira/version.rb
118
150
  homepage: https://github.com/giacope/hashira
119
151
  licenses: