diff --git a/tools/gitlint-rules.py b/tools/gitlint-rules.py index 709372b..4af0f85 100644 --- a/tools/gitlint-rules.py +++ b/tools/gitlint-rules.py @@ -10,276 +10,70 @@ from gitlint.rules import CommitMessageTitle, LineRule, RuleViolation # Copyright (c) 2015 Mike Foley # License: MIT # Ref: fit_commit/validators/tense.rb -WORD_SET = { - "adds", - "adding", - "added", - "allows", - "allowing", - "allowed", - "amends", - "amending", - "amended", - "bumps", - "bumping", - "bumped", - "calculates", - "calculating", - "calculated", - "changes", - "changing", - "changed", - "cleans", - "cleaning", - "cleaned", - "commits", - "committing", - "committed", - "corrects", - "correcting", - "corrected", - "creates", - "creating", - "created", - "darkens", - "darkening", - "darkened", - "disables", - "disabling", - "disabled", - "displays", - "displaying", - "displayed", - "documents", - "documenting", - "documented", - "drys", - "drying", - "dryed", - "ends", - "ending", - "ended", - "enforces", - "enforcing", - "enforced", - "enqueues", - "enqueuing", - "enqueued", - "extracts", - "extracting", - "extracted", - "finishes", - "finishing", - "finished", - "fixes", - "fixing", - "fixed", - "formats", - "formatting", - "formatted", - "guards", - "guarding", - "guarded", - "handles", - "handling", - "handled", - "hides", - "hiding", - "hid", - "increases", - "increasing", - "increased", - "ignores", - "ignoring", - "ignored", - "implements", - "implementing", - "implemented", - "improves", - "improving", - "improved", - "keeps", - "keeping", - "kept", - "kills", - "killing", - "killed", - "makes", - "making", - "made", - "merges", - "merging", - "merged", - "moves", - "moving", - "moved", - "permits", - "permitting", - "permitted", - "prevents", - "preventing", - "prevented", - "pushes", - "pushing", - "pushed", - "rebases", - "rebasing", - "rebased", - "refactors", - "refactoring", - "refactored", - "removes", - "removing", - "removed", - "renames", - "renaming", - "renamed", - "reorders", - "reordering", - "reordered", - "replaces", - "replacing", - "replaced", - "requires", - "requiring", - "required", - "restores", - "restoring", - "restored", - "sends", - "sending", - "sent", - "sets", - "setting", - "separates", - "separating", - "separated", - "shows", - "showing", - "showed", - "simplifies", - "simplifying", - "simplified", - "skips", - "skipping", - "skipped", - "sorts", - "sorting", - "speeds", - "speeding", - "sped", - "starts", - "starting", - "started", - "supports", - "supporting", - "supported", - "takes", - "taking", - "took", - "testing", - "tested", # 'tests' excluded to reduce false negative - "truncates", - "truncating", - "truncated", - "updates", - "updating", - "updated", - "uses", - "using", - "used", -} - -imperative_forms = [ - "add", - "allow", - "amend", - "bump", - "calculate", - "change", - "clean", - "commit", - "correct", - "create", - "darken", - "disable", - "display", - "document", - "dry", - "end", - "enforce", - "enqueue", - "extract", - "finish", - "fix", - "format", - "guard", - "handle", - "hide", - "ignore", - "implement", - "improve", - "increase", - "keep", - "kill", - "make", - "merge", - "move", - "permit", - "prevent", - "push", - "rebase", - "refactor", - "remove", - "rename", - "reorder", - "replace", - "require", - "restore", - "send", - "separate", - "set", - "show", - "simplify", - "skip", - "sort", - "speed", - "start", - "support", - "take", - "test", - "truncate", - "update", - "use", +TENSE_DATA = [ + (["adds", "adding", "added"], "add"), + (["allows", "allowing", "allowed"], "allow"), + (["amends", "amending", "amended"], "amend"), + (["bumps", "bumping", "bumped"], "bump"), + (["calculates", "calculating", "calculated"], "calculate"), + (["changes", "changing", "changed"], "change"), + (["cleans", "cleaning", "cleaned"], "clean"), + (["commits", "committing", "committed"], "commit"), + (["corrects", "correcting", "corrected"], "correct"), + (["creates", "creating", "created"], "create"), + (["darkens", "darkening", "darkened"], "darken"), + (["disables", "disabling", "disabled"], "disable"), + (["displays", "displaying", "displayed"], "display"), + (["documents", "documenting", "documented"], "document"), + (["drys", "drying", "dryed"], "dry"), + (["ends", "ending", "ended"], "end"), + (["enforces", "enforcing", "enforced"], "enforce"), + (["enqueues", "enqueuing", "enqueued"], "enqueue"), + (["extracts", "extracting", "extracted"], "extract"), + (["finishes", "finishing", "finished"], "finish"), + (["fixes", "fixing", "fixed"], "fix"), + (["formats", "formatting", "formatted"], "format"), + (["guards", "guarding", "guarded"], "guard"), + (["handles", "handling", "handled"], "handle"), + (["hides", "hiding", "hid"], "hide"), + (["increases", "increasing", "increased"], "increase"), + (["ignores", "ignoring", "ignored"], "ignore"), + (["implements", "implementing", "implemented"], "implement"), + (["improves", "improving", "improved"], "improve"), + (["keeps", "keeping", "kept"], "keep"), + (["kills", "killing", "killed"], "kill"), + (["makes", "making", "made"], "make"), + (["merges", "merging", "merged"], "merge"), + (["moves", "moving", "moved"], "move"), + (["permits", "permitting", "permitted"], "permit"), + (["prevents", "preventing", "prevented"], "prevent"), + (["pushes", "pushing", "pushed"], "push"), + (["rebases", "rebasing", "rebased"], "rebase"), + (["refactors", "refactoring", "refactored"], "refactor"), + (["removes", "removing", "removed"], "remove"), + (["renames", "renaming", "renamed"], "rename"), + (["reorders", "reordering", "reordered"], "reorder"), + (["replaces", "replacing", "replaced"], "replace"), + (["requires", "requiring", "required"], "require"), + (["restores", "restoring", "restored"], "restore"), + (["sends", "sending", "sent"], "send"), + (["sets", "setting"], "set"), + (["separates", "separating", "separated"], "separate"), + (["shows", "showing", "showed"], "show"), + (["simplifies", "simplifying", "simplified"], "simplify"), + (["skips", "skipping", "skipped"], "skip"), + (["sorts", "sorting"], "sort"), + (["speeds", "speeding", "sped"], "speed"), + (["starts", "starting", "started"], "start"), + (["supports", "supporting", "supported"], "support"), + (["takes", "taking", "took"], "take"), + (["testing", "tested"], "test"), # "tests" excluded to reduce false negatives + (["truncates", "truncating", "truncated"], "truncate"), + (["updates", "updating", "updated"], "update"), + (["uses", "using", "used"], "use"), ] -imperative_forms.sort() - -def head_binary_search(key: str, words: List[str]) -> str: - """Find the imperative mood version of `word` by looking at the first - 3 characters.""" - - # Edge case: 'disable' and 'display' have the same 3 starting letters. - if key in ["displays", "displaying", "displayed"]: - return "display" - - lower = 0 - upper = len(words) - 1 - - while True: - if lower > upper: - # Should not happen - raise Exception(f"Cannot find imperative mood of {key}") - - mid = (lower + upper) // 2 - imperative_form = words[mid] - - if key[:3] == imperative_form[:3]: - return imperative_form - elif key < imperative_form: - upper = mid - 1 - elif key > imperative_form: - lower = mid + 1 +TENSE_CORRECTIONS = {word: imperative for words, imperative in TENSE_DATA for word in words} class ImperativeMood(LineRule): @@ -303,8 +97,8 @@ class ImperativeMood(LineRule): words = line.split(": ", 1)[-1].split() first_word = words[0].lower() - if first_word in WORD_SET: - imperative = head_binary_search(first_word, imperative_forms) + if first_word in TENSE_CORRECTIONS: + imperative = TENSE_CORRECTIONS[first_word] violation = RuleViolation( self.id, self.error_msg.format(