Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
egiurleo committed Feb 2, 2024
1 parent f818960 commit 2d86a91
Show file tree
Hide file tree
Showing 8 changed files with 162 additions and 104 deletions.
2 changes: 1 addition & 1 deletion config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ Sorbet/ValidVersionAnnotations:
Include:
- "**/*.rbi"

Sorbet/NoOverlappingAndAnnotations:
Sorbet/ForbidOverlappingAndAnnotations:
Description: 'Ensures any gem version annotations using "and" operation do not overlap unnecessarily.'
Enabled: pending
VersionAdded: '<<next>>'
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# frozen_string_literal: true

module RuboCop
module Cop
module Sorbet
# Checks that RBI gem version annotations do not contain "and" statements with
# overlapping gem versions.
#
# @example
# # bad
# # @version > 3.2.3, > 4.5
#
# # bad
# # @version > 1.0, <= 2.0, = 1.5
#
# # good
# # @version < 1.0, >= 2.0
#
class ForbidOverlappingAndAnnotations < Base
include RBIVersionAnnotationHelper

MSG = "Some message here"

def on_new_investigation
rbi_version_annotations.each do |comment|
ranges = []
versions(comment).each do |version|
ranges += version_to_ranges(version)
end

overlap = ranges.combination(2).any? do |range_1, range_2|
range_1.cover?(range_2) || range_2.cover?(range_1)
end

add_offense(comment) if overlap
end
end

private

def version_to_ranges(version_string)
operator, version = version_string.strip.split(" ")
# TODO: make more specific
raise if operator.nil? || version.nil?

begin
gem_version = Gem::Version.new(version)
rescue ArgumentError
# TODO: do something here
return
end

case operator
when "="
[Range.new(gem_version, gem_version)]
when "!="
prev_version_down = Gem::Version.new(gem_version.to_s + "-pre")
next_version_up = Gem::Version.new(gem_version.to_s + ".1")
[Range.new(nil, prev_version_down), Range.new(next_version_up, nil)]
when ">"
next_version_up = Gem::Version.new(gem_version.to_s + ".1")
[Range.new(next_version_up, nil)]
when ">="
[Range.new(gem_version, nil)]
when "<"
[Range.new(nil, gem_version, true)] # exclude ending value
when "<="
[Range.new(nil, gem_version)] # include ending value
when "~>"
[Range.new(gem_version, gem_version.bump)]
else
# TODO: make more specific
raise "INVALID OPERATOR"
end
end
end
end
end
end

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# frozen_string_literal: true

module RuboCop
module Cop
module Sorbet
module RBIVersionAnnotationHelper
VERSION_PREFIX = "# @version "

def rbi_version_annotations
processed_source.comments.select do |comment|
version_annotation?(comment)
end
end

private

def version_annotation?(comment)
comment.text.start_with?(VERSION_PREFIX)
end

def versions(comment)
comment.text.delete_prefix(VERSION_PREFIX).split(", ")
end
end
end
end
end
14 changes: 4 additions & 10 deletions lib/rubocop/cop/sorbet/rbi_versioning/valid_version_annotations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,15 @@ module Sorbet
# # @version <= 4.3-preview
#
class ValidVersionAnnotations < Base
MSG = "Invalid gem version(s) detected: %<versions>s"
include RBIVersionAnnotationHelper

VERSION_PREFIX = "# @version "
MSG = "Invalid gem version(s) detected: %<versions>s"

def on_new_investigation
processed_source.comments.each_with_index do |comment, _comment_idx|
next unless version_annotation?(comment)

rbi_version_annotations.each do |comment|
invalid_versions = []

comment.text.delete_prefix(VERSION_PREFIX).split(", ").each do |version|
versions.each do |version|
invalid_versions << version unless valid_version?(version)
end

Expand All @@ -42,10 +40,6 @@ def on_new_investigation

private

def version_annotation?(comment)
comment.text.start_with?(VERSION_PREFIX)
end

def valid_version?(version_string)
parts = version_string.strip.split(" ")
return false unless parts.length == 2
Expand Down
3 changes: 2 additions & 1 deletion lib/rubocop/cop/sorbet_cops.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@
require_relative "sorbet/rbi/forbid_rbi_outside_of_allowed_paths"
require_relative "sorbet/rbi/single_line_rbi_class_module_definitions"

require_relative "sorbet/rbi_versioning/rbi_version_annotation_helper"
require_relative "sorbet/rbi_versioning/valid_version_annotations"
require_relative "sorbet/rbi_versioning/no_overlapping_and_annotations"
require_relative "sorbet/rbi_versioning/forbid_overlapping_and_annotations"

require_relative "sorbet/signatures/allow_incompatible_override"
require_relative "sorbet/signatures/checked_true_in_signature"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# frozen_string_literal: true

RSpec.describe(RuboCop::Cop::Sorbet::ForbidOverlappingAndAnnotations, :config) do
it "does not register an offense when comment is not a version annotation" do
expect_no_offenses(<<~RUBY)
# a random comment
RUBY
end

it "does not register an offense when versions do not overlap" do
expect_no_offenses(<<~RUBY)
# @version < 1.0, >= 2.0
RUBY
end

it "registers an offense when one version is contained within a range" do
expect_offense(<<~RUBY)
# @version < 1.0, = 0.4.0
^^^^^^^^^^^^^^^^^^^^^^^^^ Some message here
RUBY
end

it "registers an offense when one version is contained within one of a few ranges" do
expect_offense(<<~RUBY)
# @version > 5.0, < 1.0, = 0.4
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Some message here
RUBY
end

it "does not register an offense when one version partially overlaps with another" do
expect_no_offenses(<<~RUBY)
# @version > 5.0, < 7.0
RUBY
end

it "registers an offense when twiddle-waka operator is used" do
expect_offense(<<~RUBY)
# @version ~> 3.6, = 3.6.8
^^^^^^^^^^^^^^^^^^^^^^^^^^ Some message here
RUBY
end

it "registers an offense when not-equal operator is used" do
expect_offense(<<~RUBY)
# @version != 4.0, <= 3.8
^^^^^^^^^^^^^^^^^^^^^^^^^ Some message here
RUBY
end
end

This file was deleted.

0 comments on commit 2d86a91

Please sign in to comment.