Skip to content

Commit

Permalink
First version
Browse files Browse the repository at this point in the history
  • Loading branch information
cedeber committed Sep 7, 2024
1 parent 1b7bc4c commit 9a697f1
Show file tree
Hide file tree
Showing 10 changed files with 3,647 additions and 0 deletions.
37 changes: 37 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Test

on:
push:
branches:
- main
pull_request:
branches:
- main

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
test:
name: Node.js ${{ matrix.node-version }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
node-version:
- 22
- 20
- 18
os:
- ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npx ava
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.DS_Store
node_modules
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"editor.formatOnSave": true
}
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# eslint-plugin-throw

ESLint plugin to enforce function naming and JSDoc annotations for functions that throw
18 changes: 18 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import eslintPlugin from "eslint-plugin-eslint-plugin";
import nodePlugin from "eslint-plugin-n";

/** @type import("eslint").Linter.Config[] */
export default [
eslintPlugin.configs["flat/recommended"],
nodePlugin.configs["flat/recommended-script"],
{
parserOptions: {
ecmaVersion: 2021,
sourceType: "module",
},
rules: {
"eslint-plugin/require-meta-docs-description": "error",
"n/exports-style": ["error", "module.exports"],
},
},
];
49 changes: 49 additions & 0 deletions lib/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import fs from "fs";

const pkg = JSON.parse(
fs.readFileSync(new URL("./package.json", import.meta.url), "utf8")
);

/**
* @type {import("eslint").ESLint.Plugin}
*/
const plugin = {
meta: {
name: pkg.name,
version: pkg.version,
},
configs: {},
rules: {
"throw-documentation": {
create(context) {
// rule implementation ...
},
},
},
processors: {},
};

Object.assign(plugin.configs, {
recommended: [
{
plugins: {
"eslint-plugin-throw": plugin,
},
rules: {
"eslint-plugin-throw/throw-documentation": "error",
},
languageOptions: {
globals: {
myGlobal: "readonly",
},
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
},
},
],
});

export default plugin;
52 changes: 52 additions & 0 deletions lib/rules/throw-documentation.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* @type {import("eslint").Rule.RuleModule}
*/
export default {
meta: {
type: "suggestion",
docs: {
description:
"Enforce JSDoc @throws tag for functions that throw exceptions",
category: "Best Practices",
recommended: "error",
},
messages: {
missingThrows:
"Function throws an exception but lacks a @throws tag in JSDoc.",
},
schema: [], // no options
},
create(context) {
return {
FunctionDeclaration(node) {
const sourceCode = context.sourceCode;
const jsDocComment = sourceCode.getJSDocComment(node);

// if (!jsDocComment) return; // If there's no JSDoc, skip

const hasThrow = node.body.body.some(
(statement) => statement.type === "ThrowStatement"
);

if (hasThrow) {
// Missing JSDoc @throws
if (!jsDocComment) {
context.report({
node: node,
messageId: "missingThrows",
});
return;
}

const throwsTag = jsDocComment.value.includes("@throws");
if (!throwsTag) {
context.report({
node: node,
messageId: "missingThrows",
});
}
}
},
};
},
};
32 changes: 32 additions & 0 deletions lib/tests/throw-documentation.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import test from "ava";
import AvaRuleTester from "eslint-ava-rule-tester";
import rule from "../rules/throw-documentation.mjs";

const ruleTester = new AvaRuleTester(test, {
languageOptions: { ecmaVersion: 2021, sourceType: "module" },
});

ruleTester.run("throw-documentation", rule, {
valid: [
{
code: `
/**
* @throws {Error}
*/
function test() {
throw new Error('test');
}
`,
},
],
invalid: [
{
code: `
function test() {
throw new Error('test');
}
`,
errors: [{ messageId: "missingThrows" }],
},
],
});
Loading

0 comments on commit 9a697f1

Please sign in to comment.