code_keeper 0.5.0 → 0.5.1

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: 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