-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: added valid-repository-directory rule (#123)
## PR Checklist - [x] Addresses an existing open issue: fixes #53 - [x] That issue was marked as [`status: accepting prs`](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues?q=is%3Aopen+is%3Aissue+label%3A%22status%3A+accepting+prs%22) - [x] Steps in [CONTRIBUTING.md](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/blob/main/.github/CONTRIBUTING.md) were taken ## Overview Equivalent to `json-files/ensure-repository-directory`. Renamed to `valid-*` to match the precedent of the existing rules `valid-package-def` and `valid-package-dependency`. Re-uses the `findJSONLiteralWithValue` utility and renames it to the more appropriate `findPropertyWithKeyValue`
- Loading branch information
1 parent
928c5b4
commit 84035c3
Showing
7 changed files
with
254 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# Enforce that if repository directory is specified, it matches the path to the package.json file (`package-json/valid-repository-directory`) | ||
|
||
💼 This rule is enabled in the ✅ `recommended` config. | ||
|
||
💡 This rule is manually fixable by [editor suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions). | ||
|
||
<!-- end auto-generated rule header --> | ||
|
||
## Rule Details | ||
|
||
This rule enforces that `"repository"` > `"directory"` points to the right directory for a `package.json`. | ||
If `"directory"` isn't specified, this rule will do nothing. | ||
|
||
Example of **incorrect** code for this rule for a `package.json` located at `packages/example/package.json`: | ||
|
||
```json | ||
{ | ||
"repository": { | ||
"directory": "something-else" | ||
} | ||
} | ||
``` | ||
|
||
Example of **correct** code for this rule for a `package.json` located at `packages/example/package.json`: | ||
|
||
```json | ||
{ | ||
"repository": { | ||
"directory": "packages/example" | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import type { AST as JsonAST } from "jsonc-eslint-parser"; | ||
|
||
import * as ESTree from "estree"; | ||
import * as path from "node:path"; | ||
|
||
import { createRule } from "../createRule.js"; | ||
import { findPropertyWithKeyValue } from "../utils/findPropertyWithKeyValue.js"; | ||
|
||
export default createRule({ | ||
create(context) { | ||
return { | ||
"Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=repository][value.type=JSONObjectExpression]"( | ||
node: JsonAST.JSONProperty & { | ||
value: JsonAST.JSONObjectExpression; | ||
}, | ||
) { | ||
const directoryProperty = findPropertyWithKeyValue( | ||
node.value.properties, | ||
"directory", | ||
); | ||
if ( | ||
directoryProperty?.value.type !== "JSONLiteral" || | ||
typeof directoryProperty.value.value !== "string" | ||
) { | ||
return; | ||
} | ||
|
||
const directoryValue = directoryProperty.value.value; | ||
const expected = path.normalize(path.dirname(context.filename)); | ||
|
||
if (path.normalize(directoryValue) !== expected) { | ||
context.report({ | ||
messageId: "mismatched", | ||
node: directoryProperty.value as unknown as ESTree.Node, | ||
suggest: [ | ||
{ | ||
fix(fixer) { | ||
return fixer.replaceText( | ||
directoryProperty.value as unknown as ESTree.Node, | ||
`"${expected}"`, | ||
); | ||
}, | ||
messageId: "replace", | ||
}, | ||
], | ||
}); | ||
} | ||
}, | ||
}; | ||
}, | ||
|
||
meta: { | ||
docs: { | ||
category: "Best Practices", | ||
description: | ||
"Enforce that if repository directory is specified, it matches the path to the package.json file", | ||
recommended: true, | ||
}, | ||
hasSuggestions: true, | ||
messages: { | ||
mismatched: "Directory does not match package.json directory.", | ||
replace: "Replace with '{{ expected }}'.", | ||
}, | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
import rule from "../../rules/valid-repository-directory.js"; | ||
import { ruleTester } from "./ruleTester.js"; | ||
|
||
ruleTester.run("valid-repository-directory", rule, { | ||
invalid: [ | ||
{ | ||
code: `{ | ||
"repository": { | ||
"directory": "nested/package.json" | ||
} | ||
} | ||
`, | ||
errors: [ | ||
{ | ||
column: 16, | ||
endColumn: 37, | ||
line: 3, | ||
messageId: "mismatched", | ||
suggestions: [ | ||
{ | ||
messageId: "replace", | ||
output: `{ | ||
"repository": { | ||
"directory": "." | ||
} | ||
} | ||
`, | ||
}, | ||
], | ||
}, | ||
], | ||
filename: "package.json", | ||
}, | ||
{ | ||
code: `{ | ||
"repository": { | ||
"directory": "incorrect/package.json" | ||
} | ||
} | ||
`, | ||
errors: [ | ||
{ | ||
column: 16, | ||
endColumn: 40, | ||
line: 3, | ||
messageId: "mismatched", | ||
suggestions: [ | ||
{ | ||
messageId: "replace", | ||
output: `{ | ||
"repository": { | ||
"directory": "correct" | ||
} | ||
} | ||
`, | ||
}, | ||
], | ||
}, | ||
], | ||
filename: "correct/package.json", | ||
}, | ||
{ | ||
code: `{ | ||
"repository": { | ||
"directory": "incorrect/package.json" | ||
} | ||
} | ||
`, | ||
errors: [ | ||
{ | ||
column: 16, | ||
endColumn: 40, | ||
line: 3, | ||
messageId: "mismatched", | ||
suggestions: [ | ||
{ | ||
messageId: "replace", | ||
output: `{ | ||
"repository": { | ||
"directory": "deeply/nested" | ||
} | ||
} | ||
`, | ||
}, | ||
], | ||
}, | ||
], | ||
filename: "deeply/nested/package.json", | ||
}, | ||
], | ||
valid: [ | ||
`{}`, | ||
`{ "repository": "" }`, | ||
`{ "repository": "JoshuaKGoldberg/eslint-plugin-package-json" }`, | ||
`{ "repository": "https://github.com/JoshuaKGoldberg/eslint-plugin-package-json" }`, | ||
`{ "repository": { "directory": null } }`, | ||
`{ "repository": { "directory": {} } }`, | ||
`{ | ||
"repository": { | ||
"directory": 123 | ||
} | ||
} | ||
`, | ||
{ | ||
code: `{ | ||
"repository": { | ||
"directory": "nested" | ||
} | ||
} | ||
`, | ||
filename: "nested/package.json", | ||
}, | ||
{ | ||
code: `{ | ||
"repository": { | ||
"directory": "deeply/nested" | ||
} | ||
} | ||
`, | ||
filename: "deeply/nested/package.json", | ||
}, | ||
], | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import type { AST as JsonAST } from "jsonc-eslint-parser"; | ||
|
||
export type JSONPropertyWithKeyAndValue<Value extends string> = | ||
JsonAST.JSONProperty & { | ||
key: JsonAST.JSONStringLiteral; | ||
value: Value; | ||
}; | ||
|
||
export function findPropertyWithKeyValue<Value extends string>( | ||
properties: JsonAST.JSONProperty[], | ||
value: Value, | ||
) { | ||
return properties.find( | ||
(property): property is JSONPropertyWithKeyAndValue<Value> => | ||
property.key.type === "JSONLiteral" && property.key.value === value, | ||
); | ||
} |