From 30b478f1cd67f5ef167093ce9a8d0a36a4f4f65f Mon Sep 17 00:00:00 2001 From: alex Date: Wed, 16 Jul 2025 15:50:51 -0400 Subject: [PATCH] preview/ast-grep --- .coderabbit.yaml | 13 +++ greet.js | 104 ++++++++++++++++++ jsx_ast_grep_failure.ts | 22 ++++ rules/no-console-except-error.yml | 14 +++ ...-unnecessary-type-definition-use-state.yml | 7 ++ rules/ts-const.yaml | 15 +++ 6 files changed, 175 insertions(+) create mode 100644 .coderabbit.yaml create mode 100644 greet.js create mode 100644 jsx_ast_grep_failure.ts create mode 100644 rules/no-console-except-error.yml create mode 100644 rules/replace-unnecessary-type-definition-use-state.yml create mode 100644 rules/ts-const.yaml diff --git a/.coderabbit.yaml b/.coderabbit.yaml new file mode 100644 index 0000000..091996f --- /dev/null +++ b/.coderabbit.yaml @@ -0,0 +1,13 @@ +# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json +early_access: true +reviews: + path_instructions: + - path: "**/*.{js,ts}" + instructions: "Ensure that all constant variables are defined using UPPER CASE letters" + tools: + ast-grep: + rule_dirs: + - "rules" + - "test-missing-dir" + packages: + - "test-peter-rabbit/test-ast-grep-custom-package" diff --git a/greet.js b/greet.js new file mode 100644 index 0000000..8cf8aa8 --- /dev/null +++ b/greet.js @@ -0,0 +1,104 @@ +/** + * Prints a greeting to the console. + * @param {string} name + * @param {string} surname + */ +export function greet(name, surname) { + console.log(`Hello, ${name} ${surname}!`) +} + +/** + * Prints a welcome message to the console. + * @param {string} name + * @param {string} surname + */ +export function welcome(name, surname) { + console.log(`Welcome, ${name} ${surname}!`) +} + +import React from 'react' +import PropTypes from 'prop-types' + +function HelloWorld({ + greeting = "hello", + greeted = '"World"', + silent = false, + onMouseOver, +}) { + if (!greeting) { + console.log("No greeting") + return null + } + + // TODO: Don't use random in render + const num = Math.floor(Math.random() * 1e7) + .toString() + .replace(/.d+/gi, "") + + return ( +
+ + {greeting.slice(0, 1).toUpperCase() + greeting.slice(1).toLowerCase()} + + {greeting.endsWith(",") ? ( + " " + ) : ( + ", " + )} + {greeted} + {silent ? "." : "!"} +
+ ) +} + +HelloWorld.propTypes = { + greeting: PropTypes.string, + greeted: PropTypes.string, + silent: PropTypes.bool, + onMouseOver: PropTypes.func, +} + +/** + * Fails ast-grep because of console.log used in the function + * @param {string} text + * @param {string} string + * @returns {boolean} + */ +export function findInString(text, string, logFn = console.error) { + logFn("text", text) + return text.includes(string) +} + return text.includes(string) +} + +/** + * Fails ast-grep because of console.log used in the catch block + * @param {string} text + * @param {string} string + * @returns {boolean} + */ +export async function findInStringAsync(text, string) { + try { + return text.includes(string) + } catch (error) { + console.log("error", error) + } +} + +/** + * Doesn't fail ast-grep since console.error is allowed in catch block + * @param {string} text + * @param {string} string + * @returns {boolean} + */ +export async function findInStringTreated(text, string) { + try { + return text.includes(string) + } catch (error) { + console.error("error", error) + } +} diff --git a/jsx_ast_grep_failure.ts b/jsx_ast_grep_failure.ts new file mode 100644 index 0000000..1109dac --- /dev/null +++ b/jsx_ast_grep_failure.ts @@ -0,0 +1,22 @@ +import { useState } from 'react' + +const greeting: string = "Hello, world!"; + +async function test() { + + const [state, setState] = useState("test string") + + const [state2, setState2] = useState("test string") + + const [first, second] = await Promise.all([ + await (new Promise(() => {console.log("logging this long task")})), + new Promise(() => {console.log("logging another long task")}), + ]) + + return { + state, + setState, + first, + second + } +} diff --git a/rules/no-console-except-error.yml b/rules/no-console-except-error.yml new file mode 100644 index 0000000..151c955 --- /dev/null +++ b/rules/no-console-except-error.yml @@ -0,0 +1,14 @@ +id: no-console-except-error +language: javascript +message: 'Do not use console.$METHOD except for console.error in catch clause' +rule: + any: + - pattern: console.error($$$) + not: + inside: + kind: catch_clause + stopBy: end + - pattern: console.$METHOD($$$) +constraints: + METHOD: + regex: 'log|debug|warn' \ No newline at end of file diff --git a/rules/replace-unnecessary-type-definition-use-state.yml b/rules/replace-unnecessary-type-definition-use-state.yml new file mode 100644 index 0000000..7582fa9 --- /dev/null +++ b/rules/replace-unnecessary-type-definition-use-state.yml @@ -0,0 +1,7 @@ +id: replace-unnecessary-type-definition-use-state +language: "typescript" +rule: + any: + - pattern: useState($A) +fix: + useState($A) diff --git a/rules/ts-const.yaml b/rules/ts-const.yaml new file mode 100644 index 0000000..b271478 --- /dev/null +++ b/rules/ts-const.yaml @@ -0,0 +1,15 @@ +id: ts-const +language: Typescript +rule: + all: + - any: + - pattern: "const $VAR: $TYPE = $VALUE" + - pattern: "const $VAR = $VALUE" + - inside: + kind: program +constraints: + VAR: + regex: '.*[^A-Z_].*' +severity: warning +message: Always capitalize const variables +note: Const variables should be capitalized