sorbet-progress 0.2.5 → 0.3.0

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