diff --git a/config/default.yml b/config/default.yml index 5848d3b..a4ade21 100644 --- a/config/default.yml +++ b/config/default.yml @@ -299,6 +299,11 @@ SketchupSuggestions/AddGroup: Reference: https://github.com/SketchUp/rubocop-sketchup/tree/main/manual/cops_suggestions.md#addgroup Enabled: true +SketchupSuggestions/CommandTitle: + Description: Use title case for command titles. + Reference: https://github.com/SketchUp/rubocop-sketchup/tree/main/manual/cops_suggestions.md#commandtitle + Enabled: true + SketchupSuggestions/Compatibility: Description: Incompatible feature with target SketchUp version. Reference: https://github.com/SketchUp/rubocop-sketchup/tree/main/manual/cops_suggestions.md#compatibility diff --git a/lib/rubocop/sketchup/cop/suggestions/command_title.rb b/lib/rubocop/sketchup/cop/suggestions/command_title.rb new file mode 100644 index 0000000..b49806e --- /dev/null +++ b/lib/rubocop/sketchup/cop/suggestions/command_title.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module SketchupSuggestions + # SketchUp command titles should be in title case, e.g. "Make Component" + # and "Follow Me". + # + # In English, capitalize the first letter of each word. Other languages + # may have different rules. + class CommandTitle < SketchUp::Cop + + def_node_matcher :init_entity?, <<-PATTERN + (send (const (const nil? :UI) :Command ) :new ... ) + PATTERN + + MESSAGE = 'Use title case in command titles. ' \ + 'In English, capitalize the first letter of each word.' + + def on_send(node) + return unless init_entity?(node) + return if node.arguments.first.str_content.nil? + return if title_case?(node.arguments.first.str_content) + + add_offense(node, message: MESSAGE) + end + + private + + # REVIEW: Extract to where they can be re-used? + def title_case?(text) + text == title_case(text) + end + + def title_case(text) + text.gsub(/^(.)/) { ::Regexp.last_match(1).upcase } + .gsub(/\ (.)/) { " #{::Regexp.last_match(1).upcase}" } + .gsub(/-(.)/) { "-#{::Regexp.last_match(1).upcase}" } + .gsub(/(\.)$/, '') + end + end + end + end +end diff --git a/manual/cops.md b/manual/cops.md index d300c7c..aace3c2 100644 --- a/manual/cops.md +++ b/manual/cops.md @@ -91,6 +91,7 @@ In the following section you find all available cops: #### Department [SketchupSuggestions](cops_suggestions.md) * [SketchupSuggestions/AddGroup](cops_suggestions.md#sketchupsuggestionsaddgroup) +* [SketchupSuggestions/CommandTitle](cops_suggestions.md#sketchupsuggestionscommandtitle) * [SketchupSuggestions/Compatibility](cops_suggestions.md#sketchupsuggestionscompatibility) * [SketchupSuggestions/DynamicComponentInternals](cops_suggestions.md#sketchupsuggestionsdynamiccomponentinternals) * [SketchupSuggestions/FileEncoding](cops_suggestions.md#sketchupsuggestionsfileencoding) diff --git a/manual/cops_suggestions.md b/manual/cops_suggestions.md index bb30347..4862578 100644 --- a/manual/cops_suggestions.md +++ b/manual/cops_suggestions.md @@ -40,6 +40,23 @@ face2 = group.entities.add_face(points2) * [https://github.com/SketchUp/rubocop-sketchup/tree/main/manual/cops_suggestions.md#addgroup](https://github.com/SketchUp/rubocop-sketchup/tree/main/manual/cops_suggestions.md#addgroup) + +## SketchupSuggestions/CommandTitle + +Enabled by default | Supports autocorrection +--- | --- +Enabled | No + +SketchUp command titles should be in title case, e.g. "Make Component" +and "Follow Me". + +In English, capitalize the first letter of each word. Other languages +may have different rules. + +### References + +* [https://github.com/SketchUp/rubocop-sketchup/tree/main/manual/cops_suggestions.md#commandtitle](https://github.com/SketchUp/rubocop-sketchup/tree/main/manual/cops_suggestions.md#commandtitle) + ## SketchupSuggestions/Compatibility diff --git a/spec/rubocop/cop/sketchup_suggestions/command_title_spec.rb b/spec/rubocop/cop/sketchup_suggestions/command_title_spec.rb new file mode 100644 index 0000000..ea3fdb0 --- /dev/null +++ b/spec/rubocop/cop/sketchup_suggestions/command_title_spec.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe RuboCop::Cop::SketchupSuggestions::CommandTitle, :config do + + bad_capitalization = [ + 'text', + 'text text', + 'Text text', + 'text Text', + 'Text.', + 'Text Text.', + 'Text text.', + 'text 2-Point', + 'text 2-point' + ] + + bad_capitalization.each do |keyword| + it "registers an offense when using UI::Command.new(\"#{keyword}\")" do + expect_offense(<<~RUBY, keyword: keyword) + UI::Command.new("%{keyword}") + ^^^^^^^^^^^^^^^^^^{keyword}^^ Use title case in command titles. [...] + RUBY + end + + # TODO: Add for setter methods. + # Can we test by how a local variable was defined? Or only by its name? + # + # command = UI::Command.new("Test") + # command.menu_text = "%{keyword}" + # + # menu.add_item("%{keyword}") + end + + good_capitalization = [ + 'Text', + 'Text Text', + 'Text 2-Point', + '文本' + ] + + good_capitalization.each do |keyword| + it "does not register an offense when using UI::Command.new(\"#{keyword}\")" do + expect_no_offenses(<<~RUBY, keyword: keyword) + UI::Command.new("%{keyword}") + RUBY + end + end + + it 'does not register an offense when using UI::Command.new(variable)' do + expect_no_offenses(<<~RUBY) + UI::Command.new(variable) + RUBY + end + +end