Fanclub
und fan_club
sind im Code gemischt ... Ich denke, es ist üblich. Ich würde es gerne mit denen vereinen, die sagen, dass dies derjenige im Team ist, aber ich habe nicht genug Gedächtnis im Kopf, um mich an solche Regeln zu erinnern ... Es ist auch eine gute Idee, Leute darauf hinweisen zu lassen, und ich möchte es einem Computer überlassen, der viele Male geduldig darauf hinweist.
Also habe ich ein custom_cop für [Rubocop] erstellt (https://github.com/rubocop-hq/rubocop).
Übrigens, auch wenn Sie keine so mühsame Arbeit verwenden, scheint es einfacher zu sein, mit dem Hauptzweig nach dem Diff zu suchen. Aber ich wollte custom_cop
schreiben. Es ist ein Sonntagsprogramm, oder?
Wenn Sie versuchen zu definieren, was Sie wollen, so weit Sie verstehen können ... Ist es so? Schlüsselwörter nehmen während der Anwendungsentwicklung um ein Vielfaches zu, daher möchte ich sie in einer externen Datei definieren.
Listen Sie die falschen Wörter und die Wörter, die Sie korrigieren möchten, in der YAML-Datei auf, weisen Sie auf falsche Wörter hin und korrigieren Sie sie.
Wie auch immer, es ist nicht interessant, wenn es nicht funktioniert, also werde ich mein Bestes geben, um Folgendes zu erreichen: point_down :.
Weisen Sie darauf hin, ob der Wert, den Sie in die Variable eingeben, das falsche Wort fanclub ist
Bereiten Sie Code vor, der überprüft werden kann, wenn rubocop ausgeführt wird. Ich denke, der Code der Anwendung, die Sie tatsächlich verwenden, ist in Ordnung.
target.rb
a = 'fanclub'
custom_cop :cop:
Ich habe es fast durch Kopieren geschafft. Wie auch immer, ich hoffe du kannst dich so bewegen.
lib/custom_cops/spell_inconsistency.rb
# frozen_string_literal: true
module CustomCops
class SpellInconsistency < RuboCop::Cop::Cop
WRONG_KEYWORD = 'fanclub'.freeze
def on_str(node)
add_offense(node, message: "Use 'fan_club' instead of 'fanclub'.") if node.source.include?(WRONG_KEYWORD)
end
end
end
.rubocop.yml :wrench:
Stellen Sie das erstellte custom_cop so ein, dass es von rubocop verwendet werden kann.
yaml:.rubocop.yml
require:
- './lib/custom_cops/spell_inconsistency'
Bei Ausführung mit rubocop target.rb
...
Zusätzlich zum Hinweis "Ich verwende Variablen nicht nur zur Definition" oder "Da es sich um eine Konstante handelt, frieren Sie sie bitte ein" ... "CustomCops / SpellInconsistency: Verwenden Sie" fan_club "anstelle von" fanclub " !!
Ich möchte es auf die in YAML registrierte erweitern.
Weisen Sie darauf hin, ob der Wert, den Sie in die Variable eingeben, das falsche Wort in der YAML-Datei ist
spell_inconsistency.yml :wrench:
Registrieren Sie hier "Fanclub", "Fanclub" und "FANCLUB". In Zukunft möchte ich sie in zwei Worten schreiben: "fan_club", "FanClub" und "FAN_CLUB".
lib/custom_cops/spell_inconsistency.yml
# Wrong: Correct
fanclub: fan_club
Fanclub: Fanclub
FANCLUB: FAN_CLUB
target.rb
a = 'fanclub'
b = 'Fanclub'
c = 'FANCLUB'
custom_cop :cop:
Die Datei, in der das Wort registriert ist, wird von "YAML.load_file" gelesen und durch Drehen um "each" überprüft.
lib/custom_cops/spell_inconsistency.rb
# frozen_string_literal: true
require 'yaml'
module CustomCops
class SpellInconsistency < RuboCop::Cop::Cop
MESSAGE_TEMPLATE = "Use '%s' instead of '%s'."
SPELL_INCONSISTENCIES = YAML.load_file(Pathname(__dir__).join('spell_inconsistency.yml'))
def on_str(node)
SPELL_INCONSISTENCIES.each do |wrong_keyword, correct_keyword|
add_offense(node, message: message(wrong_keyword, correct_keyword)) if node.source.include?(wrong_keyword)
end
end
private
def message(wrong_keyword, correct_keyword)
MESSAGE_TEMPLATE % [correct_keyword, wrong_keyword]
end
end
end
Wenn Sie es mit "rubocop target.rb" ausführen, gibt es viele zusätzliche Nachrichten. Wenn Sie also nur Ihren eigenen custom_cop wie "rubocop --only CustomCops / SpellInconsistency target.rb" angeben und ausführen ...
Oh, es sieht gut aus: Daumen hoch:
Machen Sie dasselbe, wenn Sie Symbole oder Konstanten ersetzen, die einer Zeichenfolge sehr ähnlich sehen.
target.rb
a = 'Fanclub'
b = :fanclub
c = FANCLUB
custom_cop :cop:
Schauen Sie sich vor dem Schreiben [RuboCop :: AST :: Traversal
] an (https://github.com/rubocop-hq/rubocop-ast/blob/master/lib/rubocop/ast/traversal.rb).
Unmittelbar nach dem Anzeigen von # walk
Es sieht so aus, als würden Sie eine Methode mit diesem Namen aufrufen und den Knotentyp betrachten, den Sie überquert haben.
Es scheint also, dass mein # on_str
auch aufgerufen wurde.
lib/rubocop/ast/traversal.rb
def walk(node)
return if node.nil?
send(:"on_#{node.type}", node)
nil
end
Ich habe die ganze Datei durchsucht und so "const" und "sym" gefunden, also habe ich beschlossen, auch "# on_sym" und "on_const" zu implementieren. Die Inspektionsmethode ist genau die gleiche, definieren Sie sie also mit define_method
.
lib/custom_cops/spell_inconsistency.rb
# frozen_string_literal: true
require 'yaml'
module CustomCops
class SpellInconsistency < RuboCop::Cop::Cop
MESSAGE_TEMPLATE = "Use '%s' instead of '%s'."
SPELL_INCONSISTENCIES = YAML.load_file(Pathname(__dir__).join('spell_inconsistency.yml'))
NODE_TYPES = %I[str const sym].freeze
NODE_TYPES.each do |node_type|
define_method "on_#{node_type}" do |node|
SPELL_INCONSISTENCIES.each do |wrong_keyword, correct_keyword|
add_offense(node, message: message(wrong_keyword, correct_keyword)) if node.source.include?(wrong_keyword)
end
end
end
def message(wrong_keyword, correct_keyword)
MESSAGE_TEMPLATE % [correct_keyword, wrong_keyword]
end
end
end
Bei Ausführung als rubocop - nur CustomCops / SpellInconsistency target.rb
...
Sieht gut aus: +1:
Nachdem wir nun Zeichenfolgen, Symbole und Konstanten haben, lassen Sie sie darauf hinweisen, wenn wir das falsche Wort für den Variablennamen verwenden.
target.rb
a = 'Fanclub'
b = :fanclub
c = FANCLUB
fanclub = 'a'
Apropos Variablen, "Variable" wäre "var" ... Also, [RuboCop :: AST :: Traversal
](https://github.com/rubocop-hq/rubocop-ast/blob/master/lib Ich habe mir (/rubocop/ast/traversal.rb) angesehen, aber ... es gibt nicht viel davon ...
In Development Basic der offiziellen RuboCop-Dokumentation heißt es, "Ruby-Parse" in der Befehlszeile zu verwenden. Ich verstehe.
Es war "lvasgn".
Zu NODE_TYPES
hinzufügen ...
lib/custom_cops/spell_inconsistency.rb
(Kürzung)
module CustomCops
class SpellInconsistency < RuboCop::Cop::Cop
(Kürzung)
NODE_TYPES = %I[str const sym lvasgn].freeze
NODE_TYPES.each do |node_type|
define_method "on_#{node_type}" do |node|
SPELL_INCONSISTENCIES.each do |wrong_keyword, correct_keyword|
add_offense(node, message: message(wrong_keyword, correct_keyword)) if node.source.include?(wrong_keyword)
end
end
end
(Kürzung)
end
end
Wenn Sie rubocop ausführen - nur CustomCops / SpellInconsistency target.rb
...
fanclub = 'a'
wurde erkannt ... a =' FanClub
wurde ebenfalls erkannt ...
Schauen wir uns den Originalcode und die Ausgabe von Ruby-Parse genauer an.
(lvasgn :fanclub
(str "a"))
Die Zuordnung zu einer Variablen lautet "Variablenname = Ausdruck", nicht wahr? Ich frage mich, ob der Ausdruck der Zeichenkette "a" entspricht.
Wenn Sie es so betrachten, ist lvasgn
der linke Wert ein Zeichen
für die Zuordnung auf der linken Seite.
(Da es vor langer Zeit eine Syntaxanalyse in einer Universitätsklasse gab, kann ich sie nicht erklären, aber ich kann sie nicht auf einer Ebene erklären, die ich verstehen kann ... Es tut mir leid.)
(Substitution auf der linken Seite:fanclub
(String"a"))
Der Grund, warum ich zweimal mit "fanclub =" a "feststeckte, war, dass es auf" fanclub "von" str "und auf" fanclub "von" str "in" lvasgn "reagierte. Wahrscheinlich von.
(lvasgn :a
(str "fanclub"))
Es scheint, dass Sie es nur unmittelbar nach "lvasgn" einnehmen sollten.
Wenn Sie das offizielle Dokument Development Basic von RuboCop lesen, sehen Sie die Methoden, die häufig im Argument node
of on_ ~
verwendet werden. War dort. Sie sollten "Kinder" verwenden und das erste Kind verwenden.
node.type # => :send
node.children # => [s(:send, s(:send, nil, :something), :empty?), :!]
node.source # => "!something.empty?"
custom_cop :cop: Abgesehen von "str", "const", "sym" habe ich "on_lvasgn" gemacht, um das erste Kind zu inspizieren.
lib/custom_cops/spell_inconsistency.rb
(Kürzung)
module CustomCops
class SpellInconsistency < RuboCop::Cop::Cop
(Kürzung)
NODE_TYPES = %I[str const sym].freeze
NODE_TYPES.each do |node_type|
define_method "on_#{node_type}" do |node|
SPELL_INCONSISTENCIES.each do |wrong_keyword, correct_keyword|
add_offense(node, message: message(wrong_keyword, correct_keyword)) if node.source.include?(wrong_keyword)
end
end
end
def on_lvasgn(node)
target = node.children.first
SPELL_INCONSISTENCIES.each do |wrong_keyword, correct_keyword|
add_offense(node, message: message(wrong_keyword, correct_keyword)) if target.match?(/#{wrong_keyword}/)
end
end
(Kürzung)
end
end
Bei Ausführung als rubocop - nur CustomCops / SpellInconsistency target.rb
...
Sieht gut aus: tada:
Was wir bisher gemacht haben, ist ... Strings, Symbole, Konstanten und Variablennamen zu überprüfen. In Anbetracht der Syntax von Ruby ... Es gibt Methoden- und Klassennamen, um die Teile zu finden, die behandelt werden sollten. Sie werden danach etwas bemerken ... Dann war es mühsam, den Code einzeln zur Inspektion auszuführen, deshalb wollte ich einen Test schreiben.
Die Dateien unter "spec / support" sind "erforderlich". Es scheint, dass Personen, die versuchen, die Anwendung später aufzurufen, häufig bereits eingerichtet sind.
spec/spec_helper.rb
RSpec.configure do |config|
(Kürzung)
Dir["#{__dir__}/support/**/*.rb"].sort.each { |f| require f }
end
Ich lade die RSpec-Unterstützung für Rubocop und lade das von mir hinzugefügte custom_cop.
spec/support/rubocop.rb
# frozen_string_literal: true
require 'rubocop'
require 'rubocop/rspec/support'
Dir["#{__dir__}/../../lib/**/*.rb"].sort.each { |f| require f }
RSpec.configure do |config|
config.include(RuboCop::RSpec::ExpectOffense)
end
Der im Prüfzielcode geschriebene Code wird in den Test übertragen, und es wird auch beschrieben, wie die Ausgabe bei der Ausführung von Rubocop ausgeführt wird.
spec/lib/custom_cops/spell_inconstency_spec.rb
# frozen_string_literal: true
RSpec.describe CustomCops::SpellInconsistency do
subject(:cop) { described_class.new }
it 'Fehler in Zeichenketten erkennen können' do
expect_offense(<<-RUBY)
fan_club = 'fanclub'
^^^^^^^^^ Use 'fan_club' instead of 'fanclub'.
RUBY
end
it 'Fehler in Symbolen erkennen können' do
expect_offense(<<-RUBY)
fan_club = :fanclub
^^^^^^^^ Use 'fan_club' instead of 'fanclub'.
RUBY
end
it 'Ständige Fehler erkennen können' do
expect_offense(<<-RUBY)
fan_club = FANCLUB
^^^^^^^ Use 'FAN_CLUB' instead of 'FANCLUB'.
RUBY
end
it 'Fehler in Variablennamen erkennen können' do
expect_offense(<<-RUBY)
fanclub = 'fan_club'
^^^^^^^^^^^^^^^^^^^^ Use 'fan_club' instead of 'fanclub'.
RUBY
end
end
Bei Ausführung mit rspec spec / lib / custom_cops / Zauber_inconstency_spec.rb
...
Sieht gut aus: Daumen hoch:
Ich habe die Variablen definiert, aber ich habe die Konstanten noch nicht definiert, also werde ich es tun.
Funktionscode für Konstanten- und Methodendefinitionen.
target.rb
FANCLUB = 'a'
ruby-parse
Mit "Ruby-Parse" analysieren.
Die konstante Definition ist "casgn", ein anderes Format als "lvasgn". Es war der zweite.
custom_cop :cop: Ich habe eine Prüfmethode für "casgn" erstellt.
lib/custom_cops/spell_inconsistency.rb
(Kürzung)
module CustomCops
class SpellInconsistency < RuboCop::Cop::Cop
(Kürzung)
def on_casgn(node)
target = node.children[1]
SPELL_INCONSISTENCIES.each do |wrong_keyword, correct_keyword|
add_offense(node, message: message(wrong_keyword, correct_keyword)) if target.match?(/#{wrong_keyword}/)
end
end
(Kürzung)
end
end
Bei Ausführung als rubocop - nur CustomCops / SpellInconsistency target.rb
...
Sieht gut aus: Daumen hoch:
Fügen Sie es dem Test hinzu, damit Sie feststellen, ob es kaputt geht.
spec/lib/custom_cops/spell_inconstency_spec.rb
# frozen_string_literal: true
RSpec.describe CustomCops::SpellInconsistency do
subject(:cop) { described_class.new }
(Kürzung)
it 'Fehler in konstanten Namen erkennen können' do
expect_offense(<<-RUBY)
FANCLUB = 'fan_club'
^^^^^^^^^^^^^^^^^^^^ Use 'FAN_CLUB' instead of 'FANCLUB'.
RUBY
end
end
Zu diesem Zeitpunkt habe ich das Verfahren irgendwie verstanden.
Wiederholen Sie diesen Vorgang, um die Erkennungsgenauigkeit zu verbessern.
Wir werden ihm bei der Definition der Methode einen Namen geben. Schauen wir uns das an. Da es viele Elemente in einer Zeile gibt und es viele Arten von Elementen gibt, werden wir sie in kleine Stücke schneiden.
In Anbetracht eines kurzen Codeteils sieht es aus wie "def set_fanclub; hoge; end".
Ruby-Parse betrachten ...
Das erste "Kind" von "def" ist so. Es ähnelt dem lvasgn
, das beim Zuweisen zu einer Variablen verwendet wird.
Verwenden Sie wie bei "str" und "const" "define_method" in einer Schleife, um sie zu gruppieren.
lib/custom_cops/spell_inconsistency.rb
(Kürzung)
module CustomCops
class SpellInconsistency < RuboCop::Cop::Cop
(Kürzung)
NODE_TYPES_ONE = %I[str const sym].freeze
NODE_TYPES_FIRST_CHILD = %I[lvasgn def].freeze
NODE_TYPES_ONE.each do |node_type|
define_method "on_#{node_type}" do |node|
SPELL_INCONSISTENCIES.each do |wrong_keyword, correct_keyword|
add_offense(node, message: message(wrong_keyword, correct_keyword)) if node.source.include?(wrong_keyword)
end
end
end
NODE_TYPES_FIRST_CHILD.each do |node_type|
define_method "on_#{node_type}" do |node|
target = node.children.first
SPELL_INCONSISTENCIES.each do |wrong_keyword, correct_keyword|
add_offense(node, message: message(wrong_keyword, correct_keyword)) if target.match?(/#{wrong_keyword}/)
end
end
end
(Kürzung)
end
end
Das Argument ist "arg", das die gleiche Form wie "lvasgn" hat, also werden wir es zusammenfassen.
lib/custom_cops/spell_inconsistency.rb
(Kürzung)
module CustomCops
class SpellInconsistency < RuboCop::Cop::Cop
(Kürzung)
NODE_TYPES_FIRST_CHILD = %I[lvasgn def arg].freeze
(Kürzung)
end
end
Sie können den Argumenten Standardwerte zuweisen, aber da sie mit "str", "sym" bzw. "const" identisch sind, fügen Sie nichts hinzu.
Das Schlüsselwortargument lautet "kwarg" und hat dieselbe Form wie "lvasgn". Wir werden es also zusammenfassen.
lib/custom_cops/spell_inconsistency.rb
(Kürzung)
module CustomCops
class SpellInconsistency < RuboCop::Cop::Cop
(Kürzung)
NODE_TYPES_FIRST_CHILD = %I[lvasgn def arg kwarg].freeze
(Kürzung)
end
end
Wenn der Standardwert für das Schlüsselwortargument angegeben wird, lautet der Argumentname "kwoptarg". Dies ist die gleiche Form wie "lvasgn", daher werden wir ihn zusammenfassen.
lib/custom_cops/spell_inconsistency.rb
(Kürzung)
module CustomCops
class SpellInconsistency < RuboCop::Cop::Cop
(Kürzung)
NODE_TYPES_FIRST_CHILD = %I[lvasgn def arg kwarg kwoptarg].freeze
(Kürzung)
end
end
Ich erinnerte mich an das Schlüsselwortargument der Methodendefinition. Es wurde von demselben Symbol unterstützt.
Der Klassenname und der Modulname waren const
.
Ich bin so weit gekommen ... Ich habe das Gefühl, dass es immer noch viele Auslassungen gibt. Da ich jedoch einen Test schreibe, habe ich das Gefühl, dass ich ihn basierend auf dem, was mir aufgefallen ist, schrittweise erweitern kann.
Aber ... es war super einfach, aber es war wahnsinnig schwierig. Auf keinen Fall werde ich die Syntaxanalyse beißen ... Ich habe mich jedoch mit [Rubocop] angefreundet (https://github.com/rubocop-hq/rubocop). Wenn Sie eine Regel erstellen möchten, an die Sie sich mit Ihrem Arbeitscode nicht erinnern können, werde ich es versuchen.