Merge branch 'custom-empty-exception-class-cop' into 'master'
Add RuboCop cop for custom error classes Closes #28770 See merge request !9573
This commit is contained in:
commit
981c730fdb
43 changed files with 239 additions and 81 deletions
|
@ -5,7 +5,7 @@ class Projects::BlobController < Projects::ApplicationController
|
||||||
include ActionView::Helpers::SanitizeHelper
|
include ActionView::Helpers::SanitizeHelper
|
||||||
|
|
||||||
# Raised when given an invalid file path
|
# Raised when given an invalid file path
|
||||||
class InvalidPathError < StandardError; end
|
InvalidPathError = Class.new(StandardError)
|
||||||
|
|
||||||
before_action :require_non_empty_project, except: [:new, :create]
|
before_action :require_non_empty_project, except: [:new, :create]
|
||||||
before_action :authorize_download_code!
|
before_action :authorize_download_code!
|
||||||
|
|
|
@ -19,7 +19,7 @@ class Project < ActiveRecord::Base
|
||||||
|
|
||||||
extend Gitlab::ConfigHelper
|
extend Gitlab::ConfigHelper
|
||||||
|
|
||||||
class BoardLimitExceeded < StandardError; end
|
BoardLimitExceeded = Class.new(StandardError)
|
||||||
|
|
||||||
NUMBER_OF_PERMITTED_BOARDS = 1
|
NUMBER_OF_PERMITTED_BOARDS = 1
|
||||||
UNKNOWN_IMPORT_URL = 'http://unknown.git'.freeze
|
UNKNOWN_IMPORT_URL = 'http://unknown.git'.freeze
|
||||||
|
|
|
@ -7,7 +7,7 @@ class ProjectWiki
|
||||||
'AsciiDoc' => :asciidoc
|
'AsciiDoc' => :asciidoc
|
||||||
}.freeze unless defined?(MARKUPS)
|
}.freeze unless defined?(MARKUPS)
|
||||||
|
|
||||||
class CouldNotCreateWikiError < StandardError; end
|
CouldNotCreateWikiError = Class.new(StandardError)
|
||||||
|
|
||||||
# Returns a string describing what went wrong after
|
# Returns a string describing what went wrong after
|
||||||
# an operation fails.
|
# an operation fails.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
class PipelineSerializer < BaseSerializer
|
class PipelineSerializer < BaseSerializer
|
||||||
class InvalidResourceError < StandardError; end
|
InvalidResourceError = Class.new(StandardError)
|
||||||
|
|
||||||
entity PipelineEntity
|
entity PipelineEntity
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
module Commits
|
module Commits
|
||||||
class ChangeService < ::BaseService
|
class ChangeService < ::BaseService
|
||||||
class ValidationError < StandardError; end
|
ValidationError = Class.new(StandardError)
|
||||||
class ChangeError < StandardError; end
|
ChangeError = Class.new(StandardError)
|
||||||
|
|
||||||
def execute
|
def execute
|
||||||
@start_project = params[:start_project] || @project
|
@start_project = params[:start_project] || @project
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module Files
|
module Files
|
||||||
class BaseService < ::BaseService
|
class BaseService < ::BaseService
|
||||||
class ValidationError < StandardError; end
|
ValidationError = Class.new(StandardError)
|
||||||
|
|
||||||
def execute
|
def execute
|
||||||
@start_project = params[:start_project] || @project
|
@start_project = params[:start_project] || @project
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module Files
|
module Files
|
||||||
class MultiService < Files::BaseService
|
class MultiService < Files::BaseService
|
||||||
class FileChangedError < StandardError; end
|
FileChangedError = Class.new(StandardError)
|
||||||
|
|
||||||
ACTIONS = %w[create update delete move].freeze
|
ACTIONS = %w[create update delete move].freeze
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module Files
|
module Files
|
||||||
class UpdateService < Files::BaseService
|
class UpdateService < Files::BaseService
|
||||||
class FileChangedError < StandardError; end
|
FileChangedError = Class.new(StandardError)
|
||||||
|
|
||||||
def commit
|
def commit
|
||||||
repository.update_file(current_user, @file_path, @file_content,
|
repository.update_file(current_user, @file_path, @file_content,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module Issues
|
module Issues
|
||||||
class MoveService < Issues::BaseService
|
class MoveService < Issues::BaseService
|
||||||
class MoveError < StandardError; end
|
MoveError = Class.new(StandardError)
|
||||||
|
|
||||||
def execute(issue, new_project)
|
def execute(issue, new_project)
|
||||||
@old_issue = issue
|
@old_issue = issue
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
module MergeRequests
|
module MergeRequests
|
||||||
class ResolveService < MergeRequests::BaseService
|
class ResolveService < MergeRequests::BaseService
|
||||||
class MissingFiles < Gitlab::Conflict::ResolutionError
|
MissingFiles = Class.new(Gitlab::Conflict::ResolutionError)
|
||||||
end
|
|
||||||
|
|
||||||
attr_accessor :conflicts, :rugged, :merge_index, :merge_request
|
attr_accessor :conflicts, :rugged, :merge_index, :merge_request
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ module Projects
|
||||||
class DestroyService < BaseService
|
class DestroyService < BaseService
|
||||||
include Gitlab::ShellAdapter
|
include Gitlab::ShellAdapter
|
||||||
|
|
||||||
class DestroyError < StandardError; end
|
DestroyError = Class.new(StandardError)
|
||||||
|
|
||||||
DELETED_FLAG = '+deleted'.freeze
|
DELETED_FLAG = '+deleted'.freeze
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ module Projects
|
||||||
class ImportService < BaseService
|
class ImportService < BaseService
|
||||||
include Gitlab::ShellAdapter
|
include Gitlab::ShellAdapter
|
||||||
|
|
||||||
class Error < StandardError; end
|
Error = Class.new(StandardError)
|
||||||
|
|
||||||
def execute
|
def execute
|
||||||
add_repository_to_project unless project.gitlab_project_import?
|
add_repository_to_project unless project.gitlab_project_import?
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
module Projects
|
module Projects
|
||||||
class TransferService < BaseService
|
class TransferService < BaseService
|
||||||
include Gitlab::ShellAdapter
|
include Gitlab::ShellAdapter
|
||||||
class TransferError < StandardError; end
|
TransferError = Class.new(StandardError)
|
||||||
|
|
||||||
def execute(new_namespace)
|
def execute(new_namespace)
|
||||||
if allowed_transfer?(current_user, project, new_namespace)
|
if allowed_transfer?(current_user, project, new_namespace)
|
||||||
|
|
|
@ -160,13 +160,10 @@ module API
|
||||||
# Exceptions
|
# Exceptions
|
||||||
#
|
#
|
||||||
|
|
||||||
class MissingTokenError < StandardError; end
|
MissingTokenError = Class.new(StandardError)
|
||||||
|
TokenNotFoundError = Class.new(StandardError)
|
||||||
class TokenNotFoundError < StandardError; end
|
ExpiredError = Class.new(StandardError)
|
||||||
|
RevokedError = Class.new(StandardError)
|
||||||
class ExpiredError < StandardError; end
|
|
||||||
|
|
||||||
class RevokedError < StandardError; end
|
|
||||||
|
|
||||||
class InsufficientScopeError < StandardError
|
class InsufficientScopeError < StandardError
|
||||||
attr_reader :scopes
|
attr_reader :scopes
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
module Bitbucket
|
module Bitbucket
|
||||||
module Error
|
module Error
|
||||||
class Unauthorized < StandardError
|
Unauthorized = Class.new(StandardError)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module Ci
|
module Ci
|
||||||
class GitlabCiYamlProcessor
|
class GitlabCiYamlProcessor
|
||||||
class ValidationError < StandardError; end
|
ValidationError = Class.new(StandardError)
|
||||||
|
|
||||||
include Gitlab::Ci::Config::Entry::LegacyValidationHelpers
|
include Gitlab::Ci::Config::Entry::LegacyValidationHelpers
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# file path string when combined in a request parameter
|
# file path string when combined in a request parameter
|
||||||
module ExtractsPath
|
module ExtractsPath
|
||||||
# Raised when given an invalid file path
|
# Raised when given an invalid file path
|
||||||
class InvalidPathError < StandardError; end
|
InvalidPathError = Class.new(StandardError)
|
||||||
|
|
||||||
# Given a string containing both a Git tree-ish, such as a branch or tag, and
|
# Given a string containing both a Git tree-ish, such as a branch or tag, and
|
||||||
# a filesystem path joined by forward slashes, attempts to separate the two.
|
# a filesystem path joined by forward slashes, attempts to separate the two.
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#
|
#
|
||||||
module Gitlab
|
module Gitlab
|
||||||
module Access
|
module Access
|
||||||
class AccessDeniedError < StandardError; end
|
AccessDeniedError = Class.new(StandardError)
|
||||||
|
|
||||||
NO_ACCESS = 0
|
NO_ACCESS = 0
|
||||||
GUEST = 10
|
GUEST = 10
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module Gitlab
|
module Gitlab
|
||||||
module Auth
|
module Auth
|
||||||
class MissingPersonalTokenError < StandardError; end
|
MissingPersonalTokenError = Class.new(StandardError)
|
||||||
|
|
||||||
SCOPES = [:api, :read_user].freeze
|
SCOPES = [:api, :read_user].freeze
|
||||||
DEFAULT_SCOPES = [:api].freeze
|
DEFAULT_SCOPES = [:api].freeze
|
||||||
|
|
|
@ -6,7 +6,7 @@ module Gitlab
|
||||||
module Build
|
module Build
|
||||||
module Artifacts
|
module Artifacts
|
||||||
class Metadata
|
class Metadata
|
||||||
class ParserError < StandardError; end
|
ParserError = Class.new(StandardError)
|
||||||
|
|
||||||
VERSION_PATTERN = /^[\w\s]+(\d+\.\d+\.\d+)/
|
VERSION_PATTERN = /^[\w\s]+(\d+\.\d+\.\d+)/
|
||||||
INVALID_PATH_PATTERN = %r{(^\.?\.?/)|(/\.?\.?/)}
|
INVALID_PATH_PATTERN = %r{(^\.?\.?/)|(/\.?\.?/)}
|
||||||
|
|
|
@ -6,7 +6,7 @@ module Gitlab
|
||||||
# Factory class responsible for fabricating entry objects.
|
# Factory class responsible for fabricating entry objects.
|
||||||
#
|
#
|
||||||
class Factory
|
class Factory
|
||||||
class InvalidFactory < StandardError; end
|
InvalidFactory = Class.new(StandardError)
|
||||||
|
|
||||||
def initialize(entry)
|
def initialize(entry)
|
||||||
@entry = entry
|
@entry = entry
|
||||||
|
|
|
@ -6,7 +6,7 @@ module Gitlab
|
||||||
# Base abstract class for each configuration entry node.
|
# Base abstract class for each configuration entry node.
|
||||||
#
|
#
|
||||||
class Node
|
class Node
|
||||||
class InvalidError < StandardError; end
|
InvalidError = Class.new(StandardError)
|
||||||
|
|
||||||
attr_reader :config, :metadata
|
attr_reader :config, :metadata
|
||||||
attr_accessor :key, :parent, :description
|
attr_accessor :key, :parent, :description
|
||||||
|
|
|
@ -2,7 +2,7 @@ module Gitlab
|
||||||
module Ci
|
module Ci
|
||||||
class Config
|
class Config
|
||||||
class Loader
|
class Loader
|
||||||
class FormatError < StandardError; end
|
FormatError = Class.new(StandardError)
|
||||||
|
|
||||||
def initialize(config)
|
def initialize(config)
|
||||||
@config = YAML.safe_load(config, [Symbol], [], true)
|
@config = YAML.safe_load(config, [Symbol], [], true)
|
||||||
|
|
|
@ -4,8 +4,7 @@ module Gitlab
|
||||||
include Gitlab::Routing.url_helpers
|
include Gitlab::Routing.url_helpers
|
||||||
include IconsHelper
|
include IconsHelper
|
||||||
|
|
||||||
class MissingResolution < ResolutionError
|
MissingResolution = Class.new(ResolutionError)
|
||||||
end
|
|
||||||
|
|
||||||
CONTEXT_LINES = 3
|
CONTEXT_LINES = 3
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
module Gitlab
|
module Gitlab
|
||||||
module Conflict
|
module Conflict
|
||||||
class FileCollection
|
class FileCollection
|
||||||
class ConflictSideMissing < StandardError
|
ConflictSideMissing = Class.new(StandardError)
|
||||||
end
|
|
||||||
|
|
||||||
attr_reader :merge_request, :our_commit, :their_commit
|
attr_reader :merge_request, :our_commit, :their_commit
|
||||||
|
|
||||||
|
|
|
@ -1,25 +1,15 @@
|
||||||
module Gitlab
|
module Gitlab
|
||||||
module Conflict
|
module Conflict
|
||||||
class Parser
|
class Parser
|
||||||
class UnresolvableError < StandardError
|
UnresolvableError = Class.new(StandardError)
|
||||||
end
|
UnmergeableFile = Class.new(UnresolvableError)
|
||||||
|
UnsupportedEncoding = Class.new(UnresolvableError)
|
||||||
class UnmergeableFile < UnresolvableError
|
|
||||||
end
|
|
||||||
|
|
||||||
class UnsupportedEncoding < UnresolvableError
|
|
||||||
end
|
|
||||||
|
|
||||||
# Recoverable errors - the conflict can be resolved in an editor, but not with
|
# Recoverable errors - the conflict can be resolved in an editor, but not with
|
||||||
# sections.
|
# sections.
|
||||||
class ParserError < StandardError
|
ParserError = Class.new(StandardError)
|
||||||
end
|
UnexpectedDelimiter = Class.new(ParserError)
|
||||||
|
MissingEndDelimiter = Class.new(ParserError)
|
||||||
class UnexpectedDelimiter < ParserError
|
|
||||||
end
|
|
||||||
|
|
||||||
class MissingEndDelimiter < ParserError
|
|
||||||
end
|
|
||||||
|
|
||||||
def parse(text, our_path:, their_path:, parent_file: nil)
|
def parse(text, our_path:, their_path:, parent_file: nil)
|
||||||
raise UnmergeableFile if text.blank? # Typically a binary file
|
raise UnmergeableFile if text.blank? # Typically a binary file
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
module Gitlab
|
module Gitlab
|
||||||
module Conflict
|
module Conflict
|
||||||
class ResolutionError < StandardError
|
ResolutionError = Class.new(StandardError)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,19 +4,19 @@ require_dependency 'gitlab/email/handler'
|
||||||
# Inspired in great part by Discourse's Email::Receiver
|
# Inspired in great part by Discourse's Email::Receiver
|
||||||
module Gitlab
|
module Gitlab
|
||||||
module Email
|
module Email
|
||||||
class ProcessingError < StandardError; end
|
ProcessingError = Class.new(StandardError)
|
||||||
class EmailUnparsableError < ProcessingError; end
|
EmailUnparsableError = Class.new(ProcessingError)
|
||||||
class SentNotificationNotFoundError < ProcessingError; end
|
SentNotificationNotFoundError = Class.new(ProcessingError)
|
||||||
class ProjectNotFound < ProcessingError; end
|
ProjectNotFound = Class.new(ProcessingError)
|
||||||
class EmptyEmailError < ProcessingError; end
|
EmptyEmailError = Class.new(ProcessingError)
|
||||||
class AutoGeneratedEmailError < ProcessingError; end
|
AutoGeneratedEmailError = Class.new(ProcessingError)
|
||||||
class UserNotFoundError < ProcessingError; end
|
UserNotFoundError = Class.new(ProcessingError)
|
||||||
class UserBlockedError < ProcessingError; end
|
UserBlockedError = Class.new(ProcessingError)
|
||||||
class UserNotAuthorizedError < ProcessingError; end
|
UserNotAuthorizedError = Class.new(ProcessingError)
|
||||||
class NoteableNotFoundError < ProcessingError; end
|
NoteableNotFoundError = Class.new(ProcessingError)
|
||||||
class InvalidNoteError < ProcessingError; end
|
InvalidNoteError = Class.new(ProcessingError)
|
||||||
class InvalidIssueError < ProcessingError; end
|
InvalidIssueError = Class.new(ProcessingError)
|
||||||
class UnknownIncomingEmail < ProcessingError; end
|
UnknownIncomingEmail = Class.new(ProcessingError)
|
||||||
|
|
||||||
class Receiver
|
class Receiver
|
||||||
def initialize(raw)
|
def initialize(raw)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
module Gitlab
|
module Gitlab
|
||||||
module Git
|
module Git
|
||||||
class Diff
|
class Diff
|
||||||
class TimeoutError < StandardError; end
|
TimeoutError = Class.new(StandardError)
|
||||||
include Gitlab::Git::EncodingHelper
|
include Gitlab::Git::EncodingHelper
|
||||||
|
|
||||||
# Diff properties
|
# Diff properties
|
||||||
|
|
|
@ -10,9 +10,9 @@ module Gitlab
|
||||||
|
|
||||||
SEARCH_CONTEXT_LINES = 3
|
SEARCH_CONTEXT_LINES = 3
|
||||||
|
|
||||||
class NoRepository < StandardError; end
|
NoRepository = Class.new(StandardError)
|
||||||
class InvalidBlobName < StandardError; end
|
InvalidBlobName = Class.new(StandardError)
|
||||||
class InvalidRef < StandardError; end
|
InvalidRef = Class.new(StandardError)
|
||||||
|
|
||||||
# Full path to repo
|
# Full path to repo
|
||||||
attr_reader :path
|
attr_reader :path
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
module Gitlab
|
module Gitlab
|
||||||
module ImportExport
|
module ImportExport
|
||||||
class Error < StandardError; end
|
Error = Class.new(StandardError)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#
|
#
|
||||||
module Gitlab
|
module Gitlab
|
||||||
module OAuth
|
module OAuth
|
||||||
class SignupDisabledError < StandardError; end
|
SignupDisabledError = Class.new(StandardError)
|
||||||
|
|
||||||
class User
|
class User
|
||||||
attr_accessor :auth_hash, :gl_user
|
attr_accessor :auth_hash, :gl_user
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module Gitlab
|
module Gitlab
|
||||||
class RouteMap
|
class RouteMap
|
||||||
class FormatError < StandardError; end
|
FormatError = Class.new(StandardError)
|
||||||
|
|
||||||
def initialize(data)
|
def initialize(data)
|
||||||
begin
|
begin
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
module Gitlab
|
module Gitlab
|
||||||
module Serializer
|
module Serializer
|
||||||
class Pagination
|
class Pagination
|
||||||
class InvalidResourceError < StandardError; end
|
InvalidResourceError = Class.new(StandardError)
|
||||||
include ::API::Helpers::Pagination
|
include ::API::Helpers::Pagination
|
||||||
|
|
||||||
def initialize(request, response)
|
def initialize(request, response)
|
||||||
|
|
|
@ -2,7 +2,7 @@ require 'securerandom'
|
||||||
|
|
||||||
module Gitlab
|
module Gitlab
|
||||||
class Shell
|
class Shell
|
||||||
class Error < StandardError; end
|
Error = Class.new(StandardError)
|
||||||
|
|
||||||
KeyAdder = Struct.new(:io) do
|
KeyAdder = Struct.new(:io) do
|
||||||
def add_key(id, key)
|
def add_key(id, key)
|
||||||
|
|
|
@ -4,7 +4,7 @@ module Gitlab
|
||||||
module Finders
|
module Finders
|
||||||
class RepoTemplateFinder < BaseTemplateFinder
|
class RepoTemplateFinder < BaseTemplateFinder
|
||||||
# Raised when file is not found
|
# Raised when file is not found
|
||||||
class FileNotFoundError < StandardError; end
|
FileNotFoundError = Class.new(StandardError)
|
||||||
|
|
||||||
def initialize(project, base_dir, extension, categories = {})
|
def initialize(project, base_dir, extension, categories = {})
|
||||||
@categories = categories
|
@categories = categories
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
module Gitlab
|
module Gitlab
|
||||||
class UpdatePathError < StandardError; end
|
UpdatePathError = Class.new(StandardError)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
module Mattermost
|
module Mattermost
|
||||||
class ClientError < Mattermost::Error; end
|
ClientError = Class.new(Mattermost::Error)
|
||||||
|
|
||||||
class Client
|
class Client
|
||||||
attr_reader :user
|
attr_reader :user
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
module Mattermost
|
module Mattermost
|
||||||
class Error < StandardError; end
|
Error = Class.new(StandardError)
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,7 +5,7 @@ module Mattermost
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class ConnectionError < Mattermost::Error; end
|
ConnectionError = Class.new(Mattermost::Error)
|
||||||
|
|
||||||
# This class' prime objective is to obtain a session token on a Mattermost
|
# This class' prime objective is to obtain a session token on a Mattermost
|
||||||
# instance with SSO configured where this GitLab instance is the provider.
|
# instance with SSO configured where this GitLab instance is the provider.
|
||||||
|
|
64
rubocop/cop/custom_error_class.rb
Normal file
64
rubocop/cop/custom_error_class.rb
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
module RuboCop
|
||||||
|
module Cop
|
||||||
|
# This cop makes sure that custom error classes, when empty, are declared
|
||||||
|
# with Class.new.
|
||||||
|
#
|
||||||
|
# @example
|
||||||
|
# # bad
|
||||||
|
# class FooError < StandardError
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # okish
|
||||||
|
# class FooError < StandardError; end
|
||||||
|
#
|
||||||
|
# # good
|
||||||
|
# FooError = Class.new(StandardError)
|
||||||
|
class CustomErrorClass < RuboCop::Cop::Cop
|
||||||
|
MSG = 'Use `Class.new(SuperClass)` to define an empty custom error class.'.freeze
|
||||||
|
|
||||||
|
def on_class(node)
|
||||||
|
_klass, parent, body = node.children
|
||||||
|
|
||||||
|
return if body
|
||||||
|
|
||||||
|
parent_klass = class_name_from_node(parent)
|
||||||
|
|
||||||
|
return unless parent_klass && parent_klass.to_s.end_with?('Error')
|
||||||
|
|
||||||
|
add_offense(node, :expression)
|
||||||
|
end
|
||||||
|
|
||||||
|
def autocorrect(node)
|
||||||
|
klass, parent, _body = node.children
|
||||||
|
replacement = "#{class_name_from_node(klass)} = Class.new(#{class_name_from_node(parent)})"
|
||||||
|
|
||||||
|
lambda do |corrector|
|
||||||
|
corrector.replace(node.source_range, replacement)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# The nested constant `Foo::Bar::Baz` looks like:
|
||||||
|
#
|
||||||
|
# s(:const,
|
||||||
|
# s(:const,
|
||||||
|
# s(:const, nil, :Foo), :Bar), :Baz)
|
||||||
|
#
|
||||||
|
# So recurse through that to get the name as written in the source.
|
||||||
|
#
|
||||||
|
def class_name_from_node(node, suffix = nil)
|
||||||
|
return unless node&.type == :const
|
||||||
|
|
||||||
|
name = node.children[1].to_s
|
||||||
|
name = "#{name}::#{suffix}" if suffix
|
||||||
|
|
||||||
|
if node.children[0]
|
||||||
|
class_name_from_node(node.children[0], name)
|
||||||
|
else
|
||||||
|
name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,3 +1,4 @@
|
||||||
|
require_relative 'cop/custom_error_class'
|
||||||
require_relative 'cop/gem_fetcher'
|
require_relative 'cop/gem_fetcher'
|
||||||
require_relative 'cop/migration/add_column'
|
require_relative 'cop/migration/add_column'
|
||||||
require_relative 'cop/migration/add_column_with_default'
|
require_relative 'cop/migration/add_column_with_default'
|
||||||
|
|
111
spec/rubocop/cop/custom_error_class_spec.rb
Normal file
111
spec/rubocop/cop/custom_error_class_spec.rb
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
require 'rubocop'
|
||||||
|
require 'rubocop/rspec/support'
|
||||||
|
|
||||||
|
require_relative '../../../rubocop/cop/custom_error_class'
|
||||||
|
|
||||||
|
describe RuboCop::Cop::CustomErrorClass do
|
||||||
|
include CopHelper
|
||||||
|
|
||||||
|
subject(:cop) { described_class.new }
|
||||||
|
|
||||||
|
context 'when a class has a body' do
|
||||||
|
it 'does nothing' do
|
||||||
|
inspect_source(cop, 'class CustomError < StandardError; def foo; end; end')
|
||||||
|
|
||||||
|
expect(cop.offenses).to be_empty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when a class has no explicit superclass' do
|
||||||
|
it 'does nothing' do
|
||||||
|
inspect_source(cop, 'class CustomError; end')
|
||||||
|
|
||||||
|
expect(cop.offenses).to be_empty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when a class has a superclass that does not end in Error' do
|
||||||
|
it 'does nothing' do
|
||||||
|
inspect_source(cop, 'class CustomError < BasicObject; end')
|
||||||
|
|
||||||
|
expect(cop.offenses).to be_empty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when a class is empty and inherits from a class ending in Error' do
|
||||||
|
context 'when the class is on a single line' do
|
||||||
|
let(:source) do
|
||||||
|
<<-SOURCE
|
||||||
|
module Foo
|
||||||
|
class CustomError < Bar::Baz::BaseError; end
|
||||||
|
end
|
||||||
|
SOURCE
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:expected) do
|
||||||
|
<<-EXPECTED
|
||||||
|
module Foo
|
||||||
|
CustomError = Class.new(Bar::Baz::BaseError)
|
||||||
|
end
|
||||||
|
EXPECTED
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'registers an offense' do
|
||||||
|
expected_highlights = source.split("\n")[1].strip
|
||||||
|
|
||||||
|
inspect_source(cop, source)
|
||||||
|
|
||||||
|
aggregate_failures do
|
||||||
|
expect(cop.offenses.size).to eq(1)
|
||||||
|
expect(cop.offenses.map(&:line)).to eq([2])
|
||||||
|
expect(cop.highlights).to contain_exactly(expected_highlights)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'autocorrects to the right version' do
|
||||||
|
autocorrected = autocorrect_source(cop, source, 'foo/custom_error.rb')
|
||||||
|
|
||||||
|
expect(autocorrected).to eq(expected)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the class is on multiple lines' do
|
||||||
|
let(:source) do
|
||||||
|
<<-SOURCE
|
||||||
|
module Foo
|
||||||
|
class CustomError < Bar::Baz::BaseError
|
||||||
|
end
|
||||||
|
end
|
||||||
|
SOURCE
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:expected) do
|
||||||
|
<<-EXPECTED
|
||||||
|
module Foo
|
||||||
|
CustomError = Class.new(Bar::Baz::BaseError)
|
||||||
|
end
|
||||||
|
EXPECTED
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'registers an offense' do
|
||||||
|
expected_highlights = source.split("\n")[1..2].join("\n").strip
|
||||||
|
|
||||||
|
inspect_source(cop, source)
|
||||||
|
|
||||||
|
aggregate_failures do
|
||||||
|
expect(cop.offenses.size).to eq(1)
|
||||||
|
expect(cop.offenses.map(&:line)).to eq([2])
|
||||||
|
expect(cop.highlights).to contain_exactly(expected_highlights)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'autocorrects to the right version' do
|
||||||
|
autocorrected = autocorrect_source(cop, source, 'foo/custom_error.rb')
|
||||||
|
|
||||||
|
expect(autocorrected).to eq(expected)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue