Skip to content

Commit dacfd95

Browse files
authored
feat: use eslint-compat-utils (#251)
* feat: use eslint-compat-utils * Create unlucky-spoons-sniff.md * fix
1 parent b8c7403 commit dacfd95

File tree

12 files changed

+119
-137
lines changed

12 files changed

+119
-137
lines changed

.changeset/unlucky-spoons-sniff.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"eslint-plugin-json-schema-validator": minor
3+
---
4+
5+
feat: use eslint-compat-utils

.eslintrc.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,57 @@ module.exports = {
4646
],
4747
},
4848
],
49+
"no-restricted-properties": [
50+
"error",
51+
{
52+
object: "context",
53+
property: "getSourceCode",
54+
message:
55+
"Please use `eslint-compat-utils` module's `getSourceCode(context).getScope()` instead.",
56+
},
57+
{
58+
object: "context",
59+
property: "sourceCode",
60+
message:
61+
"Please use `eslint-compat-utils` module's `getSourceCode(context).getScope()` instead.",
62+
},
63+
{
64+
object: "context",
65+
property: "getFilename",
66+
message:
67+
"Please use `eslint-compat-utils` module's `getFilename(context)` instead.",
68+
},
69+
{
70+
object: "context",
71+
property: "filename",
72+
message:
73+
"Please use `eslint-compat-utils` module's `getFilename(context)` instead.",
74+
},
75+
{
76+
object: "context",
77+
property: "getCwd",
78+
message:
79+
"Please use `eslint-compat-utils` module's `getCwd(context)` instead.",
80+
},
81+
{
82+
object: "context",
83+
property: "cwd",
84+
message:
85+
"Please use `eslint-compat-utils` module's `getCwd(context)` instead.",
86+
},
87+
{
88+
object: "context",
89+
property: "getScope",
90+
message:
91+
"Please use `eslint-compat-utils` module's `getSourceCode(context).getScope()` instead.",
92+
},
93+
{
94+
object: "context",
95+
property: "parserServices",
96+
message:
97+
"Please use `eslint-compat-utils` module's `getSourceCode(context).parserServices` instead.",
98+
},
99+
],
49100
},
50101
overrides: [
51102
{

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
"@eslint-community/eslint-utils": "^4.3.0",
5454
"ajv": "^8.0.0",
5555
"debug": "^4.3.1",
56+
"eslint-compat-utils": "^0.1.2",
5657
"json-schema-migrate": "^2.0.0",
5758
"jsonc-eslint-parser": "^2.0.0",
5859
"minimatch": "^8.0.0",
@@ -83,7 +84,7 @@
8384
"eslint-config-prettier": "^9.0.0",
8485
"eslint-plugin-eslint-comments": "^3.2.0",
8586
"eslint-plugin-eslint-plugin": "^5.0.0",
86-
"eslint-plugin-json-schema-validator": "^4.0.0",
87+
"eslint-plugin-json-schema-validator": "^4.6.1",
8788
"eslint-plugin-jsonc": "^2.0.0",
8889
"eslint-plugin-markdown": "^3.0.0",
8990
"eslint-plugin-n": "^16.0.0",

src/rules/no-invalid.ts

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import type { ValidateError, Validator } from "../utils/validator-factory";
2626
import { compile } from "../utils/validator-factory";
2727
import type { SchemaObject } from "../utils/types";
2828
import fs from "fs";
29+
import { getCwd, getFilename, getSourceCode } from "../utils/compat";
2930

3031
const CATALOG_URL = "https://www.schemastore.org/api/json/catalog.json";
3132

@@ -161,6 +162,7 @@ export default createRule("no-invalid", {
161162
type: "suggestion",
162163
},
163164
create(context, { filename }) {
165+
const sourceCode = getSourceCode(context);
164166
const cwd = getCwd(context);
165167
const relativeFilename = filename.startsWith(cwd)
166168
? path.relative(cwd, filename)
@@ -172,7 +174,6 @@ export default createRule("no-invalid", {
172174
}
173175

174176
let existsExports = false;
175-
const sourceCode = context.getSourceCode();
176177

177178
/**
178179
* Validate JSON Schema
@@ -254,17 +255,17 @@ export default createRule("no-invalid", {
254255

255256
return {
256257
Program(node) {
257-
if (context.parserServices.isJSON) {
258+
if (sourceCode.parserServices.isJSON) {
258259
const program = node as JSONAST.JSONProgram;
259260
validateData(getStaticJSONValue(program), (error) => {
260261
return errorDataToLoc(getJSONNodeFromPath(program, error.path));
261262
});
262-
} else if (context.parserServices.isYAML) {
263+
} else if (sourceCode.parserServices.isYAML) {
263264
const program = node as YAML.YAMLProgram;
264265
validateData(getStaticYAMLValue(program), (error) => {
265266
return errorDataToLoc(getYAMLNodeFromPath(program, error.path));
266267
});
267-
} else if (context.parserServices.isTOML) {
268+
} else if (sourceCode.parserServices.isTOML) {
268269
const program = node as TOML.TOMLProgram;
269270
validateData(getStaticTOMLValue(program), (error) => {
270271
return errorDataToLoc(getTOMLNodeFromPath(program, error.path));
@@ -358,13 +359,13 @@ export default createRule("no-invalid", {
358359
/** Find schema path from program */
359360
function findSchemaPath(node: unknown) {
360361
let $schema = null;
361-
if (context.parserServices.isJSON) {
362+
if (sourceCode.parserServices.isJSON) {
362363
const program = node as JSONAST.JSONProgram;
363364
$schema = findSchemaPathFromJSON(program);
364-
} else if (context.parserServices.isYAML) {
365+
} else if (sourceCode.parserServices.isYAML) {
365366
const program = node as YAML.YAMLProgram;
366367
$schema = findSchemaPathFromYAML(program);
367-
} else if (context.parserServices.isTOML) {
368+
} else if (sourceCode.parserServices.isTOML) {
368369
const program = node as TOML.TOMLProgram;
369370
$schema = findSchemaPathFromTOML(program);
370371
}
@@ -374,7 +375,7 @@ export default createRule("no-invalid", {
374375
path.dirname(
375376
typeof context.getPhysicalFilename === "function"
376377
? context.getPhysicalFilename()
377-
: getPhysicalFilename(context.getFilename()),
378+
: getPhysicalFilename(getFilename(context)),
378379
),
379380
$schema,
380381
)
@@ -384,7 +385,7 @@ export default createRule("no-invalid", {
384385

385386
/** Validator from $schema */
386387
function get$SchemaValidators(context: RuleContext): Validator[] | null {
387-
const $schemaPath = findSchemaPath(context.getSourceCode().ast);
388+
const $schemaPath = findSchemaPath(sourceCode.ast);
388389
if (!$schemaPath) return null;
389390

390391
const validator = schemaPathToValidator($schemaPath, context);
@@ -560,16 +561,6 @@ export default createRule("no-invalid", {
560561
},
561562
});
562563

563-
/**
564-
* Get cwd
565-
*/
566-
function getCwd(context: RuleContext) {
567-
if (context.getCwd) {
568-
return context.getCwd();
569-
}
570-
return path.resolve("");
571-
}
572-
573564
/**
574565
* ! copied from https://github.com/mdx-js/eslint-mdx/blob/b97db2e912a416d5d40ddb78ab6c9fa1ab150c17/packages/eslint-mdx/src/helpers.ts#L28-L50
575566
*

src/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { Rule } from "eslint";
44
import type { AST as JSON } from "jsonc-eslint-parser";
55
import type { AST as YAML } from "yaml-eslint-parser";
66
import type { AST as TOML } from "toml-eslint-parser";
7-
import type { AST as ES } from "eslint";
7+
import type { AST as ES, Scope } from "eslint";
88
import type { Comment as ESTreeComment } from "estree";
99
import type { ESLintNode, VElement } from "vue-eslint-parser/ast";
1010
export interface RuleListener {
@@ -105,6 +105,7 @@ export interface SourceCode {
105105
visitorKeys: {
106106
[nodeType: string]: string[];
107107
};
108+
scopeManager: Scope.ScopeManager;
108109

109110
getText(
110111
node?: NodeOrToken,

src/utils/ast/js/utils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type { RuleContext } from "../../../types";
1313
// @ts-expect-error -- no type def
1414
import * as eslintUtils from "@eslint-community/eslint-utils";
1515
import type { Variable } from "eslint-scope";
16+
import { getSourceCode } from "../../compat";
1617

1718
/**
1819
* Gets the property name of a given node.
@@ -145,7 +146,7 @@ export function findInitNode(
145146
function getScope(context: RuleContext, currentNode: ESLintNode) {
146147
// On Program node, get the outermost scope to avoid return Node.js special function scope or ES modules scope.
147148
const inner = currentNode.type !== "Program";
148-
const scopeManager = (context.getSourceCode() as any).scopeManager;
149+
const scopeManager = getSourceCode(context).scopeManager;
149150

150151
let node: any = currentNode;
151152
for (; node; node = node.parent || null) {

src/utils/compat.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import {
2+
getSourceCode as getSourceCodeBase,
3+
getFilename as getFilenameBase,
4+
getCwd as getCwdBase,
5+
} from "eslint-compat-utils";
6+
import type { RuleContext, SourceCode } from "../types";
7+
import type { Rule, SourceCode as ESLintSourceCode } from "eslint";
8+
9+
export function getSourceCode(context: RuleContext): SourceCode;
10+
export function getSourceCode(context: Rule.RuleContext): ESLintSourceCode;
11+
/**
12+
* Returns an extended instance of `context.sourceCode` or the result of `context.getSourceCode()`.
13+
* Extended instances can use new APIs such as `getScope(node)` even with old ESLint.
14+
*/
15+
export function getSourceCode(
16+
context: RuleContext | Rule.RuleContext,
17+
): SourceCode | ESLintSourceCode {
18+
return getSourceCodeBase(context as never) as never;
19+
}
20+
21+
/**
22+
* Gets the value of `context.filename`, but for older ESLint it returns the result of `context.getFilename()`.
23+
*/
24+
export function getFilename(context: RuleContext | Rule.RuleContext): string {
25+
return getFilenameBase(context as never);
26+
}
27+
28+
/**
29+
* Gets the value of `context.cwd`, but for older ESLint it returns the result of `context.getCwd()`.
30+
* Versions older than v6.6.0 return a value from the result of `process.cwd()`.
31+
*/
32+
export function getCwd(context: RuleContext | Rule.RuleContext): string {
33+
return getCwdBase(context as never);
34+
}

src/utils/index.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import * as jsoncESLintParser from "jsonc-eslint-parser";
1111
import * as yamlESLintParser from "yaml-eslint-parser";
1212
import * as tomlESLintParser from "toml-eslint-parser";
1313
import path from "path";
14+
import { getFilename, getSourceCode } from "./compat";
1415

1516
/**
1617
* Define the rule.
@@ -32,17 +33,18 @@ export function createRule(
3233
},
3334
},
3435
create(context: Rule.RuleContext): any {
35-
const filename = context.getFilename();
36+
const sourceCode = getSourceCode(context);
37+
const filename = getFilename(context);
3638
const visitor = rule.create(context as any, {
3739
customBlock: false,
3840
filename,
3941
});
4042
if (
41-
typeof context.parserServices.defineCustomBlocksVisitor ===
43+
typeof sourceCode.parserServices.defineCustomBlocksVisitor ===
4244
"function" &&
4345
path.extname(filename) === ".vue"
4446
) {
45-
const jsonVisitor = context.parserServices.defineCustomBlocksVisitor(
47+
const jsonVisitor = sourceCode.parserServices.defineCustomBlocksVisitor(
4648
context,
4749
jsoncESLintParser,
4850
{
@@ -63,7 +65,7 @@ export function createRule(
6365
},
6466
},
6567
);
66-
const yamlVisitor = context.parserServices.defineCustomBlocksVisitor(
68+
const yamlVisitor = sourceCode.parserServices.defineCustomBlocksVisitor(
6769
context,
6870
yamlESLintParser,
6971
{
@@ -79,7 +81,7 @@ export function createRule(
7981
},
8082
},
8183
);
82-
const tomlVisitor = context.parserServices.defineCustomBlocksVisitor(
84+
const tomlVisitor = sourceCode.parserServices.defineCustomBlocksVisitor(
8385
context,
8486
tomlESLintParser,
8587
{

src/utils/schema.ts

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { syncGet, get } from "./http-client";
55
import debugBuilder from "debug";
66
import type { SchemaObject } from "./types";
77
import { draft7 as migrateToDraft7 } from "json-schema-migrate";
8+
import { getCwd } from "./compat";
89
const debug = debugBuilder("eslint-plugin-json-schema-validator:utils-schema");
910

1011
const TTL = 1000 * 60 * 60 * 24;
@@ -248,13 +249,3 @@ function resolvePath(modulePath: string | void, context: RuleContext) {
248249
}
249250
return modulePath;
250251
}
251-
252-
/**
253-
* Get cwd
254-
*/
255-
function getCwd(context: RuleContext) {
256-
if (context.getCwd) {
257-
return context.getCwd();
258-
}
259-
return path.resolve("");
260-
}

0 commit comments

Comments
 (0)