From bab56ca316a5049dcc7612ca4ddd89e1dc1146c8 Mon Sep 17 00:00:00 2001 From: Eneroth Date: Tue, 18 Apr 2023 16:11:03 +0200 Subject: [PATCH 1/7] Fix #145 Add cop for bad command title capitalization --- config/default.yml | 5 ++ .../sketchup/cop/suggestions/command_title.rb | 43 +++++++++++++++ manual/cops.md | 1 + manual/cops_suggestions.md | 17 ++++++ .../command_title_spec.rb | 53 +++++++++++++++++++ 5 files changed, 119 insertions(+) create mode 100644 lib/rubocop/sketchup/cop/suggestions/command_title.rb create mode 100644 spec/rubocop/cop/sketchup_suggestions/command_title_spec.rb 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..ce16d30 --- /dev/null +++ b/lib/rubocop/sketchup/cop/suggestions/command_title.rb @@ -0,0 +1,43 @@ +# 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 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..e282602 --- /dev/null +++ b/spec/rubocop/cop/sketchup_suggestions/command_title_spec.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe RuboCop::Cop::SketchupSuggestions::CommandTitle do + + subject(:cop) { described_class.new } + + 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 + +end From 7eee0a21b02a9e3b0a76230049cffaa7343960e7 Mon Sep 17 00:00:00 2001 From: Eneroth Date: Wed, 19 Apr 2023 15:59:39 +0200 Subject: [PATCH 2/7] Fix false positive when using variable instead of string token --- lib/rubocop/sketchup/cop/suggestions/command_title.rb | 1 + spec/rubocop/cop/sketchup_suggestions/command_title_spec.rb | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/lib/rubocop/sketchup/cop/suggestions/command_title.rb b/lib/rubocop/sketchup/cop/suggestions/command_title.rb index ce16d30..9d276a6 100644 --- a/lib/rubocop/sketchup/cop/suggestions/command_title.rb +++ b/lib/rubocop/sketchup/cop/suggestions/command_title.rb @@ -19,6 +19,7 @@ class CommandTitle < SketchUp::Cop 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) diff --git a/spec/rubocop/cop/sketchup_suggestions/command_title_spec.rb b/spec/rubocop/cop/sketchup_suggestions/command_title_spec.rb index e282602..96da4f1 100644 --- a/spec/rubocop/cop/sketchup_suggestions/command_title_spec.rb +++ b/spec/rubocop/cop/sketchup_suggestions/command_title_spec.rb @@ -50,4 +50,10 @@ 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 From b5ef4f16d879285452034e65d2f5d4225f05e4f5 Mon Sep 17 00:00:00 2001 From: Eneroth Date: Mon, 24 Apr 2023 14:01:40 +0200 Subject: [PATCH 3/7] Fuck it all --- .../sketchup/cop/suggestions/command_title.rb | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/rubocop/sketchup/cop/suggestions/command_title.rb b/lib/rubocop/sketchup/cop/suggestions/command_title.rb index 9d276a6..8db1314 100644 --- a/lib/rubocop/sketchup/cop/suggestions/command_title.rb +++ b/lib/rubocop/sketchup/cop/suggestions/command_title.rb @@ -28,15 +28,28 @@ def on_send(node) private # REVIEW: Extract to where they can be re-used? + + # Test if string is in title case + # (first letter of each word capitalized and no trailing period.) def title_case?(text) - text == title_case(text) + text == title_case(text) && text[-1] != '.' end + # Capitalize the worst letter of each word (including after a hyphen). def title_case(text) + ### text.gsub(/\b\w/, &:capitalize) + + # Capitalize the first letter of the string, the first letter after + # each space and first letter after each hyphen. + # + # This code has an identical result as the commented out line above + # except that the above line gives false positives for the cop + # which is impossible as they both act fucking identically when tested + # separetely. + # Fuck the whole fucking universe. text.gsub(/^(.)/) { ::Regexp.last_match(1).upcase } .gsub(/\ (.)/) { " #{::Regexp.last_match(1).upcase}" } .gsub(/-(.)/) { "-#{::Regexp.last_match(1).upcase}" } - .gsub(/(\.)$/, '') end end end From 1ae795cfbdfddaf97ee6624ea14c2910450e1e15 Mon Sep 17 00:00:00 2001 From: Eneroth Date: Mon, 24 Apr 2023 14:02:58 +0200 Subject: [PATCH 4/7] Fuck the fuck --- lib/rubocop/sketchup/cop/suggestions/command_title.rb | 8 -------- 1 file changed, 8 deletions(-) diff --git a/lib/rubocop/sketchup/cop/suggestions/command_title.rb b/lib/rubocop/sketchup/cop/suggestions/command_title.rb index 8db1314..f9fefb5 100644 --- a/lib/rubocop/sketchup/cop/suggestions/command_title.rb +++ b/lib/rubocop/sketchup/cop/suggestions/command_title.rb @@ -37,16 +37,8 @@ def title_case?(text) # Capitalize the worst letter of each word (including after a hyphen). def title_case(text) - ### text.gsub(/\b\w/, &:capitalize) - # Capitalize the first letter of the string, the first letter after # each space and first letter after each hyphen. - # - # This code has an identical result as the commented out line above - # except that the above line gives false positives for the cop - # which is impossible as they both act fucking identically when tested - # separetely. - # Fuck the whole fucking universe. text.gsub(/^(.)/) { ::Regexp.last_match(1).upcase } .gsub(/\ (.)/) { " #{::Regexp.last_match(1).upcase}" } .gsub(/-(.)/) { "-#{::Regexp.last_match(1).upcase}" } From 099a42e854bb0d5c2d34eb24dc503351cbbbe055 Mon Sep 17 00:00:00 2001 From: Eneroth Date: Mon, 24 Apr 2023 14:29:15 +0200 Subject: [PATCH 5/7] Reset the fuck --- lib/rubocop/sketchup/cop/suggestions/command_title.rb | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/lib/rubocop/sketchup/cop/suggestions/command_title.rb b/lib/rubocop/sketchup/cop/suggestions/command_title.rb index f9fefb5..9d276a6 100644 --- a/lib/rubocop/sketchup/cop/suggestions/command_title.rb +++ b/lib/rubocop/sketchup/cop/suggestions/command_title.rb @@ -28,20 +28,15 @@ def on_send(node) private # REVIEW: Extract to where they can be re-used? - - # Test if string is in title case - # (first letter of each word capitalized and no trailing period.) def title_case?(text) - text == title_case(text) && text[-1] != '.' + text == title_case(text) end - # Capitalize the worst letter of each word (including after a hyphen). def title_case(text) - # Capitalize the first letter of the string, the first letter after - # each space and first letter after each hyphen. text.gsub(/^(.)/) { ::Regexp.last_match(1).upcase } .gsub(/\ (.)/) { " #{::Regexp.last_match(1).upcase}" } .gsub(/-(.)/) { "-#{::Regexp.last_match(1).upcase}" } + .gsub(/(\.)$/, '') end end end From 8cb1817304fcb884b6490a8b6f16e3c20d7586ea Mon Sep 17 00:00:00 2001 From: Eneroth Date: Thu, 27 Apr 2023 17:23:35 +0200 Subject: [PATCH 6/7] Stuff --- spec/rubocop/cop/sketchup_suggestions/command_title_spec.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/spec/rubocop/cop/sketchup_suggestions/command_title_spec.rb b/spec/rubocop/cop/sketchup_suggestions/command_title_spec.rb index 96da4f1..ea3fdb0 100644 --- a/spec/rubocop/cop/sketchup_suggestions/command_title_spec.rb +++ b/spec/rubocop/cop/sketchup_suggestions/command_title_spec.rb @@ -2,9 +2,7 @@ require 'spec_helper' -describe RuboCop::Cop::SketchupSuggestions::CommandTitle do - - subject(:cop) { described_class.new } +describe RuboCop::Cop::SketchupSuggestions::CommandTitle, :config do bad_capitalization = [ 'text', From c81c5b820849613af716720a32c07173da214453 Mon Sep 17 00:00:00 2001 From: Eneroth Date: Thu, 27 Apr 2023 17:28:01 +0200 Subject: [PATCH 7/7] Commit message --- lib/rubocop/sketchup/cop/suggestions/command_title.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rubocop/sketchup/cop/suggestions/command_title.rb b/lib/rubocop/sketchup/cop/suggestions/command_title.rb index 9d276a6..b49806e 100644 --- a/lib/rubocop/sketchup/cop/suggestions/command_title.rb +++ b/lib/rubocop/sketchup/cop/suggestions/command_title.rb @@ -14,7 +14,7 @@ class CommandTitle < SketchUp::Cop (send (const (const nil? :UI) :Command ) :new ... ) PATTERN - MESSAGE = 'Use title case in command titles. '\ + MESSAGE = 'Use title case in command titles. ' \ 'In English, capitalize the first letter of each word.' def on_send(node)