Skip to content

Commit

Permalink
First version of a cop
Browse files Browse the repository at this point in the history
  • Loading branch information
himynameisjonas committed Nov 12, 2024
1 parent 0f85f20 commit eef1d1f
Show file tree
Hide file tree
Showing 13 changed files with 114 additions and 34 deletions.
3 changes: 3 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Naming/FileName:
Exclude:
- lib/rubocop-teamtailor.rb
6 changes: 3 additions & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ GEM
specs:
ast (2.4.2)
diff-lcs (1.5.1)
json (2.7.4)
json (2.8.1)
language_server-protocol (3.17.0.3)
lint_roller (1.1.0)
parallel (1.26.3)
parser (3.3.5.0)
parser (3.3.6.0)
ast (~> 2.4.1)
racc
racc (1.8.1)
Expand Down Expand Up @@ -43,7 +43,7 @@ GEM
rubocop-ast (>= 1.32.2, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.32.3)
rubocop-ast (1.35.0)
parser (>= 3.3.1.0)
rubocop-performance (1.22.1)
rubocop (>= 1.48.1, < 2.0)
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Rubocop::Teamtailor
# RuboCop::Teamtailor

TODO: Delete this and the text below, and describe your gem

Expand Down Expand Up @@ -36,4 +36,4 @@ The gem is available as open source under the terms of the [MIT License](https:/

## Code of Conduct

Everyone interacting in the Rubocop::Teamtailor project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/rubocop-teamtailor/blob/main/CODE_OF_CONDUCT.md).
Everyone interacting in the RuboCop::Teamtailor project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/rubocop-teamtailor/blob/main/CODE_OF_CONDUCT.md).
17 changes: 6 additions & 11 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,29 @@

require "bundler/gem_tasks"
require "rspec/core/rake_task"

RSpec::Core::RakeTask.new(:spec)

require "standard/rake"

task default: %i[spec standard]

require 'rspec/core/rake_task'

RSpec::Core::RakeTask.new(:spec) do |spec|
spec.pattern = FileList['spec/**/*_spec.rb']
spec.pattern = FileList["spec/**/*_spec.rb"]
end

desc 'Generate a new cop with a template'
desc "Generate a new cop with a template"
task :new_cop, [:cop] do |_task, args|
require 'rubocop'
require "rubocop"

cop_name = args.fetch(:cop) do
warn 'usage: bundle exec rake new_cop[Department/Name]'
warn "usage: bundle exec rake new_cop[Department/Name]"
exit!
end

generator = RuboCop::Cop::Generator.new(cop_name)

generator.write_source
generator.write_spec
generator.inject_require(root_file_path: 'lib/rubocop/cop/teamtailor_cops.rb')
generator.inject_config(config_file_path: 'config/default.yml')
generator.inject_require(root_file_path: "lib/rubocop/cop/teamtailor_cops.rb")
generator.inject_config(config_file_path: "config/default.yml")

puts generator.todo
end
6 changes: 6 additions & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Write it!

Teamtailor/NoHasManyInActiveModelSerializer:
Description: "TODO: Write a description of the cop."
Enabled: true
VersionAdded: "<<next>>"
10 changes: 5 additions & 5 deletions lib/rubocop-teamtailor.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# frozen_string_literal: true

require 'rubocop'
require "rubocop"

require_relative 'rubocop/teamtailor'
require_relative 'rubocop/teamtailor/version'
require_relative 'rubocop/teamtailor/inject'
require_relative "rubocop/teamtailor"
require_relative "rubocop/teamtailor/version"
require_relative "rubocop/teamtailor/inject"

RuboCop::Teamtailor::Inject.defaults!

require_relative 'rubocop/cop/teamtailor_cops'
require_relative "rubocop/cop/teamtailor_cops"
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# frozen_string_literal: true

module RuboCop
module Cop
module Teamtailor
class NoHasManyInActiveModelSerializer < Base
MSG = "No embedding of records"

def_node_matcher :no_has_many?, <<~PATTERN
(send nil? :has_many ...)
PATTERN

def on_class(class_node)
return unless class_node.defined_module_name.end_with?("Serializer")
check_children(class_node)
end

private

def check_children(node)
if no_has_many?(node)
add_offense(node)
end

if node.respond_to?(:children)
node.children.each { |child| check_children(child) }
end
end
end
end
end
end
3 changes: 3 additions & 0 deletions lib/rubocop/cop/teamtailor_cops.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# frozen_string_literal: true

require_relative "teamtailor/no_has_many_in_active_model_serializer"
8 changes: 4 additions & 4 deletions lib/rubocop/teamtailor.rb
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# frozen_string_literal: true

require_relative "teamtailor/version"
require "yaml"

module RuboCop
module Teamtailor
class Error < StandardError; end
# Your code goes here...
PROJECT_ROOT = Pathname.new(__dir__).parent.parent.expand_path.freeze
CONFIG_DEFAULT = PROJECT_ROOT.join('config', 'default.yml').freeze
CONFIG = YAML.safe_load(CONFIG_DEFAULT.read).freeze
PROJECT_ROOT = Pathname.new(__dir__).parent.parent.expand_path.freeze
CONFIG_DEFAULT = PROJECT_ROOT.join("config", "default.yml").freeze
CONFIG = YAML.safe_load(CONFIG_DEFAULT.read).freeze

private_constant(:CONFIG_DEFAULT, :PROJECT_ROOT)
end
end

2 changes: 1 addition & 1 deletion sig/rubocop/teamtailor.rbs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module Rubocop
module RuboCop
module Teamtailor
VERSION: String
# See the writing guide of rbs: https://github.com/ruby/rbs#guides
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Teamtailor::NoHasManyInActiveModelSerializer, :config do
let(:config) { RuboCop::Config.new }

context "when in a serializer" do
it "registers an offense when using `has_many`" do
expect_offense(<<~RUBY)
class FooSerializer < ActiveModel::Serializer
has_many :locations, embed: :ids
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Teamtailor/NoHasManyInActiveModelSerializer: No embedding of records
end
RUBY
end

it "registers an offense for all `has_many`" do
expect_offense(<<~RUBY)
class FooSerializer < ActiveModel::Serializer
has_many :locations, embed: :ids
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Teamtailor/NoHasManyInActiveModelSerializer: No embedding of records
has_many :users, embed: :ids
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Teamtailor/NoHasManyInActiveModelSerializer: No embedding of records
end
RUBY
end

it "does not register an offense `has_one`" do
expect_no_offenses(<<~RUBY)
class FooSerializer < ActiveModel::Serializer
attributes :location_ids
end
RUBY
end
end

context "when not in a serializer" do
it "does not register an offense when using has_many" do
expect_no_offenses(<<~RUBY)
class Foo
has_many :locations
end
RUBY
end
end
end
8 changes: 2 additions & 6 deletions spec/rubocop/teamtailor_spec.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
# frozen_string_literal: true

RSpec.describe Rubocop::Teamtailor do
RSpec.describe RuboCop::Teamtailor do
it "has a version number" do
expect(Rubocop::Teamtailor::VERSION).not_to be nil
end

it "does something useful" do
expect(false).to eq(true)
expect(RuboCop::Teamtailor::VERSION).not_to be nil
end
end
4 changes: 2 additions & 2 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

require 'rubocop-teamtailor'
require 'rubocop/rspec/support'
require "rubocop-teamtailor"
require "rubocop/rspec/support"

RSpec.configure do |config|
config.include RuboCop::RSpec::ExpectOffense
Expand Down

0 comments on commit eef1d1f

Please sign in to comment.