-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create a cop to validate gem version annotations in RBI files
While adding gem version annotations to RBI files would allow developers to write more comprehensive RBIs for their gems, it has has the potential to create RBI files that are cluttered, disorganized, or incorrect. This would be the first of a few cops meant to keep versioned RBIs clean and accurate. This cop checks that every version included in a "@Version" annotation fits the format specified by the RBI library.
- Loading branch information
Showing
5 changed files
with
170 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
27 changes: 27 additions & 0 deletions
27
lib/rubocop/cop/sorbet/rbi_versioning/gem_version_annotation_helper.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 GemVersionAnnotationHelper | ||
VERSION_PREFIX = "# @version " | ||
|
||
def gem_version_annotations | ||
processed_source.comments.select do |comment| | ||
gem_version_annotation?(comment) | ||
end | ||
end | ||
|
||
private | ||
|
||
def gem_version_annotation?(comment) | ||
comment.text.start_with?(VERSION_PREFIX) | ||
end | ||
|
||
def gem_versions(comment) | ||
comment.text.delete_prefix(VERSION_PREFIX).split(", ") | ||
end | ||
end | ||
end | ||
end | ||
end |
61 changes: 61 additions & 0 deletions
61
lib/rubocop/cop/sorbet/rbi_versioning/valid_gem_version_annotations.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module Cop | ||
module Sorbet | ||
# Checks that gem versions in RBI annotations are properly formatted per the Bundler gem specification. | ||
# | ||
# @example | ||
# # bad | ||
# # @version > not a version number | ||
# | ||
# # good | ||
# # @version = 1 | ||
# | ||
# # good | ||
# # @version > 1.2.3 | ||
# | ||
# # good | ||
# # @version <= 4.3-preview | ||
# | ||
class ValidGemVersionAnnotations < Base | ||
include GemVersionAnnotationHelper | ||
|
||
MSG = "Invalid gem version(s) detected: %<versions>s" | ||
VALID_OPERATORS = ["=", "!=", ">", ">=", "<", "<=", "~>"] | ||
|
||
def on_new_investigation | ||
gem_version_annotations.each do |comment| | ||
invalid_versions = gem_versions(comment).select do |version| | ||
!valid_version?(version) | ||
end | ||
|
||
unless invalid_versions.empty? | ||
message = format(MSG, versions: invalid_versions.join(", ")) | ||
add_offense(comment, message: message) | ||
end | ||
end | ||
end | ||
|
||
private | ||
|
||
def valid_version?(version_string) | ||
parts = version_string.strip.split(" ") | ||
operator, version = parts | ||
|
||
return false if operator.nil? || parts.nil? | ||
|
||
return false unless VALID_OPERATORS.include?(operator) | ||
|
||
begin | ||
Gem::Version.new(version) | ||
rescue ArgumentError | ||
return false | ||
end | ||
|
||
true | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
64 changes: 64 additions & 0 deletions
64
spec/rubocop/cop/sorbet/rbi_versioning/valid_gem_version_annotations_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.describe(RuboCop::Cop::Sorbet::ValidGemVersionAnnotations, :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 comment is a valid version annotation" do | ||
expect_no_offenses(<<~RUBY) | ||
# @version = 1.3.4-prerelease | ||
RUBY | ||
end | ||
|
||
it "does not register an offense when comment uses AND version annotations" do | ||
expect_no_offenses(<<~RUBY) | ||
# @version > 1, < 3.5 | ||
RUBY | ||
end | ||
|
||
it "does not register an offense when comment uses OR version annotations" do | ||
expect_no_offenses(<<~RUBY) | ||
# @version > 1.3.6 | ||
# @version <= 4 | ||
RUBY | ||
end | ||
|
||
it "registers an offense when gem version is not formatted correctly" do | ||
expect_offense(<<~RUBY) | ||
# @version = blah | ||
^^^^^^^^^^^^^^^^^ Invalid gem version(s) detected: = blah | ||
RUBY | ||
end | ||
|
||
it "registers an offense when one gem version out of the list is not formatted correctly" do | ||
expect_offense(<<~RUBY) | ||
# @version < 3.2, > 4, ~> five | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Invalid gem version(s) detected: ~> five | ||
RUBY | ||
end | ||
|
||
it "registers an offense when one gem version is not formatted correctly in an OR" do | ||
expect_offense(<<~RUBY) | ||
# @version < 3.2, > 4 | ||
# @version ~> five | ||
^^^^^^^^^^^^^^^^^^ Invalid gem version(s) detected: ~> five | ||
RUBY | ||
end | ||
|
||
it "registers an offense for multiple incorrectly formatted versions" do | ||
expect_offense(<<~RUBY) | ||
# @version < 3.2, ~> five, = blah | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Invalid gem version(s) detected: ~> five, = blah | ||
RUBY | ||
end | ||
|
||
it "registers an offense if operator is invalid" do | ||
expect_offense(<<~RUBY) | ||
# @version << 3.2 | ||
^^^^^^^^^^^^^^^^^ Invalid gem version(s) detected: << 3.2 | ||
RUBY | ||
end | ||
end |