diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-12-11 15:10:04 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-12-11 15:10:04 +0000 |
commit | a8704bd33cb36b4e7e88bb10d61265b8ad8a058c (patch) | |
tree | 4a9eb565d016d789168657fadbc78214afb61725 /rubocop/cop | |
parent | 54f170b69972d46a5bab2a0231510a41e610da31 (diff) | |
download | gitlab-ce-a8704bd33cb36b4e7e88bb10d61265b8ad8a058c.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'rubocop/cop')
-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 |