Skip to content

Commit

Permalink
Sorbet fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
amazimbe committed Sep 4, 2024
1 parent a6ac29a commit bc53568
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 52 deletions.
41 changes: 27 additions & 14 deletions maven/lib/dependabot/maven/new_version.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# typed: true
# typed: strict
# frozen_string_literal: true

require "dependabot/maven/version_parser"
Expand All @@ -9,47 +9,60 @@

module Dependabot
module Maven
class NewVersion < Dependabot::Version
PRERELEASE_QUALIFIERS = [
class NewVersion
extend T::Sig
extend T::Helpers

PRERELEASE_QUALIFIERS = T.let([
Dependabot::Maven::VersionParser::ALPHA,
Dependabot::Maven::VersionParser::BETA,
Dependabot::Maven::VersionParser::MILESTONE,
Dependabot::Maven::VersionParser::RC,
Dependabot::Maven::VersionParser::SNAPSHOT
].freeze
].freeze, T::Array[Integer])

attr_accessor :bucket
sig { returns(Dependabot::Maven::TokenBucket) }
attr_accessor :token_bucket

sig { params(version: T.nilable(String)).returns(T::Boolean) }
def self.correct?(version)
return false if version.nil? || version.empty?

Dependabot::Maven::VersionParser.parse(version.to_s).any?
Dependabot::Maven::VersionParser.parse(version.to_s).to_a.any?
end

sig { params(version: T.nilable(String)).void }
def initialize(version)
@version_string = version.to_s
@bucket = Dependabot::Maven::VersionParser.parse(version.to_s)
@version_string = T.let(version, T.nilable(String))
@token_bucket = T.let(Dependabot::Maven::VersionParser.parse(version.to_s), Dependabot::Maven::TokenBucket)
end

sig { returns(String) }
def inspect
"#<#{self.class} #{@version_string}>"
"#<#{self.class} #{version_string}>"
end

sig { returns(String) }
def to_s
@version_string
T.must(version_string)
end

sig { returns(T::Boolean) }
def prerelease?
bucket.to_a.flatten.any? do |token|
token_bucket.to_a.flatten.any? do |token|
token.is_a?(Integer) && token.negative?
end
end

sig { params(other: ::Dependabot::Maven::NewVersion).returns(Integer) }
def <=>(other)
bucket <=> other.bucket
T.must(token_bucket <=> other.token_bucket)
end

private

sig { returns(T.nilable(String)) }
attr_reader :version_string
end
end
end

Dependabot::Utils.register_version_class("maven", Dependabot::Maven::NewVersion)
106 changes: 70 additions & 36 deletions maven/lib/dependabot/maven/version_parser.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# typed: ignore
# typed: strict
# frozen_string_literal: true

require "sorbet-runtime"
Expand All @@ -8,67 +8,92 @@
#
module Dependabot
module Maven
TokenBucket = Struct.new(:tokens, :addition) do
class TokenBucket < T::Struct
extend T::Sig
extend T::Helpers
include Comparable

prop :tokens, T::Array[T.untyped]
prop :addition, T.nilable(TokenBucket)

sig { returns(T::Array[T.untyped]) }
def to_a
return tokens if addition.nil?

tokens.clone.append(addition.to_a)
end

sig { params(other: TokenBucket).returns(T.nilable(Integer)) }
def <=>(other)
cmp = compare_tokens(tokens, other.tokens)
return cmp unless cmp.zero?
return cmp unless cmp&.zero?

compare_additions(addition, other.addition)
end

def compare_tokens(a, b) # rubocop:disable Naming/MethodParameterName
max_idx = [a.size, b.size].max - 1
sig { params(first: T::Array[Integer], second: T::Array[Integer]).returns(T.nilable(Integer)) }
def compare_tokens(first, second)
max_idx = [first.size, second.size].max - 1
(0..max_idx).each do |idx|
cmp = compare_token_pair(a[idx], b[idx])
return cmp unless cmp.zero?
cmp = compare_token_pair(first[idx], second[idx])
return cmp unless T.must(cmp).zero?
end
0
end

def compare_token_pair(a = 0, b = 0) # rubocop:disable Metrics/PerceivedComplexity
a ||= 0
b ||= 0
sig do
params(
first: T.nilable(T.any(String, Integer)),
second: T.nilable(T.any(String, Integer))
).returns(T.nilable(Integer))
end
def compare_token_pair(first = 0, second = 0) # rubocop:disable Metrics/PerceivedComplexity,Metrics/CyclomaticComplexity
first ||= 0
second ||= 0

if a.is_a?(Integer) && b.is_a?(String)
return a <= 0 ? -1 : 1
if first.is_a?(Integer) && second.is_a?(String)
return first <= 0 ? -1 : 1
end

if a.is_a?(String) && b.is_a?(Integer)
return b <= 0 ? 1 : -1
if first.is_a?(String) && second.is_a?(Integer)
return second <= 0 ? 1 : -1
end

if a == Dependabot::Maven::VersionParser::SP && b.is_a?(String) && b != Dependabot::Maven::VersionParser::SP
if first == Dependabot::Maven::VersionParser::SP &&
second.is_a?(String) && second != Dependabot::Maven::VersionParser::SP
return -1
end

if b == Dependabot::Maven::VersionParser::SP && a.is_a?(String) && a != Dependabot::Maven::VersionParser::SP
if second == Dependabot::Maven::VersionParser::SP &&
first.is_a?(String) && first != Dependabot::Maven::VersionParser::SP
return 1
end

a <=> b # a and b are both ints or strings
if first.is_a?(Integer) && second.is_a?(Integer)
first <=> second
elsif first.is_a?(String) && second.is_a?(String)
first <=> second
end
end

sig do
params(first: T.nilable(TokenBucket), second: T.nilable(TokenBucket)).returns(T.nilable(Integer))
end
def compare_additions(first, second)
return 0 if first.nil? && second.nil?

(first || empty_addition) <=> (second || empty_addition)
end

sig { returns(TokenBucket) }
def empty_addition
TokenBucket.new([])
TokenBucket.new(tokens: [])
end
end

class VersionParser
extend T::Sig
extend T::Helpers
include Comparable

ALPHA = -5
BETA = -4
Expand All @@ -77,42 +102,51 @@ class VersionParser
SNAPSHOT = -1
SP = "sp"

def self.parse(version_string)
new(version_string).parse
end
sig { params(version: T.nilable(String)).returns(TokenBucket) }
def self.parse(version)
raise ArgumentError, "Malformed version string #{version}" if version.nil?

sig { returns(String) }
attr_reader :version_string
new(version).parse
end

sig { params(version_string: String).void }
def initialize(version_string)
@version_string = version_string
sig { params(version: String).void }
def initialize(version)
@version = version
@token_bucket = T.let(TokenBucket.new(tokens: []), T.nilable(TokenBucket))
@parse_result = T.let(@token_bucket, T.nilable(TokenBucket))
@scanner = T.let(StringScanner.new(version.downcase), StringScanner)
end

sig { returns(TokenBucket) }
def parse
@scanner = StringScanner.new(version_string.downcase)
@token_bucket = TokenBucket.new([])
@result = @token_bucket
parse_version(false)

raise ArgumentError, "Malformed version string #{version_string}" if @result.to_a.empty?
raise ArgumentError, "Malformed version string #{version}" if parse_result.to_a.empty?

@result
T.must(parse_result)
end

private

# sig { returns(String) }
sig { returns(StringScanner) }
attr_reader :scanner

sig { returns(String) }
attr_reader :version

sig { returns(T.nilable(TokenBucket)) }
attr_reader :parse_result

sig { params(token: T.nilable(T.any(String, Integer))).void }
def parse_addition(token = nil)
@token_bucket.addition = TokenBucket.new([token].compact)
@token_bucket = @token_bucket.addition
@token_bucket&.addition = TokenBucket.new(tokens: [token].compact)
@token_bucket = @token_bucket&.addition

scanner.skip(/-+/)
parse_version(true)
end

sig { params(number_begins_partition: T.nilable(T::Boolean)).void }
def parse_version(number_begins_partition) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
# skip leading v if any
scanner.skip(/v/)
Expand All @@ -122,7 +156,7 @@ def parse_version(number_begins_partition) # rubocop:disable Metrics/AbcSize,Met
if number_begins_partition
parse_addition(s.to_i)
else
@token_bucket.tokens << s.to_i
T.must(@token_bucket).tokens << s.to_i
end

elsif (s = scanner.match?(/a\d+/))
Expand Down
3 changes: 1 addition & 2 deletions maven/spec/dependabot/maven/new_version_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
it { is_expected.to be(true) }
end

context "with a null version" do
context "with a nil version" do
let(:version_string) { nil }

it { is_expected.to be(false) }
Expand Down Expand Up @@ -480,7 +480,6 @@
described_class.new("1.0-cr1"),
described_class.new("1.0-SNAPSHOT"),
described_class.new("1.0-RELEASE"),
described_class.new("1.0"),
described_class.new("1.0-sp"),
described_class.new("1.0-a"),
described_class.new("1.0-whatever"),
Expand Down
20 changes: 20 additions & 0 deletions maven/spec/dependabot/maven/version_parser_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,25 @@
end
end
end

context "with a nil version" do
let(:version) { nil }

let(:err_msg) { "Malformed version string #{version}" }

it "raises an exception" do
expect { described_class.parse(version) }.to raise_error(ArgumentError, err_msg)
end
end

context "with a malformed version" do
let(:version) { "" }

let(:err_msg) { "Malformed version string #{version}" }

it "raises an exception" do
expect { described_class.parse(version) }.to raise_error(ArgumentError, err_msg)
end
end
end
end

0 comments on commit bc53568

Please sign in to comment.