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