Skip to content
This repository has been archived by the owner on Dec 25, 2023. It is now read-only.

Commit

Permalink
Add support for custom rules dirs (#75)
Browse files Browse the repository at this point in the history
* Add support for custom rules dirs

Resolves #68

* Changelog

* Add a bunch of test files for custom rules

* Work around directory mangling issue

* add link to eslint config docs

* Improve console output when linting fails

* changelog

* format
  • Loading branch information
apexskier authored Jan 25, 2021
1 parent 9a166e2 commit 135760c
Show file tree
Hide file tree
Showing 14 changed files with 155 additions and 13 deletions.
10 changes: 10 additions & 0 deletions ESLint.novaextension/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## future

### Added

- Support custom rules directories

### Changed

- Improved Preferences meta-info

## v1.6.0

### Added
Expand Down
26 changes: 22 additions & 4 deletions ESLint.novaextension/extension.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,21 @@
},
{
"key": "apexskier.eslint.config.eslintPath",
"title": "Path to ESLint executable",
"title": "ESLint executable",
"type": "path"
},
{
"key": "apexskier.eslint.config.eslintConfigPath",
"title": "Path to ESLint configuration",
"title": "ESLint configuration",
"type": "path"
},
{
"key": "apexskier.eslint.config.eslintRulesDirs",
"title": "Rules directories",
"link": "https://eslint.org/docs/user-guide/command-line-interface#-rulesdir",
"type": "pathArray",
"allowFiles": false,
"allowFolders": true
}
],

Expand All @@ -54,15 +62,25 @@
},
{
"key": "apexskier.eslint.config.eslintPath",
"title": "Path to ESLint executable",
"title": "ESLint executable",
"type": "path",
"relative": true
},
{
"key": "apexskier.eslint.config.eslintConfigPath",
"title": "Path to ESLint configuration",
"title": "ESLint configuration",
"link": "https://eslint.org/docs/user-guide/configuring#configuration-file-formats",
"type": "path",
"relative": true
},
{
"key": "apexskier.eslint.config.eslintRulesDirs",
"title": "Rules directories",
"link": "https://eslint.org/docs/user-guide/command-line-interface#-rulesdir",
"type": "pathArray",
"relative": true,
"allowFiles": false,
"allowFolders": true
}
],

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"concurrently": "^5.3.0",
"eslint": "^7.18.0",
"eslint-config-prettier": "^7.2.0",
"eslint-plugin-custom-rules": "file:./test/rules-1/custom-rules",
"eslint-plugin-html": "^6.1.1",
"eslint-plugin-markdown": "^2.0.0-rc.1",
"eslint-plugin-nova": "^1.3.0",
Expand Down
35 changes: 35 additions & 0 deletions src/getRulesDirs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// returns custom eslint rules directories
export function getRulesDirs(): Array<string> | null {
const rulesDirs: Array<string> =
nova.config.get("apexskier.eslint.config.eslintRulesDirs", "array") ?? [];
const workspaceRulesDirs = nova.workspace.config.get(
"apexskier.eslint.config.eslintRulesDirs",
"array"
);
if (workspaceRulesDirs) {
for (const dir of workspaceRulesDirs) {
if (!dir.trim()) {
continue;
}
if (nova.path.isAbsolute(dir)) {
rulesDirs.push(dir);
} else if (nova.workspace.path) {
rulesDirs.push(nova.path.join(nova.workspace.path, dir));
} else {
nova.workspace.showErrorMessage(
"Save your workspace before using a relative ESLint rules directories."
);
return null;
}
}
}

return (
rulesDirs
.filter((d) => d.trim())
// hack - JSON stringifying works around https://github.com/eslint/eslint/issues/14025 by forcing levn to parse as a string, not a regex
// I could try to strip the `/Volumes/Macintosh HD` from Nova's workspace dir, but that would have to be
// conditional, since global settings won't include it. This feels simpler, although it could break if eslint's options parsing changes
.map((d) => JSON.stringify(d))
);
}
46 changes: 37 additions & 9 deletions src/process.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import type { Linter, ESLint } from "eslint";
import { getEslintPath } from "./getEslintPath";
import { getEslintConfig } from "./getEslintConfig";
import { getRulesDirs } from "./getRulesDirs";

let eslintPath: string | null = null;
let eslintConfigPath: string | null = null;
let eslintRulesDirs: Array<string> | null = null;

// TODO: Clean up these disposables on deactivation
nova.config.onDidChange("apexskier.eslint.config.eslintPath", async () => {
eslintPath = await getEslintPath();
console.log("Updating ESLint executable globally", eslintPath);
Expand All @@ -30,10 +34,24 @@ nova.workspace.config.onDidChange(
nova.commands.invoke("apexskier.eslint.config.lintAllEditors");
}
);
nova.config.onDidChange("apexskier.eslint.config.eslintRulesDirs", () => {
eslintRulesDirs = getRulesDirs();
console.log("Updating ESLint rules globally");
nova.commands.invoke("apexskier.eslint.config.lintAllEditors");
});
nova.workspace.config.onDidChange(
"apexskier.eslint.config.eslintRulesDirs",
() => {
eslintRulesDirs = getRulesDirs();
console.log("Updating ESLint rules for workspace");
nova.commands.invoke("apexskier.eslint.config.lintAllEditors");
}
);

export async function initialize() {
eslintPath = await getEslintPath();
eslintConfigPath = getEslintConfig();
eslintRulesDirs = getRulesDirs();
}

const syntaxToSupportingPlugins: {
Expand Down Expand Up @@ -140,7 +158,12 @@ class ESLintProcess implements Disposable {
const areLintErrors = status === 1;
const noLintErrors = status === 0;
if (!areLintErrors && !noLintErrors && !lintProcessWasTerminated) {
console.warn(stderr);
console.warn("Failed to lint");
console.group();
console.warn("stderr: ", stderr);
console.log("command: ", this._process.command);
console.log("args: ", ...(this._process.args ?? []));
console.groupEnd();
throw new Error(`failed to lint (${status})`);
}
if (lintProcessWasTerminated) {
Expand All @@ -167,6 +190,17 @@ class ESLintProcess implements Disposable {
}
}

function addConfigArguments(toArgs: Array<string>) {
if (eslintRulesDirs) {
for (const dir of eslintRulesDirs) {
toArgs.unshift("--rulesdir", dir);
}
}
if (eslintConfigPath) {
toArgs.unshift("--config", eslintConfigPath);
}
}

export function runLintPass(
content: string,
path: string | null,
Expand All @@ -185,7 +219,6 @@ export function runLintPass(
return disposable;
}
const eslint = eslintPath;
const eslintConfig = eslintConfigPath;
// remove file:/Volumes/Macintosh HD from uri
const cleanPath = path
? "/" + decodeURI(path).split("/").slice(5).join("/")
Expand All @@ -200,9 +233,7 @@ export function runLintPass(
if (cleanPath) {
args.unshift("--stdin-filename", cleanPath);
}
if (eslintConfig) {
args.unshift("--config", eslintConfig);
}
addConfigArguments(args);
const process = new ESLintProcess(eslint, args, callback);
disposable.add(process);
process.write(content);
Expand Down Expand Up @@ -230,7 +261,6 @@ export function runFixPass(
return disposable;
}
const eslint = eslintPath;
const eslintConfig = eslintConfigPath;
// remove file:/Volumes/Macintosh HD from uri
const cleanPath = "/" + decodeURI(path).split("/").slice(5).join("/");

Expand All @@ -241,9 +271,7 @@ export function runFixPass(
} else {
const args = ["--fix", "--format=json"];
args.unshift(cleanPath);
if (eslintConfig) {
args.unshift("--config", eslintConfig);
}
addConfigArguments(args);
const process = new ESLintProcess(eslint, args, callback);
disposable.add(process);
}
Expand Down
7 changes: 7 additions & 0 deletions test/rules-1/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
plugins: ["custom-rules"],
extends: ["../../.eslintrc"],
rules: {
"custom-rules/test-rule": 1,
},
};
1 change: 1 addition & 0 deletions test/rules-1/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
`index.js` should have one warning (custom-rules/test-rule)
13 changes: 13 additions & 0 deletions test/rules-1/custom-rules/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module.exports = {
rules: {
"test-rule": {
create: function (context) {
return {
TemplateLiteral(node) {
context.report(node, "template literals show test-rule error");
},
};
},
},
},
};
6 changes: 6 additions & 0 deletions test/rules-1/custom-rules/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "eslint-plugin-custom-rules",
"version": "0.0.0",
"private": "true",
"main": "index.js"
}
3 changes: 3 additions & 0 deletions test/rules-1/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function test(foo) {
console.log(`hello ${foo}`);
}
7 changes: 7 additions & 0 deletions test/rules-2/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
plugins: ["custom-rules"],
extends: ["../../.eslintrc"],
rules: {
"custom-rules/test-rule": 1,
},
};
7 changes: 7 additions & 0 deletions test/rules-2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
`index.js` should have one warning (custom-rules/test-rule) when the project has custom rules configured:

```
"apexskier.eslint.config.eslintRulesDirs" : [
"test\/rules-1\/custom-rules"
],
```
3 changes: 3 additions & 0 deletions test/rules-2/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function test(foo) {
console.log(`hello ${foo}`);
}
3 changes: 3 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,9 @@ eslint-config-prettier@^7.2.0:
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-7.2.0.tgz#f4a4bd2832e810e8cc7c1411ec85b3e85c0c53f9"
integrity sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg==

"eslint-plugin-custom-rules@file:./test/rules-1/custom-rules":
version "0.0.0"

eslint-plugin-html@^6.1.1:
version "6.1.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-html/-/eslint-plugin-html-6.1.1.tgz#95aee151900b9bb2da5fa017b45cc64456a0a74e"
Expand Down

0 comments on commit 135760c

Please sign in to comment.