sorbet-progress 0.2.5 → 0.3.0

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: d2b826258c3712e1cff93a6c4d1bb5320e2c5055a50fa043f891fa671229d5a9
4
- data.tar.gz: fab043fa62f98888b302998ac6fe4edc128b7614e40c1c6053dc1de911a2d321
3
+ metadata.gz: c938c4ae474d8ad023f0ef18383a798d8633235b17586546408b30ea0b977910
4
+ data.tar.gz: 25efefcf057f061c85e5d63b342d20c423010b95be2b39ced6addf70a5d17de9
5
5
  SHA512:
6
- metadata.gz: 8b90be69cf7bcf938efdd2047084b184641f1d536b94698226942773373e2d364fa2d46823d6cdfa90c68eae37582551af5dc0dc851257c76768e3d895f01919
7
- data.tar.gz: f82accf24f92a0fbaecb343305db8699ca080fc02bb711fad1b4f2deb7ccb988fb9b93ecbbbf34bf73eef53512fdaafb24ffcc2998767572a71d93eda763a7a9
6
+ metadata.gz: 466d87c077a1d5914a9ca70475c707e3cdb8964332b65794a73f7d6cd660f06e2ce978086a0af502948ff3cb15989a82863096af5ca32a7560ca2f23324ef361
7
+ data.tar.gz: 945748ad566f6610f4f0ee0d2ee9038a97495786a25e0357b145b26f440838dcd5f61fb5b5b0bea550a17290de69b48455ab15610a812655af7bfabb42585649
@@ -70,6 +70,10 @@ Layout/MultilineOperationIndentation:
70
70
  Lint/UnneededSplatExpansion:
71
71
  Enabled: false
72
72
 
73
+ Metrics/AbcSize:
74
+ Exclude:
75
+ - test/**/*
76
+
73
77
  # Compared to metrics like `AbcSize` or `CyclomaticComplexity`, number of
74
78
  # lines is not a useful metric.
75
79
  Metrics/ClassLength:
@@ -12,6 +12,16 @@ recommendations of [keepachangelog.com](http://keepachangelog.com/).
12
12
  - Fixed
13
13
  - None
14
14
 
15
+ ## 0.3.0 (2020-01-24)
16
+
17
+ - Breaking Changes
18
+ - None
19
+ - Added
20
+ - `--reporter` CLI option
21
+ - `bar_chart` reporter
22
+ - Fixed
23
+ - None
24
+
15
25
  ## 0.2.5 (2020-01-03)
16
26
 
17
27
  - Breaking Changes
data/README.md CHANGED
@@ -46,6 +46,44 @@ bundle exec sorbet_progress /tmp/sorbet_metrics.json
46
46
  Not sure what the best format is. Pull requests welcome. It might be nice to
47
47
  have an overall percentage, for example.
48
48
 
49
+ ## Reporters
50
+
51
+ ### bar_chart
52
+
53
+ ```
54
+ bundle exec sorbet_progress --reporter bar_chart /tmp/sorbet_metrics.json
55
+ Sorbet progress: ignore | false | true | strict+
56
+ |-0-|-2-|-------------32-------------|-------------------------61-------------------------|
57
+ Keep up the good work 👍
58
+ ```
59
+
60
+ The chart sums `strict` and `strong`, because `strict` is the highest reasonable
61
+ goal for most applications.
62
+
63
+ ### verbose
64
+
65
+ ```
66
+ bundle exec sorbet_progress --verbose /tmp/sorbet_metrics.json
67
+ Sorbet Progress
68
+
69
+ Progress for sig coverage
70
+ total_signatures 7528
71
+ total_methods 183447
72
+ total_classes 112433
73
+
74
+ Progress for file coverage
75
+ sigil_ignore 12 0.20 %
76
+ sigil_false 5466 91.60 %
77
+ sigil_true 460 7.71 %
78
+ sigil_strict 12 0.20 %
79
+ sigil_strong 17 0.28 %
80
+ ---------------------------------------
81
+ Total: 5967 100%
82
+ Keep up the good work 👍
83
+ ```
84
+
85
+ See example
86
+
49
87
  ## Contributing
50
88
 
51
89
  This project does not accept bug reports. Pull requests are welcome.
@@ -3,33 +3,6 @@
3
3
  set -e
4
4
 
5
5
  bundle exec srb tc --metrics-file /tmp/sorbet_metrics.json
6
-
7
- # TODO: Doesn't work on travis. No idea why.
8
- #
9
- # ```
10
- # Traceback (most recent call last):
11
- # 4: from /home/travis/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require'
12
- # 3: from /home/travis/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require'
13
- # 2: from /home/travis/build/jaredbeck/sorbet-progress/lib/sorbet_progress.rb:4:in `<top (required)>'
14
- # 1: from /home/travis/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require'
15
- # /home/travis/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require': cannot load such file -- sorbet-runtime
16
- # ```
17
- if [ "$TRAVIS" != 'true' ]; then
18
- bundle exec ruby -I lib \
19
- -r sorbet_progress \
20
- -e 'SorbetProgress::CLI.new(["/tmp/sorbet_metrics.json"]).run'
21
- fi
22
-
6
+ bundle exec bin/sorbet_progress --reporter bar_chart /tmp/sorbet_metrics.json
23
7
  bundle exec rubocop
24
-
25
- # TODO: This `bundle exec ruby` also doesn't work on travis.
26
- #
27
- # ```
28
- # home/travis/.rvm/gems/ruby-2.6.5/gems/bundler-2.1.3/lib/bundler/runtime.rb:312:in
29
- # `check_for_activated_spec!': You have already activated minitest 5.11.3, but
30
- # your Gemfile requires minitest 5.13.0. Prepending `bundle exec` to your
31
- # command may solve this. (Gem::LoadError)
32
- # ```
33
- if [ "$TRAVIS" != 'true' ]; then
34
- bundle exec ruby -I lib:test -r 'minitest/autorun' test/all.rb
35
- fi
8
+ bundle exec ruby -I lib:test test/all.rb
@@ -6,6 +6,9 @@ require "sorbet_progress/calculator"
6
6
  require "sorbet_progress/error"
7
7
  require "sorbet_progress/metrics"
8
8
  require "sorbet_progress/parser"
9
+ require "sorbet_progress/reporters/bar_chart"
10
+ require "sorbet_progress/reporters/base"
11
+ require "sorbet_progress/reporters/verbose"
9
12
 
10
13
  module SorbetProgress
11
14
  # Parses the provided metrics file and prints a report.
@@ -13,53 +16,32 @@ module SorbetProgress
13
16
  extend T::Sig
14
17
 
15
18
  USAGE = <<~EOS
16
- Usage: sorbet_progress /path/to/sorbet_metrics.json
19
+ Usage: sorbet_progress [--reporter name] /path/to/sorbet_metrics.json
20
+ Reporters: bar_chart, verbose
17
21
  EOS
18
22
 
19
23
  sig { params(argv: T::Array[String]).void }
20
24
  def initialize(argv)
21
- unless argv.length == 1
25
+ # TODO: use an actual CLI args parser, like optparse or trollop
26
+ case argv.length
27
+ when 1
28
+ @path = argv.first
29
+ @reporter_name = "verbose"
30
+ when 3
31
+ @path = argv.last
32
+ @reporter_name = argv[1]
33
+ else
22
34
  raise Error.new(1, USAGE)
23
35
  end
24
- @path = argv.first
25
36
  end
26
37
 
27
38
  sig { void }
28
- # rubocop:disable Metrics/AbcSize
29
39
  def run
30
40
  metrics = parse(@path)
31
- puts "Sorbet Progress\n\n"
32
-
33
- stats_calculator = Calculator.new(metrics)
34
-
35
- puts "Progress for sig coverage"
36
- stats_calculator.coverage_metrics.each do |label, value|
37
- puts format_metric(label, value)
38
- end
39
-
40
- puts "\nProgress for file coverage"
41
-
42
- stats_calculator.sigil_percentages.each do |elem|
43
- percentage =
44
- if elem[:percentage]
45
- elem[:percentage] * 100
46
- else
47
- 0
48
- end
49
- puts format(
50
- "%-17s\t%d\t%.2f %%",
51
- elem[:label],
52
- elem[:value] || 0,
53
- percentage
54
- )
55
- end
56
-
57
- puts "---------------------------------------"
58
- puts "Total: \t\t\t#{stats_calculator.total}\t100%"
59
-
60
- puts "Keep up the good work 👍"
41
+ calculator = Calculator.new(metrics)
42
+ reporter = reporter_class(@reporter_name).new(calculator)
43
+ puts reporter.report
61
44
  end
62
- # rubocop:enable Metrics/AbcSize
63
45
 
64
46
  private
65
47
 
@@ -70,13 +52,15 @@ module SorbetProgress
70
52
  raise Error.new(2, "Metrics file not found: " + e.message)
71
53
  end
72
54
 
73
- # Format a label and metric value into a presentable String.
74
- sig { params(label: Symbol, value: Integer).returns(String) }
75
- def format_metric(label, value)
76
- if value.nil?
77
- format("%-17s\tunknown", label)
55
+ sig { params(name: String).returns(T.class_of(Reporters::Base)) }
56
+ def reporter_class(name)
57
+ case name
58
+ when "verbose"
59
+ Reporters::Verbose
60
+ when "bar_chart"
61
+ Reporters::BarChart
78
62
  else
79
- format("%-17s\t%d", label, value)
63
+ raise format("Invalid reporter name: %s", @reporter_name)
80
64
  end
81
65
  end
82
66
  end
@@ -0,0 +1,83 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require "rainbow"
5
+ require "sorbet_progress/reporters/base"
6
+
7
+ module SorbetProgress
8
+ module Reporters
9
+ # Produces output something like this:
10
+ #
11
+ # ```
12
+ # Sorbet progress: ignore | false | true | strict+
13
+ # |----------------50--------------|---------25--------|-5-|------20------|
14
+ # Keep up the good work 👍
15
+ # ```
16
+ #
17
+ # The chart is colored. Colorless terminals are not supported.
18
+ #
19
+ # Strict and strong are combined into one category because strong is not
20
+ # a reachable goal in most projects.
21
+ class BarChart < Base
22
+ extend T::Sig
23
+
24
+ COLORS = T.let(%w[red yellow green blue].freeze, T::Array[String])
25
+ LENGTH = 80
26
+
27
+ sig { params(calculator: Calculator).void }
28
+ def initialize(calculator)
29
+ @calculator = calculator
30
+ end
31
+
32
+ sig { override.returns(String) }
33
+ def report
34
+ [
35
+ "Sorbet progress: ignore | false | true | strict+",
36
+ bar_chart,
37
+ "Keep up the good work 👍"
38
+ ].flatten.join("\n")
39
+ end
40
+
41
+ private
42
+
43
+ sig { returns(String) }
44
+ def bar_chart
45
+ body = segments.each_with_index.each_with_object([]) { |(e, i), a|
46
+ a.push(segment(e, i))
47
+ }.join("|")
48
+ format("|%s|", body)
49
+ end
50
+
51
+ sig { params(fraction: Float, index: Integer).returns(String) }
52
+ def segment(fraction, index)
53
+ padding_max = (fraction * LENGTH / 2).round
54
+ padding_length = [1, padding_max].max
55
+ pad = "-" * padding_length
56
+ Rainbow(
57
+ format("%s%d%s", pad, fraction * 100, pad)
58
+ ).send(T.must(COLORS[index]))
59
+ end
60
+
61
+ sig { returns(T::Array[Float]) }
62
+ def segments
63
+ sigils = sigil_count_by_name
64
+ [
65
+ T.let(sigils.fetch(:sigil_ignore, 0.0), Float),
66
+ T.let(sigils.fetch(:sigil_false, 0.0), Float),
67
+ T.let(sigils.fetch(:sigil_true, 0.0), Float),
68
+ T.let(
69
+ sigils.fetch(:sigil_strict, 0.0) + sigils.fetch(:sigil_strong, 0.0),
70
+ Float
71
+ )
72
+ ]
73
+ end
74
+
75
+ sig { returns(T::Hash[Symbol, Float]) }
76
+ def sigil_count_by_name
77
+ @calculator.sigil_percentages.each_with_object({}) { |e, a|
78
+ a[e.fetch(:label)] = e.fetch(:percentage, 0.0).to_f
79
+ }
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,24 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require "rainbow"
5
+
6
+ module SorbetProgress
7
+ module Reporters
8
+ # Abstract
9
+ class Base
10
+ extend T::Helpers
11
+ extend T::Sig
12
+ abstract!
13
+
14
+ sig { params(calculator: Calculator).void }
15
+ def initialize(calculator)
16
+ @calculator = calculator
17
+ end
18
+
19
+ sig { abstract.returns(String) }
20
+ def report
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,85 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require "sorbet_progress/reporters/base"
5
+
6
+ module SorbetProgress
7
+ module Reporters
8
+ # The first reporter written. It's quite verbose, so I'm calling it ..
9
+ class Verbose < Base
10
+ extend T::Sig
11
+
12
+ sig { params(calculator: Calculator).void }
13
+ def initialize(calculator)
14
+ @calculator = calculator
15
+ end
16
+
17
+ sig { override.returns(String) }
18
+ def report
19
+ [
20
+ "Sorbet Progress\n",
21
+ "Progress for sig coverage",
22
+ coverage_metrics,
23
+ "\nProgress for file coverage",
24
+ sigil_percentages,
25
+ "---------------------------------------",
26
+ "Total: \t\t\t#{@calculator.total}\t100%",
27
+ "Keep up the good work 👍"
28
+ ].flatten.join("\n")
29
+ end
30
+
31
+ private
32
+
33
+ # Example output:
34
+ #
35
+ # ```
36
+ # total_signatures 7528
37
+ # total_methods 183447
38
+ # total_classes 112433
39
+ # ```
40
+ sig { returns(T::Array[String]) }
41
+ def coverage_metrics
42
+ @calculator.coverage_metrics.map do |label, value|
43
+ format_metric(label, value)
44
+ end
45
+ end
46
+
47
+ # Format a label and metric value into a presentable String.
48
+ sig { params(label: Symbol, value: Integer).returns(String) }
49
+ def format_metric(label, value)
50
+ if value.nil?
51
+ format("%-17s\tunknown", label)
52
+ else
53
+ format("%-17s\t%d", label, value)
54
+ end
55
+ end
56
+
57
+ # Example output:
58
+ #
59
+ # ```
60
+ # sigil_ignore 12 0.20 %
61
+ # sigil_false 5466 91.60 %
62
+ # sigil_true 460 7.71 %
63
+ # sigil_strict 12 0.20 %
64
+ # sigil_strong 17 0.28 %
65
+ # ```
66
+ sig { returns(T::Array[String]) }
67
+ def sigil_percentages
68
+ @calculator.sigil_percentages.map do |elem|
69
+ percentage =
70
+ if elem[:percentage]
71
+ elem[:percentage] * 100
72
+ else
73
+ 0
74
+ end
75
+ format(
76
+ "%-17s\t%d\t%.2f %%",
77
+ elem[:label],
78
+ elem[:value] || 0,
79
+ percentage
80
+ )
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -4,6 +4,6 @@
4
4
  # :nodoc:
5
5
  module SorbetProgress
6
6
  def self.gem_version
7
- Gem::Version.new("0.2.5")
7
+ Gem::Version.new("0.3.0")
8
8
  end
9
9
  end
@@ -21,6 +21,7 @@ Gem::Specification.new do |spec|
21
21
  spec.required_ruby_version = ">= 2.6.3"
22
22
  spec.required_rubygems_version = ">= 3.0.3"
23
23
 
24
+ spec.add_runtime_dependency "rainbow", "3.0"
24
25
  lambda {
25
26
  requirements = ">= 0.4.4314"
26
27
  spec.add_runtime_dependency "sorbet", requirements
@@ -11,7 +11,10 @@
11
11
  module Minitest
12
12
  def self.__run(reporter, options); end
13
13
  def self.after_run(&block); end
14
+
15
+ sig { void }
14
16
  def self.autorun; end
17
+
15
18
  def self.backtrace_filter; end
16
19
  def self.backtrace_filter=(arg0); end
17
20
  def self.clock_time; end
@@ -27,7 +30,10 @@ module Minitest
27
30
  def self.process_args(args = nil); end
28
31
  def self.reporter; end
29
32
  def self.reporter=(arg0); end
30
- def self.run(args = nil); end
33
+
34
+ sig { params(args: T::Array[String]).returns(T::Boolean) }
35
+ def self.run(args = []); end
36
+
31
37
  def self.run_one_method(klass, method_name); end
32
38
  end
33
39
  module Minitest::Parallel
@@ -2670,8 +2670,6 @@ module Enumerable
2670
2670
  def to_set(klass=T.unsafe(nil), *args, &block); end
2671
2671
 
2672
2672
  def uniq(); end
2673
-
2674
- def zip(*_); end
2675
2673
  end
2676
2674
 
2677
2675
  class Enumerator
@@ -3495,8 +3493,6 @@ module MonitorMixin
3495
3493
  def synchronize(); end
3496
3494
 
3497
3495
  def try_mon_enter(); end
3498
- EXCEPTION_IMMEDIATE = ::T.let(nil, ::T.untyped)
3499
- EXCEPTION_NEVER = ::T.let(nil, ::T.untyped)
3500
3496
  end
3501
3497
 
3502
3498
  class MonitorMixin::ConditionVariable
@@ -3817,11 +3813,7 @@ class OpenSSL::KDF::KDFError
3817
3813
  end
3818
3814
 
3819
3815
  module OpenSSL::KDF
3820
- def self.hkdf(*_); end
3821
-
3822
3816
  def self.pbkdf2_hmac(*_); end
3823
-
3824
- def self.scrypt(*_); end
3825
3817
  end
3826
3818
 
3827
3819
  class OpenSSL::OCSP::Request
@@ -3830,10 +3822,6 @@ end
3830
3822
 
3831
3823
  OpenSSL::PKCS7::Signer = OpenSSL::PKCS7::SignerInfo
3832
3824
 
3833
- class OpenSSL::PKey::EC
3834
- EXPLICIT_CURVE = ::T.let(nil, ::T.untyped)
3835
- end
3836
-
3837
3825
  class OpenSSL::PKey::EC::Point
3838
3826
  def to_octet_string(_); end
3839
3827
  end
@@ -3845,20 +3833,15 @@ class OpenSSL::PKey::RSA
3845
3833
  end
3846
3834
 
3847
3835
  module OpenSSL::SSL
3848
- OP_ALLOW_NO_DHE_KEX = ::T.let(nil, ::T.untyped)
3849
3836
  OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION = ::T.let(nil, ::T.untyped)
3850
3837
  OP_CRYPTOPRO_TLSEXT_BUG = ::T.let(nil, ::T.untyped)
3851
3838
  OP_LEGACY_SERVER_CONNECT = ::T.let(nil, ::T.untyped)
3852
- OP_NO_ENCRYPT_THEN_MAC = ::T.let(nil, ::T.untyped)
3853
- OP_NO_RENEGOTIATION = ::T.let(nil, ::T.untyped)
3854
- OP_NO_TLSv1_3 = ::T.let(nil, ::T.untyped)
3855
3839
  OP_SAFARI_ECDHE_ECDSA_BUG = ::T.let(nil, ::T.untyped)
3856
3840
  OP_TLSEXT_PADDING = ::T.let(nil, ::T.untyped)
3857
3841
  SSL2_VERSION = ::T.let(nil, ::T.untyped)
3858
3842
  SSL3_VERSION = ::T.let(nil, ::T.untyped)
3859
3843
  TLS1_1_VERSION = ::T.let(nil, ::T.untyped)
3860
3844
  TLS1_2_VERSION = ::T.let(nil, ::T.untyped)
3861
- TLS1_3_VERSION = ::T.let(nil, ::T.untyped)
3862
3845
  TLS1_VERSION = ::T.let(nil, ::T.untyped)
3863
3846
  end
3864
3847
 
@@ -3888,7 +3871,6 @@ class OpenSSL::SSL::SSLSocket
3888
3871
  end
3889
3872
 
3890
3873
  module OpenSSL::X509
3891
- V_FLAG_NO_CHECK_TIME = ::T.let(nil, ::T.untyped)
3892
3874
  V_FLAG_TRUSTED_FIRST = ::T.let(nil, ::T.untyped)
3893
3875
  end
3894
3876
 
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sorbet-progress
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jared Beck
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-03 00:00:00.000000000 Z
11
+ date: 2020-01-25 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rainbow
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: sorbet
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -106,6 +120,9 @@ files:
106
120
  - lib/sorbet_progress/metric.rb
107
121
  - lib/sorbet_progress/metrics.rb
108
122
  - lib/sorbet_progress/parser.rb
123
+ - lib/sorbet_progress/reporters/bar_chart.rb
124
+ - lib/sorbet_progress/reporters/base.rb
125
+ - lib/sorbet_progress/reporters/verbose.rb
109
126
  - lib/sorbet_progress/version.rb
110
127
  - sorbet-progress.gemspec
111
128
  - sorbet/config