akainaa 0.1.2 → 0.1.6

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: 6451f71725cda32349ab87402b32e6e132d8185274ba55a930fa2389fdd12279
4
- data.tar.gz: 2b40049516aa512d8a89b607d327b1a5571b3c4221e351248d4ac13bbdc31dfd
3
+ metadata.gz: 423527610c1fbb25d01ddfb555e6ea40f8a943001b04dc399682937353529a23
4
+ data.tar.gz: 70aab5713abf80fc2dd41783fb56b6e223d2d2549438640ca4916bf2f413cba6
5
5
  SHA512:
6
- metadata.gz: f3199e1047c1295040cf043154128fcef145da13815f1cf8b69c84ec4a3237e44c525107ccb97abcc115d9d12f810e40623685843e190bb07cb99f95e35b104d
7
- data.tar.gz: 74c12cf59e645eef87f2811d95d584a32ed5ec54b6f75019114c8f595fa206e0121cf7413c87a3b53fb4523f62cc7b45ee004aab467594f4dffd2153af00d045
6
+ metadata.gz: 35978a5f110960e9c5f37e5d025efb6c40307fae6e4979a4e01f368802e230d8d3ae338f4dd1ef0370a8d69d66bbddd96d5860c65e559e49e0f56b52696cf14b
7
+ data.tar.gz: 92c0ac588743097d660462ee452438cbd3c98ae0933525689e4024b592c815dfc36e7696dffb4d3f33e44505d6d1ea291f7307b103013e29c6d70e066b9262b4
data/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.1.6] - 2024-09-11
4
+
5
+ - Feature: Add `clear` flag on first emit
6
+ - Feature: Add `trap_at_exit` option to `Akainaa.start` method
7
+ - Feature: Do not emit regularly if interval is 0 or nil
8
+
9
+ ## [0.1.5] - 2024-09-10
10
+
11
+ - Bug fix: nested method call won't handled
12
+ - Bug fix: Empty 302 response body on /akainaa/reset
13
+ - Feature: Add `ignore_glob_patterns` option to `Akainaa.start` method
14
+ - Feature: Add `hide_not_executed_files` option to `Akainaa.start` method
15
+ - Feature: Add `online_emit` option to `Akainaa.start` method
16
+
3
17
  ## [0.1.2] - 2024-05-06
4
18
 
5
19
  - Coloring all line of the method which located on multiple lines
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Akainaa (赤いなぁ)
1
+ # Akainaa (赤いなぁ、 It's red...)
2
2
 
3
3
  ![page view](./img/webui-rev02.png)
4
4
 
@@ -28,7 +28,13 @@ Here is example:
28
28
  ```ruby
29
29
  require 'akainaa'
30
30
 
31
- Akainaa.start(project_dir: File.expand_path(__dir__))
31
+ Akainaa.start(
32
+ project_dir: File.expand_path(__dir__),
33
+ ignore_glob_patterns: %w[
34
+ config/application.rb
35
+ config/initializers/*_initializer.rb
36
+ ],
37
+ )
32
38
 
33
39
  require_relative 'app'
34
40
 
@@ -39,6 +45,27 @@ run App
39
45
  Boot up application, do something, and access `/akainaa`.
40
46
  It will show Web UI what and how many executed.
41
47
 
48
+ ### Enable online emit mode
49
+
50
+ Akainaa can emit coverage data which recorded in interval to the file.
51
+ This feature is intended to be used with vscode-akainaa extension.
52
+
53
+ ```ruby
54
+ Akainaa.start(
55
+ project_dir: File.expand_path(__dir__),
56
+ ignore_glob_patterns: %w[
57
+ config/application.rb
58
+ config/initializers/*_initializer.rb
59
+ ],
60
+ online_emit: {
61
+ mode: :file,
62
+ interval: 1, # seconds
63
+ output_path: '/tmp/akainaa.json',
64
+ trap_at_exit: true,
65
+ },
66
+ )
67
+ ```
68
+
42
69
  ## Development
43
70
 
44
71
  After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/lib/akainaa/util.rb CHANGED
@@ -19,6 +19,7 @@ module Akainaa
19
19
 
20
20
  visitor.multiline_method_calls.each do |method_range|
21
21
  call_count = lines[method_range.start_line_as_idx]
22
+ next if call_count.nil?
22
23
 
23
24
  method_range.method_row_range_as_idx.each do |idx|
24
25
  if fullfilled_lines[idx].nil?
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Akainaa
4
- VERSION = "0.1.2"
4
+ VERSION = "0.1.6"
5
5
  end
data/lib/akainaa.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'coverage'
4
+ require 'fileutils'
4
5
 
5
6
  require_relative 'akainaa/version'
6
7
  require_relative 'akainaa/call_node_visitor'
@@ -10,24 +11,111 @@ module Akainaa
10
11
  class Error < StandardError; end
11
12
 
12
13
  class << self
13
- attr_accessor :project_dir
14
-
15
- def start(project_dir:)
14
+ attr_accessor :project_dir, :ignore_files, :hide_not_executed_files
15
+
16
+ def start(
17
+ project_dir:,
18
+ ignore_glob_patterns: [],
19
+ hide_not_executed_files: false,
20
+ online_emit: nil
21
+ )
16
22
  @project_dir = project_dir
17
23
  @project_dir += '/' unless @project_dir.end_with?('/')
24
+ ignore_files = ignore_glob_patterns.flat_map do |pattern|
25
+ Dir["#{@project_dir}#{pattern}"].to_a
26
+ end
27
+ @ignore_files = Set.new(ignore_files)
28
+ @hide_not_executed_files = hide_not_executed_files
29
+ @monitor = Monitor.new
30
+ @first_emitted = false
18
31
 
19
32
  Coverage.start(lines: true)
33
+
34
+ if online_emit.is_a?(Hash)
35
+ option = default_online_emit.merge(online_emit)
36
+ FileUtils.mkdir_p(File.dirname(option[:path]))
37
+ start_multipart_emit(option)
38
+
39
+ if option[:trap_at_exit]
40
+ at_exit do
41
+ write_result(peek_result, option[:path])
42
+ end
43
+ end
44
+ end
20
45
  end
21
46
 
22
47
  def peek_result
23
48
  Coverage
24
49
  .peek_result
25
50
  .select { |k, _v| k.start_with?(project_dir) }
51
+ .reject { |k, _v| ignore_files.member?(k) }
26
52
  .transform_keys { |k| k.sub(project_dir, '') }
27
53
  end
28
54
 
29
55
  def reset
30
- Coverage.result(stop: false, clear: true)
56
+ @monitor.synchronize do
57
+ Coverage.result(stop: false, clear: true)
58
+ @previous_result = {}
59
+ end
60
+ end
61
+
62
+ private def write_result(result, path)
63
+ puts "Writing coverage result to #{path}"
64
+ unless @first_emitted
65
+ puts "with clear flag"
66
+ result['clear'] = true
67
+ end
68
+ File.write(path, result.to_json)
69
+ @first_emitted = true
70
+ end
71
+
72
+ private def default_online_emit
73
+ {
74
+ mode: :file,
75
+ interval: 1,
76
+ path: 'tmp/coverage.json',
77
+ trap_at_exit: true,
78
+ }
79
+ end
80
+
81
+ private def start_multipart_emit(option)
82
+ return if option[:interval].nil? || option[:interval] <= 0
83
+
84
+ Thread.new do
85
+ @monitor.synchronize do
86
+ @previous_result = {}
87
+ end
88
+
89
+ loop do
90
+ sleep option[:interval]
91
+ current_result = peek_result
92
+
93
+ diff = {}
94
+ current_result.each do |path, path_coverage|
95
+ previous_path_coverage = @previous_result[path]
96
+
97
+ if previous_path_coverage.nil?
98
+ diff[path] = path_coverage
99
+ elsif previous_path_coverage[:lines].size != path_coverage[:lines].size
100
+ diff[path] = path_coverage
101
+ else
102
+ diff[path] = { lines: [] }
103
+
104
+ path_coverage[:lines].each_with_index do |count, index|
105
+ val = count ? count - previous_path_coverage[:lines][index] : nil
106
+
107
+ diff[path][:lines] << val
108
+ end
109
+ end
110
+ end
111
+
112
+ @monitor.synchronize do
113
+ @previous_result = current_result
114
+ end
115
+
116
+ write_result(diff, option[:path])
117
+ end
118
+ end
31
119
  end
32
120
  end
33
121
 
@@ -48,7 +136,7 @@ module Akainaa
48
136
  path = extract_path_from_query(env)
49
137
  Akainaa.reset
50
138
 
51
- [302, { 'Location' => "/akainaa?path=#{path}" }, [html]]
139
+ [302, { 'Location' => "/akainaa?path=#{path}" }, []]
52
140
  else
53
141
  @app.call(env)
54
142
  end
@@ -83,6 +171,8 @@ module Akainaa
83
171
 
84
172
  li_elements = files.sort.map do |file|
85
173
  total_count_on_file = coverage_result[file][:lines].reject(&:nil?).sum
174
+ next '' if Akainaa.hide_not_executed_files && total_count_on_file == 0
175
+
86
176
  count_top = (total_count_on_file * 10 / max_count_on_proj).to_i * 10
87
177
 
88
178
  class_suffix = file == current_path ? ' current' : ''
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: akainaa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shia
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-05-06 00:00:00.000000000 Z
11
+ date: 2024-09-11 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Minimum rack middleware for coverage
14
14
  email:
@@ -47,7 +47,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
47
47
  - !ruby/object:Gem::Version
48
48
  version: '0'
49
49
  requirements: []
50
- rubygems_version: 3.6.0.dev
50
+ rubygems_version: 3.5.11
51
51
  signing_key:
52
52
  specification_version: 4
53
53
  summary: Minimum rack middleware for coverage