code_keeper 0.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b4a15da64994715117539279f4e5e5cf188cda6d2b12a1a06bf2c9d952e675a4
4
- data.tar.gz: f4aa1e1345c5677ded8d8aaaa124d4680b92f022ed83a93410dbf747c8491216
3
+ metadata.gz: f1032e75ff8322d23a622e6bac5a04039939999032d5559e9ff54d46f04ccd16
4
+ data.tar.gz: 51e78032de7754ea37aacd6ea422d46e4c66cc94c5c5d10a2baf963cee475ee1
5
5
  SHA512:
6
- metadata.gz: '042197cb06c4aed7677d9074f53ee106264164536e3bc8a14a483c2bebf88454fd183724939daad10ea0eb5078b6718df07bfbcf615d792ac9ca4cbd2b51ef6f'
7
- data.tar.gz: a3ba59d24ab56465ede942e32262838485ef38795156a48976deb2de00508fee3a9b0249e71495ce99d05f525bd7873abf4fe195b605f9bb080a22d3fc5e1c62
6
+ metadata.gz: eedf3bcecbd0ad563300548c9b1ac9b7d2ddec52550b459754fa1556e052940ad36ce7c5fd9afdb6df0768ea5ce9dd04680d3cae6a68112d106cb4ddf6611073
7
+ data.tar.gz: c527a3f3a175535b53512f8291276b34edf6cf8b3afe267a093603a14b59c4bedb867af0383dd137b6b78992d7b9194dfd133535f811f2654a1077d61409c8ee
data/.rubocop.yml CHANGED
@@ -56,3 +56,6 @@ Metrics/PerceivedComplexity:
56
56
  Exclude:
57
57
  # It's hard to control.
58
58
  - lib/code_keeper/metrics/class_length.rb
59
+
60
+ Metrics/MethodLength:
61
+ Max: 40
data/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  ## Unrelease
4
4
 
5
+ ## 0.5.1 (2021-09-19)
6
+ ### Bug fixes
7
+ - [34](https://github.com/ebihara99999/code_keeper/pull/34): A result of the class_length doesn't show namespaces, and the class_length doesn't count comments of inner classes correctly.
8
+
5
9
  ## 0.5.0 (2021-09-16)
6
10
  ### Changes
7
11
  - [32](https://github.com/ebihara99999/code_keeper/pull/32): Specify dependency versions and loosen the supported ruby version.
@@ -15,7 +19,6 @@
15
19
  ### New features
16
20
  - [#26](https://github.com/ebihara99999/code_keeper/pull/26): Support an ABC software metric.
17
21
  - [#27](https://github.com/ebihara99999/code_keeper/pull/27): Support a class length metric.
18
- ### Bug fixes
19
22
 
20
23
  ### Changes
21
24
  - [#25](https://github.com/ebihara99999/code_keeper/pull/25): Remove redundant codes.
@@ -12,14 +12,15 @@ module CodeKeeper
12
12
 
13
13
  # NOTE: This doesn't exclude foldale sources like Array, Hash and Heredoc.
14
14
  def score
15
- @body.each_node(:class, :casgn) do |node|
16
- if node.class_type?
17
- @score_hash.store(node.loc.name.source.to_sym, calculate(node))
15
+ @body.each_node(:class, :casgn, :module) do |node|
16
+ if node.class_type? || node.module_type?
17
+ @score_hash.store(build_namespace(node), calculate(node))
18
18
  elsif node.casgn_type?
19
19
  parent = node.parent
20
20
 
21
21
  if parent&.assignment?
22
22
  block_node = node.children[2]
23
+ klass = node.loc.name.source
23
24
  elsif parent&.parent&.masgn_type?
24
25
  # In the case where `A, B = Struct.new(:a, :b)`,
25
26
  # B is always nil.
@@ -27,8 +28,10 @@ module CodeKeeper
27
28
  next unless node.loc.name.source == assigned
28
29
 
29
30
  block_node = parent.parent.children[1]
31
+ klass = node.loc.name.source
30
32
  else
31
33
  _scope, klass, block_node = *node
34
+ klass = klass.to_s
32
35
  end
33
36
 
34
37
  # This is not to raise error on dynamic assignments like `X = Y = Z = Class.new`.
@@ -37,10 +40,13 @@ module CodeKeeper
37
40
  # Similarly the block node is `:X` as follows if node is Y.
38
41
  next unless block_node.respond_to?(:class_definition?) && block_node.class_definition?
39
42
 
40
- # if the parent is an assignment_type or the parent of the parent is a masgn_type,
41
- klass ||= node.loc.name.source.to_sym
42
-
43
- @score_hash.store(klass, calculate(block_node))
43
+ # NOTE: klass doesn't have a namespace.
44
+ # Only supports namepaces in `class A; end` case.
45
+ if klass
46
+ @score_hash.store(klass, calculate(block_node)) if klass
47
+ else
48
+ @score_hash.store(build_namespace(block_node), calculate(block_node))
49
+ end
44
50
  end
45
51
  end
46
52
  @score_hash
@@ -50,24 +56,67 @@ module CodeKeeper
50
56
 
51
57
  def calculate(node)
52
58
  # node.body.line_count doesn't include comments after definition of a class.
53
- count = node.nonempty_line_count - 2
54
- count - line_count_of_inner_nodes(node) - comment_line_count(node)
59
+ # Don't use nonempty_lines. Empty lines are considered on only the node.
60
+ count = node.line_count - 2
61
+
62
+ count - line_count_of_inner_nodes(node) - comment_line_count(node) - empty_line_count(node)
63
+ end
64
+
65
+ def body_lines(node)
66
+ (node.first_line..node.last_line).to_a - descendant_class_lines(node)
67
+ end
68
+
69
+ def descendant_class_lines(node)
70
+ # A class may have multiple inner classes seperately.
71
+ # So it needs to store all descendant classes line ranges.
72
+ node.each_descendant(:class, :module).map do |desendant|
73
+ # To make easier to compare and consider inner nodes, change array of line range into an array of line numbers.
74
+ (desendant.first_line..desendant.last_line).to_a
75
+ end.flatten.uniq
76
+ end
77
+
78
+ def empty_line_count(node)
79
+ empty_lines = @ps.lines.filter_map.with_index { |line, i| i + 1 if line.empty? }
80
+ (empty_lines & body_lines(node)).size
55
81
  end
56
82
 
57
83
  def line_count_of_inner_nodes(node)
58
- count = 0
59
- node.each_descendant(:class, :module) do |klass_or_module_node|
60
- count += klass_or_module_node.nonempty_line_count
61
- end
62
- count
84
+ line_numbers = node.each_descendant(:class, :module).map do |descendant|
85
+ (descendant.first_line..descendant.last_line).to_a
86
+ end.flatten.uniq
87
+
88
+ line_numbers.size
63
89
  end
64
90
 
91
+ # Only counts the comment of the class or module of a node.
92
+ # Because `#line_count_of_inner_nodes` only considers the first inner node,
93
+ # the second or later inner nodes' commments are not necesarry to be counted.
65
94
  def comment_line_count(node)
66
- count = 0
67
- @ps.comments.each do |comment|
68
- count += 1 if (node.first_line...node.last_line).include? comment.loc.line
95
+ node_range = node.first_line...node.last_line
96
+ comment_lines = @ps.comments.map { |comment| comment.loc.line }
97
+ # The latter condition considers a class ouside or above the node.
98
+ comment_lines.select { |cl| !descendant_class_lines(node).include?(cl) && node_range.include?(cl) }.count
99
+ end
100
+
101
+ def build_namespace(node)
102
+ self_name = name_with_ns(node)
103
+
104
+ return self_name if node.each_ancestor(:class, :module).to_a.empty?
105
+
106
+ full_name = self_name.dup
107
+ node.each_ancestor(:class, :module) do |ancestor|
108
+ full_name = "#{name_with_ns(ancestor)}::#{full_name}"
109
+ end
110
+ full_name
111
+ end
112
+
113
+ def name_with_ns(node)
114
+ ns = node.children.first&.namespace&.source
115
+ if ns.nil?
116
+ node.children.first&.short_name.to_s
117
+ else
118
+ node.children.first.namespace.source + "::#{node.children.first.short_name}"
69
119
  end
70
- count
71
120
  end
72
121
  end
73
122
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CodeKeeper
4
- VERSION = "0.5.0"
4
+ VERSION = "0.5.1"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: code_keeper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yusuke Ebihara
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-09-15 00:00:00.000000000 Z
11
+ date: 2021-09-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parallel
@@ -68,7 +68,6 @@ files:
68
68
  - CHANGELOG.md
69
69
  - CODE_OF_CONDUCT.md
70
70
  - Gemfile
71
- - Gemfile.lock
72
71
  - LICENSE.txt
73
72
  - README.md
74
73
  - Rakefile
data/Gemfile.lock DELETED
@@ -1,57 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- code_keeper (0.4.0)
5
- parallel (~> 1.20.1)
6
- rubocop (~> 1.13.0)
7
- rubocop-ast (~> 1.4.1)
8
-
9
- GEM
10
- remote: https://rubygems.org/
11
- specs:
12
- ast (2.4.2)
13
- diff-lcs (1.4.4)
14
- parallel (1.20.1)
15
- parser (3.0.2.0)
16
- ast (~> 2.4.1)
17
- rainbow (3.0.0)
18
- rake (13.0.3)
19
- regexp_parser (2.1.1)
20
- rexml (3.2.5)
21
- rspec (3.10.0)
22
- rspec-core (~> 3.10.0)
23
- rspec-expectations (~> 3.10.0)
24
- rspec-mocks (~> 3.10.0)
25
- rspec-core (3.10.1)
26
- rspec-support (~> 3.10.0)
27
- rspec-expectations (3.10.1)
28
- diff-lcs (>= 1.2.0, < 2.0)
29
- rspec-support (~> 3.10.0)
30
- rspec-mocks (3.10.2)
31
- diff-lcs (>= 1.2.0, < 2.0)
32
- rspec-support (~> 3.10.0)
33
- rspec-support (3.10.2)
34
- rubocop (1.13.0)
35
- parallel (~> 1.10)
36
- parser (>= 3.0.0.0)
37
- rainbow (>= 2.2.2, < 4.0)
38
- regexp_parser (>= 1.8, < 3.0)
39
- rexml
40
- rubocop-ast (>= 1.2.0, < 2.0)
41
- ruby-progressbar (~> 1.7)
42
- unicode-display_width (>= 1.4.0, < 3.0)
43
- rubocop-ast (1.4.2)
44
- parser (>= 3.0.1.1)
45
- ruby-progressbar (1.11.0)
46
- unicode-display_width (2.1.0)
47
-
48
- PLATFORMS
49
- x86_64-linux
50
-
51
- DEPENDENCIES
52
- code_keeper!
53
- rake (~> 13.0)
54
- rspec (~> 3.0)
55
-
56
- BUNDLED WITH
57
- 2.2.3