checkr vs-code extension + git hook 🔍Write lint rules fast.
InstallationExtensionSearch for "checkr" in the VS Code extensions tab (Ctrl+Shift+X to open). Pre-commit hook
That's it! WhyLinting is a powerful tool for enforcing project consistency and finding common issues. Many tools such as ESLint, JSHint, and others exist for this purpose. However, they do not have project specific rules, and writing a custom eslint-rule requires more setup and prior knowledge than a A checkr rule results in less code review nits and catches bugs. HowOn file save and open, checkr looks for a This means you can put global checks in the project root A Each function is passed the
example
|
Token | Matches | Query | Example Match |
---|---|---|---|
$a | variable | if ($a == $b) return { $a; } | if (foo == bar) { return foo; } |
$1 | literal | $1 + $2 + $1 + $2 | 5 + "four" + 5 + "four" |
$@ | operator | 5 $@ops1 10 $@ 15 $@ops1 33 | 5 * 10 + 15 * 33 |
$# | keyword | $# ($a == true) | do (baz == true) |
$$ | non-greedy any | if ($a $$ $a) { $$ return 33; } | if (foo, bar, foo) { getFoo(); getBar(); return 33; } |
$$$ | greedy any | case $1: $$$ case $2: throw; | case "Apples": return 1; case "Bananas": throw; case "Mangos": throw; |
REGEX(...) | regex escape hatch | REGEX(3+9+2*) 5 + 5 | 33922225+5 |
Variable matchers: `$a`, `$Abcd`, `$foobar55` ✔️ `$`, `$44a`, `$^` ❌
Literal matchers: `$1`, `$2`, `$333` ✔️ `$`, `$az1`, `$\` ❌
Operator matchers: `$@`, `$@a`, `$@Operator22` ✔️ `$@@`, `$@2`, `$@%` ❌
Keyword matchers: `$#`, `$#keyword`, `$#Key1` ✔️ `$#@`, `$#5`, `$##` ❌
While code
returns a RegExp
, it also adds two methods to the returned object.
.matchAll(str)
returns all the captured results in an easy format, or an empty array for no matches.
code`$#w ($a + $1) { return $$; }`.matchAll(`
do(foo + "baz") {
return getBar();
}`);
// returns
[
{
blocks: ['getBar()'],
keywords: ['do'],
literals: ['"baz"'],
operators: [],
others: [],
variables: ['foo'],
},
];
.matchFirst(str)
returns the first captured result.
Note if there is nothing to capture or no matches, it will return an object with empty arrays.
// Match, but no capture groups specified, eg $a, $1, $#k, etc.
code`foo = bar;`.matchFirst(`foo = bar;`);
// No match.
code`foo = bar;`.matchFirst(`nomatch`);
// both return
{
blocks: [],
keywords: [],
literals: [],
operators: [],
others: [],
variables: [],
}
Examples
[
function requirePropDestructing({ fileContents, underline, code }) {
const underlineComponents = match => {
if (!match.blocks[2].includes('= props;'))
underline(code`${match.variables[0]}($$ props $$)`, "❌ `props` must be destructed.", "error");
}
code`function $a($$ props $$) { $$$ }`
.matchAll(fileContents)
.forEach(underlineComponents);
},
function requireButtonTypeAttribute({ fileContents, underline, code }) {
const underlineInvalidButtons = match => match
.blocks
.filter(x => !x.includes('type='))
.forEach(x => underline(x, "⚠️ `type` should be on buttons.", "warn"));
code`<button $$>`
.matchAll(fileContents)
.forEach(underlineInvalidButtons);
},
function enforceBooleanPropNaming({ fileContents, underline, code }) {
const underlineInvalidBooleanNames = match => {
const is = match.variables[0].startsWith("is");
const has = match.variables[0].startsWith("has");
const should = match.variables[0].startsWith("should");
const isRecommended = is || has || should;
const hoverMessage = "💬 Consider prefix with 'is', 'has', or 'should'.";
if (!isRecommended)
underline(code`${match.variables[0]}: PropTypes.bool$$`, hoverMessage, "info");
};
code`$a: PropTypes.bool$$`
.matchAll(fileContents)
.forEach(underlineInvalidBooleanNames)
}
];
Best Practices
- Verify an ESLint rule for the problem doesn't already exist.
- Prefer writing a custom ESLint rule for complicated checks.
- Avoid solving problems with linters that may be better handled with other methods.
- Prefer checks that are actionable and accurate over 90% of the time.
More best practices here.
Test code
patterns here.
Test regex patterns here.
Contributing
All improvements are welcome. When opening a PR or updating the wiki feel free to add your name to the contributors.md and an emoji if you'd like, so your name can be immortalized until the end of time!
Feel free to take any ideas or invent your own:
import
support incheckr.js
files.- Adding useful checks to the
examples/
folder. - More options to run at intervals or on other events.
- Optimizations such as file caching.
To debug the extension:
git clone
the repo.- Install
yarn
and run in it the project root. Seepackage.json
for a full list of commands. - Run
yarn watch
to compile the TypeScript into JavaScript and "watch" for any file changes. - Open the project in VS code, and press
F5
. Ctrl+R
in the debug window reloads the extension.
Contact
cs@eriklanning.com