diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-12-17 14:59:07 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-12-17 14:59:07 +0300 |
commit | 8b573c94895dc0ac0e1d9d59cf3e8745e8b539ca (patch) | |
tree | 544930fb309b30317ae9797a9683768705d664c4 /rubocop/cop/graphql/descriptions.rb | |
parent | 4b1de649d0168371549608993deac953eb692019 (diff) |
Add latest changes from gitlab-org/gitlab@13-7-stable-eev13.7.0-rc42
Diffstat (limited to 'rubocop/cop/graphql/descriptions.rb')
-rw-r--r-- | rubocop/cop/graphql/descriptions.rb | 60 |
1 files changed, 46 insertions, 14 deletions
diff --git a/rubocop/cop/graphql/descriptions.rb b/rubocop/cop/graphql/descriptions.rb index b4e00dfe336..1585e5c9788 100644 --- a/rubocop/cop/graphql/descriptions.rb +++ b/rubocop/cop/graphql/descriptions.rb @@ -13,42 +13,74 @@ # argument :some_argument, GraphQL::STRING_TYPE # end # +# class UngoodClass +# field :some_argument, +# GraphQL::STRING_TYPE, +# description: "A description that does not end in a period" +# end +# # # good # class GreatClass # argument :some_field, # GraphQL::STRING_TYPE, -# description: "Well described - a superb description" +# description: "Well described - a superb description." # # field :some_field, # GraphQL::STRING_TYPE, -# description: "A thorough and compelling description" +# description: "A thorough and compelling description." # end module RuboCop module Cop module Graphql class Descriptions < RuboCop::Cop::Cop - MSG = 'Please add a `description` property.' + MSG_NO_DESCRIPTION = 'Please add a `description` property.' + MSG_NO_PERIOD = '`description` strings must end with a `.`.' # ability_field and permission_field set a default description. - def_node_matcher :fields, <<~PATTERN - (send nil? :field $...) - PATTERN - - def_node_matcher :arguments, <<~PATTERN - (send nil? :argument $...) + def_node_matcher :field_or_argument?, <<~PATTERN + (send nil? {:field :argument} ...) PATTERN - def_node_matcher :has_description?, <<~PATTERN - (hash <(pair (sym :description) _) ...>) + def_node_matcher :description, <<~PATTERN + (... (hash <(pair (sym :description) $_) ...>)) PATTERN def on_send(node) - matches = fields(node) || arguments(node) + return unless field_or_argument?(node) + + description = description(node) + + return add_offense(node, location: :expression, message: MSG_NO_DESCRIPTION) unless description + + add_offense(node, location: :expression, message: MSG_NO_PERIOD) if no_period?(description) + end + + # Autocorrect missing periods at end of description. + def autocorrect(node) + lambda do |corrector| + description = description(node) + next unless description + + corrector.insert_after(before_end_quote(description), '.') + end + end + + private + + def no_period?(description) + # Test that the description node is a `:str` (as opposed to + # a `#copy_field_description` call) before checking. + description.type == :str && !description.value.strip.end_with?('.') + end - return if matches.nil? + # Returns a Parser::Source::Range that ends just before the final String delimiter. + def before_end_quote(string) + return string.source_range.adjust(end_pos: -1) unless string.heredoc? - add_offense(node, location: :expression) unless has_description?(matches.last) + heredoc_source = string.location.heredoc_body.source + adjust = heredoc_source.index(/\s+\Z/) - heredoc_source.length + string.location.heredoc_body.adjust(end_pos: adjust) end end end |