shard-ameba/src/ameba/rule/base.cr

101 lines
2.3 KiB
Crystal
Raw Normal View History

2017-11-07 21:50:25 +00:00
module Ameba::Rule
SPECIAL = [
Syntax.class_name,
UnneededDisableDirective.class_name,
]
2017-11-15 18:49:09 +00:00
# Represents a base of all rules. In other words, all rules
# inherits from this struct:
#
# ```
# struct MyRule < Ameba::Rule::Base
# def test(source)
# if invalid?(source)
# source.error self, location, "Something wrong."
# end
# end
#
# private def invalid?(source)
# # ...
# end
# end
# ```
#
# Enforces rules to implement an abstract `#test` method which
# is designed to test the source passed in. If source has issues
# that are tested by this rule, it should add an error.
#
2017-11-07 21:50:25 +00:00
abstract struct Base
2017-11-23 17:49:45 +00:00
include Config::RuleConfig
2017-11-13 21:20:22 +00:00
2017-11-15 18:49:09 +00:00
# This method is designed to test the source passed in. If source has issues
# that are tested by this rule, it should add an error.
2017-10-30 20:00:01 +00:00
abstract def test(source : Source)
def test(source : Source, node : Crystal::ASTNode)
# can't be abstract
end
2017-11-15 18:49:09 +00:00
# A convenient addition to `#test` method that does the same
# but returns a passed in `source` as an addition.
#
# ```
# source = MyRule.new.catch(source)
# source.valid?
# ```
#
2017-10-30 20:00:01 +00:00
def catch(source : Source)
source.tap { |s| test s }
end
2017-11-15 18:49:09 +00:00
# Returns a name of this rule, which is basically a class name.
#
# ```
# struct MyRule < Ameba::Rule::Base
# def test(source)
# end
# end
#
# MyRule.new.name # => "MyRule"
# ```
#
2017-10-30 20:00:01 +00:00
def name
2017-11-22 06:44:29 +00:00
{{@type}}.class_name
end
2017-12-18 11:06:19 +00:00
# Checks whether the source is excluded from this rule.
# It searches for a path in `excluded` property which matches
# the one of the given source.
#
# ```
# my_rule.excluded?(source) # => true or false
# ```
#
def excluded?(source)
excluded.try &.any? do |path|
# TODO: file pattern match
source.path == path || source.fullpath == File.expand_path(path)
end
end
2017-11-22 06:44:29 +00:00
protected def self.class_name
name.gsub("Ameba::Rule::", "")
2017-10-30 20:00:01 +00:00
end
2017-11-01 10:49:03 +00:00
2017-11-07 21:50:25 +00:00
protected def self.subclasses
2017-11-01 10:49:03 +00:00
{{ @type.subclasses }}
end
2017-10-30 20:00:01 +00:00
end
2017-11-07 21:50:25 +00:00
2018-01-25 09:50:11 +00:00
# Returns a list of all available rules
# (except a `Rule::Syntax` which is a special rule).
2017-11-15 18:49:09 +00:00
#
# ```
# Ameba::Rule.rules # => [LineLength, ConstantNames, ....]
# ```
#
2017-11-07 21:50:25 +00:00
def self.rules
2018-01-25 09:50:11 +00:00
Base.subclasses.reject! &.== Rule::Syntax
2017-11-07 21:50:25 +00:00
end
2017-10-30 20:00:01 +00:00
end