@venizia/dev-configs 0.4.6-0 → 0.4.7-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/checks/catalog.d.ts.map +1 -1
- package/dist/checks/catalog.js +4 -2
- package/dist/checks/catalog.js.map +1 -1
- package/dist/checks/purity/probe.d.ts.map +1 -1
- package/dist/checks/purity/probe.js +2 -1
- package/dist/checks/purity/probe.js.map +1 -1
- package/dist/checks/test-controls.d.ts.map +1 -1
- package/dist/checks/test-controls.js +2 -1
- package/dist/checks/test-controls.js.map +1 -1
- package/dist/cli/codemod/async-style.d.ts +41 -0
- package/dist/cli/codemod/async-style.d.ts.map +1 -0
- package/dist/cli/codemod/async-style.js +166 -0
- package/dist/cli/codemod/async-style.js.map +1 -0
- package/dist/cli/codemod/const-classes.d.ts.map +1 -1
- package/dist/cli/codemod/const-classes.js +2 -1
- package/dist/cli/codemod/const-classes.js.map +1 -1
- package/dist/cli/codemod/drop-redundant-casts.d.ts.map +1 -1
- package/dist/cli/codemod/drop-redundant-casts.js +2 -1
- package/dist/cli/codemod/drop-redundant-casts.js.map +1 -1
- package/dist/cli/codemod/files.d.ts +7 -0
- package/dist/cli/codemod/files.d.ts.map +1 -1
- package/dist/cli/codemod/files.js +33 -0
- package/dist/cli/codemod/files.js.map +1 -1
- package/dist/cli/codemod/index.d.ts.map +1 -1
- package/dist/cli/codemod/index.js +7 -2
- package/dist/cli/codemod/index.js.map +1 -1
- package/dist/cli/index.js +1 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/linters/house/await-support.d.ts +60 -0
- package/dist/linters/house/await-support.d.ts.map +1 -0
- package/dist/linters/house/await-support.js +209 -0
- package/dist/linters/house/await-support.js.map +1 -0
- package/dist/linters/house/common.d.ts +2 -0
- package/dist/linters/house/common.d.ts.map +1 -1
- package/dist/linters/house/common.js +2 -0
- package/dist/linters/house/common.js.map +1 -1
- package/dist/linters/house/configs.d.ts +23 -0
- package/dist/linters/house/configs.d.ts.map +1 -1
- package/dist/linters/house/configs.js +46 -1
- package/dist/linters/house/configs.js.map +1 -1
- package/dist/linters/house/effect-cleanup-consistency.rule.d.ts +17 -0
- package/dist/linters/house/effect-cleanup-consistency.rule.d.ts.map +1 -0
- package/dist/linters/house/effect-cleanup-consistency.rule.js +87 -0
- package/dist/linters/house/effect-cleanup-consistency.rule.js.map +1 -0
- package/dist/linters/house/hook-support.d.ts +29 -0
- package/dist/linters/house/hook-support.d.ts.map +1 -0
- package/dist/linters/house/hook-support.js +69 -0
- package/dist/linters/house/hook-support.js.map +1 -0
- package/dist/linters/house/index.d.ts +6 -0
- package/dist/linters/house/index.d.ts.map +1 -1
- package/dist/linters/house/index.js +6 -0
- package/dist/linters/house/index.js.map +1 -1
- package/dist/linters/house/no-async-hook-callback.rule.d.ts +18 -0
- package/dist/linters/house/no-async-hook-callback.rule.d.ts.map +1 -0
- package/dist/linters/house/no-async-hook-callback.rule.js +50 -0
- package/dist/linters/house/no-async-hook-callback.rule.js.map +1 -0
- package/dist/linters/house/no-inline-await.rule.d.ts +20 -0
- package/dist/linters/house/no-inline-await.rule.d.ts.map +1 -0
- package/dist/linters/house/no-inline-await.rule.js +76 -0
- package/dist/linters/house/no-inline-await.rule.js.map +1 -0
- package/dist/linters/house/no-return-await.rule.d.ts +15 -0
- package/dist/linters/house/no-return-await.rule.d.ts.map +1 -0
- package/dist/linters/house/no-return-await.rule.js +92 -0
- package/dist/linters/house/no-return-await.rule.js.map +1 -0
- package/dist/linters/house/plugin.d.ts.map +1 -1
- package/dist/linters/house/plugin.js +8 -0
- package/dist/linters/house/plugin.js.map +1 -1
- package/package.json +1 -1
|
@@ -13,6 +13,13 @@ export declare class CodemodFiles {
|
|
|
13
13
|
static fromGit(opts: {
|
|
14
14
|
target: string;
|
|
15
15
|
}): string[] | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* The files under `target` that a write could not be undone with git: changed in the working tree,
|
|
18
|
+
* staged, or untracked. `undefined` outside a repository or without git, where there is nothing to check.
|
|
19
|
+
*/
|
|
20
|
+
static dirty(opts: {
|
|
21
|
+
target: string;
|
|
22
|
+
}): Set<string> | undefined;
|
|
16
23
|
/** The directory walk used outside git: skips dot-directories and the build folders. */
|
|
17
24
|
static fromWalk(opts: {
|
|
18
25
|
target: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../../src/cli/codemod/files.ts"],"names":[],"mappings":"AAOA;;;;;GAKG;AACH,qBAAa,YAAY;IACvB,wJAAwJ;IACxJ,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,EAAE;IAUlD,+GAA+G;IAC/G,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,EAAE,GAAG,SAAS;IA2B9D,wFAAwF;IACxF,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,EAAE;IAoBnD,OAAO,CAAC,MAAM,CAAC,QAAQ;CAGxB"}
|
|
1
|
+
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../../src/cli/codemod/files.ts"],"names":[],"mappings":"AAOA;;;;;GAKG;AACH,qBAAa,YAAY;IACvB,wJAAwJ;IACxJ,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,EAAE;IAUlD,+GAA+G;IAC/G,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,EAAE,GAAG,SAAS;IA2B9D;;;OAGG;IACH,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,SAAS;IAiC/D,wFAAwF;IACxF,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,EAAE;IAoBnD,OAAO,CAAC,MAAM,CAAC,QAAQ;CAGxB"}
|
|
@@ -43,6 +43,39 @@ class CodemodFiles {
|
|
|
43
43
|
.map((path) => (0, node_path_1.join)(target, path))
|
|
44
44
|
.filter((path) => (0, node_fs_1.existsSync)(path) && (0, node_fs_1.statSync)(path).isFile());
|
|
45
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* The files under `target` that a write could not be undone with git: changed in the working tree,
|
|
48
|
+
* staged, or untracked. `undefined` outside a repository or without git, where there is nothing to check.
|
|
49
|
+
*/
|
|
50
|
+
static dirty(opts) {
|
|
51
|
+
const { target } = opts;
|
|
52
|
+
const cwd = (0, node_fs_1.statSync)(target).isFile() ? (0, node_path_1.dirname)(target) : target;
|
|
53
|
+
const queries = [
|
|
54
|
+
['ls-files', '--modified', '--others', '--exclude-standard', '-z'],
|
|
55
|
+
['diff', '--cached', '--name-only', '--relative', '-z'],
|
|
56
|
+
];
|
|
57
|
+
const paths = new Set();
|
|
58
|
+
for (const query of queries) {
|
|
59
|
+
let output;
|
|
60
|
+
try {
|
|
61
|
+
output = (0, node_child_process_1.execFileSync)('git', query, {
|
|
62
|
+
cwd,
|
|
63
|
+
encoding: 'utf8',
|
|
64
|
+
maxBuffer: 256 * 1024 * 1024,
|
|
65
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
for (const path of output.split('\0')) {
|
|
72
|
+
if (path !== '') {
|
|
73
|
+
paths.add((0, node_path_1.join)(cwd, path));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return paths;
|
|
78
|
+
}
|
|
46
79
|
/** The directory walk used outside git: skips dot-directories and the build folders. */
|
|
47
80
|
static fromWalk(opts) {
|
|
48
81
|
const { target } = opts;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files.js","sourceRoot":"","sources":["../../../src/cli/codemod/files.ts"],"names":[],"mappings":";;;AAAA,2DAAkD;AAClD,qCAA4D;AAC5D,
|
|
1
|
+
{"version":3,"file":"files.js","sourceRoot":"","sources":["../../../src/cli/codemod/files.ts"],"names":[],"mappings":"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","sourcesContent":["import { execFileSync } from 'node:child_process';\nimport { existsSync, readdirSync, statSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\n\nconst SKIPPED_DIRECTORIES = new Set(['node_modules', 'dist', 'build', '.git']);\nconst SOURCE_PATTERN = /\\.(?:ts|tsx|mts|cts)$/;\n\n/**\n * The source files a codemod may touch. Inside a git repository the list comes from git, so a\n * `.gitignore`d folder (a worktree, a clone, a build output) is never entered. Outside git there is\n * no ignore file to read, so the walk skips every dot-directory as well as `node_modules`, `dist`,\n * `build` and `.git`.\n */\nexport class CodemodFiles {\n /** Every `.ts`, `.tsx`, `.mts` or `.cts` file (declaration files excluded) the codemod may touch under `target`; a file target is returned as it is. */\n static collect(opts: { target: string }): string[] {\n const { target } = opts;\n\n if (statSync(target).isFile()) {\n return [target];\n }\n\n return CodemodFiles.fromGit({ target }) ?? CodemodFiles.fromWalk({ target });\n }\n\n /** Tracked files plus untracked files git does not ignore; `undefined` outside a repository or without git. */\n static fromGit(opts: { target: string }): string[] | undefined {\n const { target } = opts;\n let output: string;\n\n try {\n output = execFileSync(\n 'git',\n ['ls-files', '--cached', '--others', '--exclude-standard', '-z'],\n {\n cwd: target,\n encoding: 'utf8',\n maxBuffer: 256 * 1024 * 1024,\n stdio: ['ignore', 'pipe', 'ignore'],\n },\n );\n } catch {\n return undefined;\n }\n\n return output\n .split('\\0')\n .filter((path) => path !== '' && CodemodFiles.isSource({ name: path }))\n .filter((path) => !path.split('/').some((segment) => SKIPPED_DIRECTORIES.has(segment)))\n .map((path) => join(target, path))\n .filter((path) => existsSync(path) && statSync(path).isFile());\n }\n\n /**\n * The files under `target` that a write could not be undone with git: changed in the working tree,\n * staged, or untracked. `undefined` outside a repository or without git, where there is nothing to check.\n */\n static dirty(opts: { target: string }): Set<string> | undefined {\n const { target } = opts;\n const cwd = statSync(target).isFile() ? dirname(target) : target;\n const queries = [\n ['ls-files', '--modified', '--others', '--exclude-standard', '-z'],\n ['diff', '--cached', '--name-only', '--relative', '-z'],\n ];\n const paths = new Set<string>();\n\n for (const query of queries) {\n let output: string;\n\n try {\n output = execFileSync('git', query, {\n cwd,\n encoding: 'utf8',\n maxBuffer: 256 * 1024 * 1024,\n stdio: ['ignore', 'pipe', 'ignore'],\n });\n } catch {\n return undefined;\n }\n\n for (const path of output.split('\\0')) {\n if (path !== '') {\n paths.add(join(cwd, path));\n }\n }\n }\n\n return paths;\n }\n\n /** The directory walk used outside git: skips dot-directories and the build folders. */\n static fromWalk(opts: { target: string }): string[] {\n const { target } = opts;\n const files: string[] = [];\n\n for (const entry of readdirSync(target, { withFileTypes: true })) {\n if (entry.isDirectory()) {\n if (!SKIPPED_DIRECTORIES.has(entry.name) && !entry.name.startsWith('.')) {\n files.push(...CodemodFiles.fromWalk({ target: join(target, entry.name) }));\n }\n continue;\n }\n\n if (CodemodFiles.isSource({ name: entry.name })) {\n files.push(join(target, entry.name));\n }\n }\n\n return files;\n }\n\n private static isSource(opts: { name: string }): boolean {\n return SOURCE_PATTERN.test(opts.name) && !opts.name.endsWith('.d.ts');\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/codemod/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/codemod/index.ts"],"names":[],"mappings":"AA2CA;;;;;;GAMG;AACH,qBAAa,cAAc;WACZ,GAAG,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;CAuH1E"}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.CodemodCommand = void 0;
|
|
4
4
|
const node_fs_1 = require("node:fs");
|
|
5
5
|
const node_path_1 = require("node:path");
|
|
6
|
+
const async_style_1 = require("./async-style");
|
|
6
7
|
const const_classes_1 = require("./const-classes");
|
|
7
8
|
const drop_redundant_casts_1 = require("./drop-redundant-casts");
|
|
8
9
|
const files_1 = require("./files");
|
|
@@ -53,8 +54,11 @@ class CodemodCommand {
|
|
|
53
54
|
if (name === 'const-classes') {
|
|
54
55
|
return const_classes_1.ConstClassesCommand.run({ root: opts.root, args: rest });
|
|
55
56
|
}
|
|
57
|
+
if (name === 'async-style') {
|
|
58
|
+
return async_style_1.AsyncStyleCommand.run({ root: opts.root, args: rest });
|
|
59
|
+
}
|
|
56
60
|
if (args.includes(CodemodFlags.HELP) || args.includes(CodemodFlags.HELP_SHORT)) {
|
|
57
|
-
console.log(`${USAGE}\n\n${drop_redundant_casts_1.DropRedundantCastsCommand.USAGE}\n\n${const_classes_1.ConstClassesCommand.USAGE}`);
|
|
61
|
+
console.log(`${USAGE}\n\n${drop_redundant_casts_1.DropRedundantCastsCommand.USAGE}\n\n${const_classes_1.ConstClassesCommand.USAGE}\n\n${async_style_1.AsyncStyleCommand.USAGE}`);
|
|
58
62
|
return 0;
|
|
59
63
|
}
|
|
60
64
|
if (name !== 'model-settings') {
|
|
@@ -76,7 +80,8 @@ class CodemodCommand {
|
|
|
76
80
|
const targets = (paths.length > 0 ? paths : ['.']).map((path) => (0, node_path_1.resolve)(opts.root, path));
|
|
77
81
|
let typescript;
|
|
78
82
|
try {
|
|
79
|
-
|
|
83
|
+
const result2 = await import('typescript');
|
|
84
|
+
typescript = result2.default;
|
|
80
85
|
}
|
|
81
86
|
catch {
|
|
82
87
|
console.error('devz codemod: the "typescript" package is required to read your sources');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/codemod/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync, writeFileSync } from 'node:fs';\nimport { relative, resolve } from 'node:path';\nimport { ConstClassesCommand } from './const-classes';\nimport { DropRedundantCastsCommand } from './drop-redundant-casts';\nimport { CodemodFiles } from './files';\nimport { migrateModelSettings } from './model-settings';\n\nconst USAGE = `Usage: devz codemod model-settings [paths...] [--write | --check]\n\nMoves @model settings to the grouped shape and skipMigrate to migration.use.\n\n --write write the changed files (without it, nothing is written)\n --check dry run that exits 1 when anything would change or is left untouched (for CI)\n --help print this text and exit\n\nWith no flag it lists what would change and writes nothing. Inside a git repository it reads the\nfiles git knows (tracked, or untracked and not ignored), so ignored folders are never touched.`;\n\n/** A file that can hold a `@model` call: the decorator, an aliased import of it, or `ns.model(`. */\nconst MODEL_TEXT = /@model\\b|\\bmodel\\s+as\\s+\\w+|\\.model\\(/;\n\n/** A usage error: nothing was read or written. */\nconst USAGE_ERROR_CODE = 2;\n\nclass CodemodFlags {\n static readonly WRITE = '--write';\n static readonly CHECK = '--check';\n static readonly HELP = '--help';\n static readonly HELP_SHORT = '-h';\n\n static readonly SCHEME_SET = new Set<string>([\n this.WRITE,\n this.CHECK,\n this.HELP,\n this.HELP_SHORT,\n ]);\n\n static isValid(value: string): boolean {\n return this.SCHEME_SET.has(value);\n }\n}\n\n/**\n * `devz codemod model-settings [paths...] [--write | --check]`: moves `@model` settings from the\n * flat keys (`defaultFilter`, `defaultLimit`, `maxLimit`, `scopeFilter`) to `query` and `access`,\n * and `skipMigrate` to `migration.use`. It is a dry run unless `--write` is given: it lists what\n * would change. `--check` is the same dry run, and exits 1 when anything would change or is\n * left untouched (an untouched model still throws when its decorator runs).\n */\nexport class CodemodCommand {\n static async run(opts: { root: string; args: string[] }): Promise<number> {\n const { args } = opts;\n\n const [name, ...rest] = args;\n\n if (name === 'drop-redundant-casts') {\n return DropRedundantCastsCommand.run({ root: opts.root, args: rest });\n }\n\n if (name === 'const-classes') {\n return ConstClassesCommand.run({ root: opts.root, args: rest });\n }\n\n if (args.includes(CodemodFlags.HELP) || args.includes(CodemodFlags.HELP_SHORT)) {\n console.log(`${USAGE}\\n\\n${DropRedundantCastsCommand.USAGE}\\n\\n${ConstClassesCommand.USAGE}`);\n return 0;\n }\n\n if (name !== 'model-settings') {\n console.error(`devz codemod: unknown codemod \"${name ?? ''}\"\\n${USAGE}`);\n return USAGE_ERROR_CODE;\n }\n\n const unknown = rest.filter(\n (argument) => argument.startsWith('-') && !CodemodFlags.isValid(argument),\n );\n if (unknown.length > 0) {\n console.error(\n `devz codemod: unknown option ${unknown.map((flag) => `\"${flag}\"`).join(', ')}\\n${USAGE}`,\n );\n return USAGE_ERROR_CODE;\n }\n\n const isWrite = rest.includes(CodemodFlags.WRITE);\n const isCheck = rest.includes(CodemodFlags.CHECK);\n\n if (isWrite && isCheck) {\n console.error(\n `devz codemod: ${CodemodFlags.WRITE} and ${CodemodFlags.CHECK} contradict each other\\n${USAGE}`,\n );\n return USAGE_ERROR_CODE;\n }\n\n const paths = rest.filter((argument) => !argument.startsWith('-'));\n const targets = (paths.length > 0 ? paths : ['.']).map((path) => resolve(opts.root, path));\n\n let typescript: typeof import('typescript');\n try {\n typescript = (await import('typescript')).default;\n } catch {\n console.error('devz codemod: the \"typescript\" package is required to read your sources');\n return 1;\n }\n\n let changedCount = 0;\n let reportCount = 0;\n\n for (const target of targets) {\n const files = CodemodFiles.collect({ target });\n\n if (files.length === 0 && paths.length > 0) {\n console.warn(\n `devz codemod: no source files under \"${relative(opts.root, target) || target}\" (git ignores the path, or it holds none): nothing was read`,\n );\n }\n\n for (const file of files) {\n const source = readFileSync(file, 'utf8');\n\n if (!MODEL_TEXT.test(source)) {\n continue;\n }\n\n const result = migrateModelSettings({ typescript, fileName: file, source });\n const shown = relative(opts.root, file) || file;\n\n for (const report of result.reports) {\n reportCount += 1;\n console.warn(`${shown}:${report.line}:${report.column} ${report.reason}`);\n }\n\n if (!result.changed) {\n continue;\n }\n\n changedCount += 1;\n console.log(\n `${isWrite ? 'changed' : 'would change'} ${shown} (${result.rewritten} model(s))`,\n );\n\n if (isWrite) {\n writeFileSync(file, result.output);\n }\n }\n }\n\n console.log(\n `devz codemod model-settings: ${changedCount} file(s) ${isWrite ? 'changed' : 'would change'}, ${reportCount} left untouched`,\n );\n\n if (!isWrite && changedCount > 0) {\n console.log(`Nothing was written. Run again with ${CodemodFlags.WRITE} to apply.`);\n }\n\n if (isCheck && changedCount === 0 && reportCount > 0) {\n console.log(\n 'Nothing to rewrite, but the models above throw when the decorator runs: fix them by hand.',\n );\n }\n\n return isCheck && (changedCount > 0 || reportCount > 0) ? 1 : 0;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/codemod/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync, writeFileSync } from 'node:fs';\nimport { relative, resolve } from 'node:path';\nimport { AsyncStyleCommand } from './async-style';\nimport { ConstClassesCommand } from './const-classes';\nimport { DropRedundantCastsCommand } from './drop-redundant-casts';\nimport { CodemodFiles } from './files';\nimport { migrateModelSettings } from './model-settings';\n\nconst USAGE = `Usage: devz codemod model-settings [paths...] [--write | --check]\n\nMoves @model settings to the grouped shape and skipMigrate to migration.use.\n\n --write write the changed files (without it, nothing is written)\n --check dry run that exits 1 when anything would change or is left untouched (for CI)\n --help print this text and exit\n\nWith no flag it lists what would change and writes nothing. Inside a git repository it reads the\nfiles git knows (tracked, or untracked and not ignored), so ignored folders are never touched.`;\n\n/** A file that can hold a `@model` call: the decorator, an aliased import of it, or `ns.model(`. */\nconst MODEL_TEXT = /@model\\b|\\bmodel\\s+as\\s+\\w+|\\.model\\(/;\n\n/** A usage error: nothing was read or written. */\nconst USAGE_ERROR_CODE = 2;\n\nclass CodemodFlags {\n static readonly WRITE = '--write';\n static readonly CHECK = '--check';\n static readonly HELP = '--help';\n static readonly HELP_SHORT = '-h';\n\n static readonly SCHEME_SET = new Set<string>([\n this.WRITE,\n this.CHECK,\n this.HELP,\n this.HELP_SHORT,\n ]);\n\n static isValid(value: string): boolean {\n return this.SCHEME_SET.has(value);\n }\n}\n\n/**\n * `devz codemod model-settings [paths...] [--write | --check]`: moves `@model` settings from the\n * flat keys (`defaultFilter`, `defaultLimit`, `maxLimit`, `scopeFilter`) to `query` and `access`,\n * and `skipMigrate` to `migration.use`. It is a dry run unless `--write` is given: it lists what\n * would change. `--check` is the same dry run, and exits 1 when anything would change or is\n * left untouched (an untouched model still throws when its decorator runs).\n */\nexport class CodemodCommand {\n static async run(opts: { root: string; args: string[] }): Promise<number> {\n const { args } = opts;\n\n const [name, ...rest] = args;\n\n if (name === 'drop-redundant-casts') {\n return DropRedundantCastsCommand.run({ root: opts.root, args: rest });\n }\n\n if (name === 'const-classes') {\n return ConstClassesCommand.run({ root: opts.root, args: rest });\n }\n\n if (name === 'async-style') {\n return AsyncStyleCommand.run({ root: opts.root, args: rest });\n }\n\n if (args.includes(CodemodFlags.HELP) || args.includes(CodemodFlags.HELP_SHORT)) {\n console.log(\n `${USAGE}\\n\\n${DropRedundantCastsCommand.USAGE}\\n\\n${ConstClassesCommand.USAGE}\\n\\n${AsyncStyleCommand.USAGE}`,\n );\n return 0;\n }\n\n if (name !== 'model-settings') {\n console.error(`devz codemod: unknown codemod \"${name ?? ''}\"\\n${USAGE}`);\n return USAGE_ERROR_CODE;\n }\n\n const unknown = rest.filter(\n (argument) => argument.startsWith('-') && !CodemodFlags.isValid(argument),\n );\n if (unknown.length > 0) {\n console.error(\n `devz codemod: unknown option ${unknown.map((flag) => `\"${flag}\"`).join(', ')}\\n${USAGE}`,\n );\n return USAGE_ERROR_CODE;\n }\n\n const isWrite = rest.includes(CodemodFlags.WRITE);\n const isCheck = rest.includes(CodemodFlags.CHECK);\n\n if (isWrite && isCheck) {\n console.error(\n `devz codemod: ${CodemodFlags.WRITE} and ${CodemodFlags.CHECK} contradict each other\\n${USAGE}`,\n );\n return USAGE_ERROR_CODE;\n }\n\n const paths = rest.filter((argument) => !argument.startsWith('-'));\n const targets = (paths.length > 0 ? paths : ['.']).map((path) => resolve(opts.root, path));\n\n let typescript: typeof import('typescript');\n try {\n const result2 = await import('typescript');\n typescript = result2.default;\n } catch {\n console.error('devz codemod: the \"typescript\" package is required to read your sources');\n return 1;\n }\n\n let changedCount = 0;\n let reportCount = 0;\n\n for (const target of targets) {\n const files = CodemodFiles.collect({ target });\n\n if (files.length === 0 && paths.length > 0) {\n console.warn(\n `devz codemod: no source files under \"${relative(opts.root, target) || target}\" (git ignores the path, or it holds none): nothing was read`,\n );\n }\n\n for (const file of files) {\n const source = readFileSync(file, 'utf8');\n\n if (!MODEL_TEXT.test(source)) {\n continue;\n }\n\n const result = migrateModelSettings({ typescript, fileName: file, source });\n const shown = relative(opts.root, file) || file;\n\n for (const report of result.reports) {\n reportCount += 1;\n console.warn(`${shown}:${report.line}:${report.column} ${report.reason}`);\n }\n\n if (!result.changed) {\n continue;\n }\n\n changedCount += 1;\n console.log(\n `${isWrite ? 'changed' : 'would change'} ${shown} (${result.rewritten} model(s))`,\n );\n\n if (isWrite) {\n writeFileSync(file, result.output);\n }\n }\n }\n\n console.log(\n `devz codemod model-settings: ${changedCount} file(s) ${isWrite ? 'changed' : 'would change'}, ${reportCount} left untouched`,\n );\n\n if (!isWrite && changedCount > 0) {\n console.log(`Nothing was written. Run again with ${CodemodFlags.WRITE} to apply.`);\n }\n\n if (isCheck && changedCount === 0 && reportCount > 0) {\n console.log(\n 'Nothing to rewrite, but the models above throw when the decorator runs: fix them by hand.',\n );\n }\n\n return isCheck && (changedCount > 0 || reportCount > 0) ? 1 : 0;\n }\n}\n"]}
|
package/dist/cli/index.js
CHANGED
|
@@ -15,6 +15,7 @@ Commands:
|
|
|
15
15
|
codemod model-settings [paths...] [--write] move @model settings to the grouped shape (dry run unless --write)
|
|
16
16
|
codemod drop-redundant-casts [paths...] remove \`as X\` casts the compiler no longer needs (dry run unless --write)
|
|
17
17
|
codemod const-classes [paths...] turn a string-literal union into a const class (dry run unless --write)
|
|
18
|
+
codemod async-style [paths...] apply the no-inline-await and no-return-await fixers (dry run unless --write)
|
|
18
19
|
|
|
19
20
|
Run \`devz clean --help\` or \`devz codemod --help\` for a command's options.`;
|
|
20
21
|
const main = async (opts) => {
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";;;AACA,mCAAuC;AACvC,mCAAuC;AACvC,uCAA2C;AAC3C,iCAAqC;AAErC,MAAM,KAAK,GAAG
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";;;AACA,mCAAuC;AACvC,mCAAuC;AACvC,uCAA2C;AAC3C,iCAAqC;AAErC,MAAM,KAAK,GAAG;;;;;;;;;;;;8EAYgE,CAAC;AAE/E,MAAM,IAAI,GAAG,KAAK,EAAE,IAAwB,EAAmB,EAAE;IAC/D,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC;IAErC,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACtE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACnB,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACvB,OAAO,kBAAW,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;QACxB,OAAO,oBAAY,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;QACxB,OAAO,oBAAY,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,wBAAc,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,0BAA0B,OAAO,IAAI,EAAE,MAAM,KAAK,EAAE,CAAC,CAAC;IACpE,OAAO,CAAC,CAAC;AACX,CAAC,CAAC;AAEF,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CACxC,CAAC,QAAQ,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EACpC,CAAC,KAAc,EAAE,EAAE;IACjB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CACF,CAAC","sourcesContent":["#!/usr/bin/env bun\nimport { CheckCommand } from './check';\nimport { CleanCommand } from './clean';\nimport { CodemodCommand } from './codemod';\nimport { LintCommand } from './lint';\n\nconst USAGE = `Usage: devz <command> [options]\n\nCommands:\n lint [--fix] [files] oxlint, ESLint and the formatter; --fix writes\n check purity --claims <file> [package] [--json] probe every entry claimed browser-pure (needs a build)\n check module-cycles | split-report | catalog shared repository gates; devz check --help lists their options\n clean remove dist, node_modules/.cache and *.tsbuildinfo\n codemod model-settings [paths...] [--write] move @model settings to the grouped shape (dry run unless --write)\n codemod drop-redundant-casts [paths...] remove \\`as X\\` casts the compiler no longer needs (dry run unless --write)\n codemod const-classes [paths...] turn a string-literal union into a const class (dry run unless --write)\n codemod async-style [paths...] apply the no-inline-await and no-return-await fixers (dry run unless --write)\n\nRun \\`devz clean --help\\` or \\`devz codemod --help\\` for a command's options.`;\n\nconst main = async (opts: { argv: string[] }): Promise<number> => {\n const [command, ...args] = opts.argv;\n\n if (command === undefined || command === '--help' || command === '-h') {\n console.log(USAGE);\n return 0;\n }\n\n if (command === 'lint') {\n return LintCommand.run({ root: process.cwd(), args });\n }\n\n if (command === 'check') {\n return CheckCommand.run({ root: process.cwd(), args });\n }\n\n if (command === 'clean') {\n return CleanCommand.run({ root: process.cwd(), args });\n }\n\n if (command === 'codemod') {\n return CodemodCommand.run({ root: process.cwd(), args });\n }\n\n console.error(`devz: unknown command \"${command ?? ''}\"\\n${USAGE}`);\n return 1;\n};\n\nmain({ argv: process.argv.slice(2) }).then(\n (exitCode) => process.exit(exitCode),\n (error: unknown) => {\n console.error(error);\n process.exit(1);\n },\n);\n"]}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { Rule, SourceCode } from 'eslint';
|
|
2
|
+
/** The shared parts of the two `await` rules: where a statement can go before another, what may run first, fresh names. */
|
|
3
|
+
export declare class AwaitSupport {
|
|
4
|
+
static parentOf(opts: {
|
|
5
|
+
node: unknown;
|
|
6
|
+
}): unknown;
|
|
7
|
+
/** An ESTree node of the lint run: it has a `type` and a `range`. */
|
|
8
|
+
static isNode(value: unknown): value is Rule.Node;
|
|
9
|
+
static rangeOf(opts: {
|
|
10
|
+
node: unknown;
|
|
11
|
+
}): [number, number] | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* The statement that can take a `const` in front of it so that `awaitNode` is evaluated first, or `undefined`
|
|
14
|
+
* when hoisting would change what runs: the `await` sits in a branch (`?:`, the right of `&&`, `||`, `??`),
|
|
15
|
+
* in a loop test or update, in an unbraced `if` branch, in an optional chain, or in an arrow expression body.
|
|
16
|
+
*/
|
|
17
|
+
static hoistTarget(opts: {
|
|
18
|
+
awaitNode: unknown;
|
|
19
|
+
}): Rule.Node | undefined;
|
|
20
|
+
static isPure(opts: {
|
|
21
|
+
node: unknown;
|
|
22
|
+
}): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Whether something that does more than read a value runs, inside `statement`, before `awaitNode` does.
|
|
25
|
+
* Hoisting the `await` in front of the statement would then run it first.
|
|
26
|
+
*/
|
|
27
|
+
static hasEffectBefore(opts: {
|
|
28
|
+
statement: Rule.Node;
|
|
29
|
+
awaitNode: unknown;
|
|
30
|
+
sourceCode: SourceCode;
|
|
31
|
+
}): boolean;
|
|
32
|
+
/** The leading whitespace of the line a node starts on. */
|
|
33
|
+
static indentOf(opts: {
|
|
34
|
+
node: Rule.Node;
|
|
35
|
+
sourceCode: SourceCode;
|
|
36
|
+
}): string;
|
|
37
|
+
/** The nearest function or the program that holds `node`: the scope a new name must be free in. */
|
|
38
|
+
static scopeNodeOf(opts: {
|
|
39
|
+
node: Rule.Node;
|
|
40
|
+
}): Rule.Node;
|
|
41
|
+
/**
|
|
42
|
+
* `base`, or `base2`, `base3`... the first word that does not appear in the function (or program) holding `node`
|
|
43
|
+
* and that this lint pass has not handed out already: two fixes of one pass must not declare the same name.
|
|
44
|
+
*/
|
|
45
|
+
static freshName(opts: {
|
|
46
|
+
node: Rule.Node;
|
|
47
|
+
base: string;
|
|
48
|
+
sourceCode: SourceCode;
|
|
49
|
+
taken: Map<unknown, Set<string>>;
|
|
50
|
+
}): string;
|
|
51
|
+
/**
|
|
52
|
+
* The range to replace with the name that stands for an `await`: the `await` itself, widened over the parentheses
|
|
53
|
+
* around it when they only grouped it (`(await f()).x`, `!(await f())`).
|
|
54
|
+
*/
|
|
55
|
+
static replaceRangeOf(opts: {
|
|
56
|
+
awaitNode: Rule.Node;
|
|
57
|
+
sourceCode: SourceCode;
|
|
58
|
+
}): [number, number];
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=await-support.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"await-support.d.ts","sourceRoot":"","sources":["../../../src/linters/house/await-support.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAwC/C,2HAA2H;AAC3H,qBAAa,YAAY;IACvB,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO;IAIjD,qEAAqE;IACrE,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,IAAI,CAAC,IAAI;IAMjD,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS;IAOrE;;;;OAIG;IACH,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC,IAAI,GAAG,SAAS;IA8CvE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO;IAwC/C;;;OAGG;IACH,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE;QAC3B,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC;QACrB,SAAS,EAAE,OAAO,CAAC;QACnB,UAAU,EAAE,UAAU,CAAC;KACxB,GAAG,OAAO;IA4BX,2DAA2D;IAC3D,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC;QAAC,UAAU,EAAE,UAAU,CAAA;KAAE,GAAG,MAAM;IAK1E,mGAAmG;IACnG,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC,IAAI;IAexD;;;OAGG;IACH,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE;QACrB,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,UAAU,CAAC;QACvB,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;KAClC,GAAG,MAAM;IAgBV;;;OAGG;IACH,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC;QAAC,UAAU,EAAE,UAAU,CAAA;KAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;CAmBhG"}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AwaitSupport = void 0;
|
|
4
|
+
const common_1 = require("./common");
|
|
5
|
+
const STATEMENT_LISTS = new Set(['BlockStatement', 'Program', 'StaticBlock', 'SwitchCase']);
|
|
6
|
+
const FUNCTION_TYPES = new Set([
|
|
7
|
+
'FunctionDeclaration',
|
|
8
|
+
'FunctionExpression',
|
|
9
|
+
'ArrowFunctionExpression',
|
|
10
|
+
]);
|
|
11
|
+
/** The child of a statement that runs exactly once, before anything else of that statement. */
|
|
12
|
+
const HEAD_FIELD = {
|
|
13
|
+
IfStatement: 'test',
|
|
14
|
+
SwitchStatement: 'discriminant',
|
|
15
|
+
ForOfStatement: 'right',
|
|
16
|
+
ForInStatement: 'right',
|
|
17
|
+
ExpressionStatement: 'expression',
|
|
18
|
+
ReturnStatement: 'argument',
|
|
19
|
+
ThrowStatement: 'argument',
|
|
20
|
+
};
|
|
21
|
+
/** Nodes that evaluate to a value without doing anything else, so running them later or earlier changes nothing. */
|
|
22
|
+
const PURE_LEAVES = new Set([
|
|
23
|
+
'Identifier',
|
|
24
|
+
'Literal',
|
|
25
|
+
'ThisExpression',
|
|
26
|
+
'ArrowFunctionExpression',
|
|
27
|
+
'FunctionExpression',
|
|
28
|
+
'PrivateIdentifier',
|
|
29
|
+
]);
|
|
30
|
+
/** Wrappers whose parentheses around an `await` carry no meaning once the `await` is a name. */
|
|
31
|
+
const GROUPING_PARENTS = new Set([
|
|
32
|
+
'MemberExpression',
|
|
33
|
+
'TSAsExpression',
|
|
34
|
+
'TSSatisfiesExpression',
|
|
35
|
+
'TSNonNullExpression',
|
|
36
|
+
'UnaryExpression',
|
|
37
|
+
'BinaryExpression',
|
|
38
|
+
'SpreadElement',
|
|
39
|
+
'ArrayExpression',
|
|
40
|
+
]);
|
|
41
|
+
/** The shared parts of the two `await` rules: where a statement can go before another, what may run first, fresh names. */
|
|
42
|
+
class AwaitSupport {
|
|
43
|
+
static parentOf(opts) {
|
|
44
|
+
return (0, common_1.readField)({ node: opts.node, key: 'parent' });
|
|
45
|
+
}
|
|
46
|
+
/** An ESTree node of the lint run: it has a `type` and a `range`. */
|
|
47
|
+
static isNode(value) {
|
|
48
|
+
return ((0, common_1.nodeType)({ node: value }) !== undefined && AwaitSupport.rangeOf({ node: value }) !== undefined);
|
|
49
|
+
}
|
|
50
|
+
static rangeOf(opts) {
|
|
51
|
+
const range = (0, common_1.readField)({ node: opts.node, key: 'range' });
|
|
52
|
+
return Array.isArray(range) && typeof range[0] === 'number' && typeof range[1] === 'number'
|
|
53
|
+
? [range[0], range[1]]
|
|
54
|
+
: undefined;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The statement that can take a `const` in front of it so that `awaitNode` is evaluated first, or `undefined`
|
|
58
|
+
* when hoisting would change what runs: the `await` sits in a branch (`?:`, the right of `&&`, `||`, `??`),
|
|
59
|
+
* in a loop test or update, in an unbraced `if` branch, in an optional chain, or in an arrow expression body.
|
|
60
|
+
*/
|
|
61
|
+
static hoistTarget(opts) {
|
|
62
|
+
let child = opts.awaitNode;
|
|
63
|
+
let ancestor = AwaitSupport.parentOf({ node: child });
|
|
64
|
+
while (ancestor) {
|
|
65
|
+
const type = (0, common_1.nodeType)({ node: ancestor }) ?? '';
|
|
66
|
+
if (FUNCTION_TYPES.has(type) || type === 'ChainExpression') {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
if (type === 'ConditionalExpression' &&
|
|
70
|
+
(0, common_1.readField)({ node: ancestor, key: 'test' }) !== child) {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
if (type === 'LogicalExpression' && (0, common_1.readField)({ node: ancestor, key: 'left' }) !== child) {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
if (type === 'AssignmentExpression' &&
|
|
77
|
+
['??=', '||=', '&&='].includes(String((0, common_1.readField)({ node: ancestor, key: 'operator' }))) &&
|
|
78
|
+
(0, common_1.readField)({ node: ancestor, key: 'right' }) === child) {
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
if (type.endsWith('Statement') || type === 'VariableDeclaration') {
|
|
82
|
+
const head = HEAD_FIELD[type];
|
|
83
|
+
const isHead = type === 'VariableDeclaration' || (0, common_1.readField)({ node: ancestor, key: head }) === child;
|
|
84
|
+
const outer = AwaitSupport.parentOf({ node: ancestor });
|
|
85
|
+
const isListed = STATEMENT_LISTS.has((0, common_1.nodeType)({ node: outer }) ?? '') &&
|
|
86
|
+
(type === 'VariableDeclaration' || head !== undefined);
|
|
87
|
+
return isHead && isListed && AwaitSupport.isNode(ancestor) ? ancestor : undefined;
|
|
88
|
+
}
|
|
89
|
+
child = ancestor;
|
|
90
|
+
ancestor = AwaitSupport.parentOf({ node: child });
|
|
91
|
+
}
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
static isPure(opts) {
|
|
95
|
+
const { node } = opts;
|
|
96
|
+
const type = (0, common_1.nodeType)({ node }) ?? '';
|
|
97
|
+
const pure = (child) => AwaitSupport.isPure({ node: child });
|
|
98
|
+
const field = (key) => (0, common_1.readField)({ node, key });
|
|
99
|
+
const all = (key) => {
|
|
100
|
+
const list = (0, common_1.readField)({ node, key });
|
|
101
|
+
return Array.isArray(list) && list.every((entry) => entry === null || pure(entry));
|
|
102
|
+
};
|
|
103
|
+
if (PURE_LEAVES.has(type) ||
|
|
104
|
+
(type.startsWith('TS') &&
|
|
105
|
+
!['TSAsExpression', 'TSNonNullExpression', 'TSSatisfiesExpression'].includes(type))) {
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
const parts = new Map([
|
|
109
|
+
['TemplateLiteral', () => all('expressions')],
|
|
110
|
+
['MemberExpression', () => pure(field('object')) && pure(field('property'))],
|
|
111
|
+
['ArrayExpression', () => all('elements')],
|
|
112
|
+
['ObjectExpression', () => all('properties')],
|
|
113
|
+
['Property', () => pure(field('key')) && pure(field('value'))],
|
|
114
|
+
['SpreadElement', () => pure(field('argument'))],
|
|
115
|
+
['UnaryExpression', () => field('operator') !== 'delete' && pure(field('argument'))],
|
|
116
|
+
['BinaryExpression', () => pure(field('left')) && pure(field('right'))],
|
|
117
|
+
['LogicalExpression', () => pure(field('left')) && pure(field('right'))],
|
|
118
|
+
[
|
|
119
|
+
'ConditionalExpression',
|
|
120
|
+
() => ['test', 'consequent', 'alternate'].every((key) => pure(field(key))),
|
|
121
|
+
],
|
|
122
|
+
['TSAsExpression', () => pure(field('expression'))],
|
|
123
|
+
['TSNonNullExpression', () => pure(field('expression'))],
|
|
124
|
+
['TSSatisfiesExpression', () => pure(field('expression'))],
|
|
125
|
+
]);
|
|
126
|
+
return parts.get(type)?.() ?? false;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Whether something that does more than read a value runs, inside `statement`, before `awaitNode` does.
|
|
130
|
+
* Hoisting the `await` in front of the statement would then run it first.
|
|
131
|
+
*/
|
|
132
|
+
static hasEffectBefore(opts) {
|
|
133
|
+
const target = AwaitSupport.rangeOf({ node: opts.awaitNode });
|
|
134
|
+
if (!target) {
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
const visit = (node) => {
|
|
138
|
+
const range = AwaitSupport.rangeOf({ node });
|
|
139
|
+
if (!range) {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
if (range[0] <= target[0] && target[1] <= range[1]) {
|
|
143
|
+
const keys = opts.sourceCode.visitorKeys[(0, common_1.nodeType)({ node }) ?? ''] ?? [];
|
|
144
|
+
return keys.some((key) => {
|
|
145
|
+
const value = (0, common_1.readField)({ node, key });
|
|
146
|
+
const entries = Array.isArray(value) ? value : [value];
|
|
147
|
+
return entries.some((entry) => entry && entry !== opts.awaitNode && visit(entry));
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
return range[1] <= target[0] && !AwaitSupport.isPure({ node });
|
|
151
|
+
};
|
|
152
|
+
return visit(opts.statement);
|
|
153
|
+
}
|
|
154
|
+
/** The leading whitespace of the line a node starts on. */
|
|
155
|
+
static indentOf(opts) {
|
|
156
|
+
const line = opts.sourceCode.lines[(opts.node.loc?.start.line ?? 1) - 1] ?? '';
|
|
157
|
+
return /^\s*/.exec(line)?.[0] ?? '';
|
|
158
|
+
}
|
|
159
|
+
/** The nearest function or the program that holds `node`: the scope a new name must be free in. */
|
|
160
|
+
static scopeNodeOf(opts) {
|
|
161
|
+
let current = opts.node;
|
|
162
|
+
let parent = AwaitSupport.parentOf({ node: current });
|
|
163
|
+
while (parent && !FUNCTION_TYPES.has((0, common_1.nodeType)({ node: parent }) ?? '')) {
|
|
164
|
+
if (!AwaitSupport.isNode(parent)) {
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
current = parent;
|
|
168
|
+
parent = AwaitSupport.parentOf({ node: current });
|
|
169
|
+
}
|
|
170
|
+
return AwaitSupport.isNode(parent) ? parent : current;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* `base`, or `base2`, `base3`... the first word that does not appear in the function (or program) holding `node`
|
|
174
|
+
* and that this lint pass has not handed out already: two fixes of one pass must not declare the same name.
|
|
175
|
+
*/
|
|
176
|
+
static freshName(opts) {
|
|
177
|
+
const scope = AwaitSupport.scopeNodeOf({ node: opts.node });
|
|
178
|
+
const text = opts.sourceCode.getText(scope);
|
|
179
|
+
const reserved = opts.taken.get(scope) ?? new Set();
|
|
180
|
+
for (let index = 1;; index += 1) {
|
|
181
|
+
const candidate = index === 1 ? opts.base : `${opts.base}${index}`;
|
|
182
|
+
if (!reserved.has(candidate) && !new RegExp(`\\b${candidate}\\b`).test(text)) {
|
|
183
|
+
reserved.add(candidate);
|
|
184
|
+
opts.taken.set(scope, reserved);
|
|
185
|
+
return candidate;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* The range to replace with the name that stands for an `await`: the `await` itself, widened over the parentheses
|
|
191
|
+
* around it when they only grouped it (`(await f()).x`, `!(await f())`).
|
|
192
|
+
*/
|
|
193
|
+
static replaceRangeOf(opts) {
|
|
194
|
+
const { awaitNode, sourceCode } = opts;
|
|
195
|
+
const before = sourceCode.getTokenBefore(awaitNode);
|
|
196
|
+
const after = sourceCode.getTokenAfter(awaitNode);
|
|
197
|
+
const parentType = (0, common_1.nodeType)({ node: AwaitSupport.parentOf({ node: awaitNode }) }) ?? '';
|
|
198
|
+
const callee = parentType === 'CallExpression' &&
|
|
199
|
+
(0, common_1.readField)({ node: AwaitSupport.parentOf({ node: awaitNode }), key: 'callee' }) === awaitNode;
|
|
200
|
+
if (before?.value === '(' &&
|
|
201
|
+
after?.value === ')' &&
|
|
202
|
+
(GROUPING_PARENTS.has(parentType) || callee)) {
|
|
203
|
+
return [before.range[0], after.range[1]];
|
|
204
|
+
}
|
|
205
|
+
return [awaitNode.range?.[0] ?? 0, awaitNode.range?.[1] ?? 0];
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
exports.AwaitSupport = AwaitSupport;
|
|
209
|
+
//# sourceMappingURL=await-support.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"await-support.js","sourceRoot":"","sources":["../../../src/linters/house/await-support.ts"],"names":[],"mappings":";;;AACA,qCAA+C;AAE/C,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,gBAAgB,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,CAAC,CAAC,CAAC;AAC5F,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC;IAC7B,qBAAqB;IACrB,oBAAoB;IACpB,yBAAyB;CAC1B,CAAC,CAAC;AACH,+FAA+F;AAC/F,MAAM,UAAU,GAA2B;IACzC,WAAW,EAAE,MAAM;IACnB,eAAe,EAAE,cAAc;IAC/B,cAAc,EAAE,OAAO;IACvB,cAAc,EAAE,OAAO;IACvB,mBAAmB,EAAE,YAAY;IACjC,eAAe,EAAE,UAAU;IAC3B,cAAc,EAAE,UAAU;CAC3B,CAAC;AACF,oHAAoH;AACpH,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC;IAC1B,YAAY;IACZ,SAAS;IACT,gBAAgB;IAChB,yBAAyB;IACzB,oBAAoB;IACpB,mBAAmB;CACpB,CAAC,CAAC;AACH,gGAAgG;AAChG,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC;IAC/B,kBAAkB;IAClB,gBAAgB;IAChB,uBAAuB;IACvB,qBAAqB;IACrB,iBAAiB;IACjB,kBAAkB;IAClB,eAAe;IACf,iBAAiB;CAClB,CAAC,CAAC;AAEH,2HAA2H;AAC3H,MAAa,YAAY;IACvB,MAAM,CAAC,QAAQ,CAAC,IAAuB;QACrC,OAAO,IAAA,kBAAS,EAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,qEAAqE;IACrE,MAAM,CAAC,MAAM,CAAC,KAAc;QAC1B,OAAO,CACL,IAAA,iBAAQ,EAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,KAAK,SAAS,IAAI,YAAY,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,KAAK,SAAS,CAC/F,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,OAAO,CAAC,IAAuB;QACpC,MAAM,KAAK,GAAG,IAAA,kBAAS,EAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAC3D,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ;YACzF,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;YACtB,CAAC,CAAC,SAAS,CAAC;IAChB,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,WAAW,CAAC,IAA4B;QAC7C,IAAI,KAAK,GAAY,IAAI,CAAC,SAAS,CAAC;QACpC,IAAI,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAEtD,OAAO,QAAQ,EAAE,CAAC;YAChB,MAAM,IAAI,GAAG,IAAA,iBAAQ,EAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;YAEhD,IAAI,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,KAAK,iBAAiB,EAAE,CAAC;gBAC3D,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,IACE,IAAI,KAAK,uBAAuB;gBAChC,IAAA,kBAAS,EAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,KAAK,KAAK,EACpD,CAAC;gBACD,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,IAAI,IAAI,KAAK,mBAAmB,IAAI,IAAA,kBAAS,EAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC;gBACzF,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,IACE,IAAI,KAAK,sBAAsB;gBAC/B,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAA,kBAAS,EAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;gBACtF,IAAA,kBAAS,EAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,KAAK,KAAK,EACrD,CAAC;gBACD,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,IAAI,KAAK,qBAAqB,EAAE,CAAC;gBACjE,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;gBAC9B,MAAM,MAAM,GACV,IAAI,KAAK,qBAAqB,IAAI,IAAA,kBAAS,EAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,KAAK,KAAK,CAAC;gBACvF,MAAM,KAAK,GAAG,YAAY,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;gBAExD,MAAM,QAAQ,GACZ,eAAe,CAAC,GAAG,CAAC,IAAA,iBAAQ,EAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC;oBACpD,CAAC,IAAI,KAAK,qBAAqB,IAAI,IAAI,KAAK,SAAS,CAAC,CAAC;gBAEzD,OAAO,MAAM,IAAI,QAAQ,IAAI,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;YACpF,CAAC;YAED,KAAK,GAAG,QAAQ,CAAC;YACjB,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACpD,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,CAAC,MAAM,CAAC,IAAuB;QACnC,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;QACtB,MAAM,IAAI,GAAG,IAAA,iBAAQ,EAAC,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,CAAC,KAAc,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACtE,MAAM,KAAK,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,IAAA,kBAAS,EAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QACxD,MAAM,GAAG,GAAG,CAAC,GAAW,EAAE,EAAE;YAC1B,MAAM,IAAI,GAAG,IAAA,kBAAS,EAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;YACtC,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QACrF,CAAC,CAAC;QAEF,IACE,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC;YACrB,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;gBACpB,CAAC,CAAC,gBAAgB,EAAE,qBAAqB,EAAE,uBAAuB,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EACrF,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,GAAG,CAAwB;YAC3C,CAAC,iBAAiB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YAC7C,CAAC,kBAAkB,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;YAC5E,CAAC,iBAAiB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAC1C,CAAC,kBAAkB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC7C,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;YAC9D,CAAC,eAAe,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;YAChD,CAAC,iBAAiB,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;YACpF,CAAC,kBAAkB,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;YACvE,CAAC,mBAAmB,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;YACxE;gBACE,uBAAuB;gBACvB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;aAC3E;YACD,CAAC,gBAAgB,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;YACnD,CAAC,qBAAqB,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;YACxD,CAAC,uBAAuB,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;SAC3D,CAAC,CAAC;QAEH,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,KAAK,CAAC;IACtC,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,eAAe,CAAC,IAItB;QACC,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;QAC9D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,KAAK,GAAG,CAAC,IAAa,EAAW,EAAE;YACvC,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;YAC7C,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO,KAAK,CAAC;YACf,CAAC;YACD,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;gBACnD,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAA,iBAAQ,EAAC,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;gBAEzE,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;oBACvB,MAAM,KAAK,GAAG,IAAA,kBAAS,EAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;oBACvC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;oBAEvD,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,IAAI,KAAK,KAAK,IAAI,CAAC,SAAS,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;gBACpF,CAAC,CAAC,CAAC;YACL,CAAC;YAED,OAAO,KAAK,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QACjE,CAAC,CAAC;QAEF,OAAO,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC/B,CAAC;IAED,2DAA2D;IAC3D,MAAM,CAAC,QAAQ,CAAC,IAAiD;QAC/D,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QAC/E,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACtC,CAAC;IAED,mGAAmG;IACnG,MAAM,CAAC,WAAW,CAAC,IAAyB;QAC1C,IAAI,OAAO,GAAc,IAAI,CAAC,IAAI,CAAC;QACnC,IAAI,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QAEtD,OAAO,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAA,iBAAQ,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YACvE,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;gBACjC,MAAM;YACR,CAAC;YACD,OAAO,GAAG,MAAM,CAAC;YACjB,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QACpD,CAAC;QAED,OAAO,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;IACxD,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,SAAS,CAAC,IAKhB;QACC,MAAM,KAAK,GAAG,YAAY,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5D,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,GAAG,EAAU,CAAC;QAE5D,KAAK,IAAI,KAAK,GAAG,CAAC,GAAI,KAAK,IAAI,CAAC,EAAE,CAAC;YACjC,MAAM,SAAS,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,GAAG,KAAK,EAAE,CAAC;YACnE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,SAAS,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC7E,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBACxB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;gBAEhC,OAAO,SAAS,CAAC;YACnB,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,cAAc,CAAC,IAAsD;QAC1E,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;QACvC,MAAM,MAAM,GAAG,UAAU,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QACpD,MAAM,KAAK,GAAG,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;QAClD,MAAM,UAAU,GAAG,IAAA,iBAAQ,EAAC,EAAE,IAAI,EAAE,YAAY,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;QACxF,MAAM,MAAM,GACV,UAAU,KAAK,gBAAgB;YAC/B,IAAA,kBAAS,EAAC,EAAE,IAAI,EAAE,YAAY,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,KAAK,SAAS,CAAC;QAE/F,IACE,MAAM,EAAE,KAAK,KAAK,GAAG;YACrB,KAAK,EAAE,KAAK,KAAK,GAAG;YACpB,CAAC,gBAAgB,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC,EAC5C,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3C,CAAC;QAED,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAChE,CAAC;CACF;AAxND,oCAwNC","sourcesContent":["import type { Rule, SourceCode } from 'eslint';\nimport { nodeType, readField } from './common';\n\nconst STATEMENT_LISTS = new Set(['BlockStatement', 'Program', 'StaticBlock', 'SwitchCase']);\nconst FUNCTION_TYPES = new Set([\n 'FunctionDeclaration',\n 'FunctionExpression',\n 'ArrowFunctionExpression',\n]);\n/** The child of a statement that runs exactly once, before anything else of that statement. */\nconst HEAD_FIELD: Record<string, string> = {\n IfStatement: 'test',\n SwitchStatement: 'discriminant',\n ForOfStatement: 'right',\n ForInStatement: 'right',\n ExpressionStatement: 'expression',\n ReturnStatement: 'argument',\n ThrowStatement: 'argument',\n};\n/** Nodes that evaluate to a value without doing anything else, so running them later or earlier changes nothing. */\nconst PURE_LEAVES = new Set([\n 'Identifier',\n 'Literal',\n 'ThisExpression',\n 'ArrowFunctionExpression',\n 'FunctionExpression',\n 'PrivateIdentifier',\n]);\n/** Wrappers whose parentheses around an `await` carry no meaning once the `await` is a name. */\nconst GROUPING_PARENTS = new Set([\n 'MemberExpression',\n 'TSAsExpression',\n 'TSSatisfiesExpression',\n 'TSNonNullExpression',\n 'UnaryExpression',\n 'BinaryExpression',\n 'SpreadElement',\n 'ArrayExpression',\n]);\n\n/** The shared parts of the two `await` rules: where a statement can go before another, what may run first, fresh names. */\nexport class AwaitSupport {\n static parentOf(opts: { node: unknown }): unknown {\n return readField({ node: opts.node, key: 'parent' });\n }\n\n /** An ESTree node of the lint run: it has a `type` and a `range`. */\n static isNode(value: unknown): value is Rule.Node {\n return (\n nodeType({ node: value }) !== undefined && AwaitSupport.rangeOf({ node: value }) !== undefined\n );\n }\n\n static rangeOf(opts: { node: unknown }): [number, number] | undefined {\n const range = readField({ node: opts.node, key: 'range' });\n return Array.isArray(range) && typeof range[0] === 'number' && typeof range[1] === 'number'\n ? [range[0], range[1]]\n : undefined;\n }\n\n /**\n * The statement that can take a `const` in front of it so that `awaitNode` is evaluated first, or `undefined`\n * when hoisting would change what runs: the `await` sits in a branch (`?:`, the right of `&&`, `||`, `??`),\n * in a loop test or update, in an unbraced `if` branch, in an optional chain, or in an arrow expression body.\n */\n static hoistTarget(opts: { awaitNode: unknown }): Rule.Node | undefined {\n let child: unknown = opts.awaitNode;\n let ancestor = AwaitSupport.parentOf({ node: child });\n\n while (ancestor) {\n const type = nodeType({ node: ancestor }) ?? '';\n\n if (FUNCTION_TYPES.has(type) || type === 'ChainExpression') {\n return undefined;\n }\n if (\n type === 'ConditionalExpression' &&\n readField({ node: ancestor, key: 'test' }) !== child\n ) {\n return undefined;\n }\n if (type === 'LogicalExpression' && readField({ node: ancestor, key: 'left' }) !== child) {\n return undefined;\n }\n if (\n type === 'AssignmentExpression' &&\n ['??=', '||=', '&&='].includes(String(readField({ node: ancestor, key: 'operator' }))) &&\n readField({ node: ancestor, key: 'right' }) === child\n ) {\n return undefined;\n }\n if (type.endsWith('Statement') || type === 'VariableDeclaration') {\n const head = HEAD_FIELD[type];\n const isHead =\n type === 'VariableDeclaration' || readField({ node: ancestor, key: head }) === child;\n const outer = AwaitSupport.parentOf({ node: ancestor });\n\n const isListed =\n STATEMENT_LISTS.has(nodeType({ node: outer }) ?? '') &&\n (type === 'VariableDeclaration' || head !== undefined);\n\n return isHead && isListed && AwaitSupport.isNode(ancestor) ? ancestor : undefined;\n }\n\n child = ancestor;\n ancestor = AwaitSupport.parentOf({ node: child });\n }\n\n return undefined;\n }\n\n static isPure(opts: { node: unknown }): boolean {\n const { node } = opts;\n const type = nodeType({ node }) ?? '';\n const pure = (child: unknown) => AwaitSupport.isPure({ node: child });\n const field = (key: string) => readField({ node, key });\n const all = (key: string) => {\n const list = readField({ node, key });\n return Array.isArray(list) && list.every((entry) => entry === null || pure(entry));\n };\n\n if (\n PURE_LEAVES.has(type) ||\n (type.startsWith('TS') &&\n !['TSAsExpression', 'TSNonNullExpression', 'TSSatisfiesExpression'].includes(type))\n ) {\n return true;\n }\n\n const parts = new Map<string, () => boolean>([\n ['TemplateLiteral', () => all('expressions')],\n ['MemberExpression', () => pure(field('object')) && pure(field('property'))],\n ['ArrayExpression', () => all('elements')],\n ['ObjectExpression', () => all('properties')],\n ['Property', () => pure(field('key')) && pure(field('value'))],\n ['SpreadElement', () => pure(field('argument'))],\n ['UnaryExpression', () => field('operator') !== 'delete' && pure(field('argument'))],\n ['BinaryExpression', () => pure(field('left')) && pure(field('right'))],\n ['LogicalExpression', () => pure(field('left')) && pure(field('right'))],\n [\n 'ConditionalExpression',\n () => ['test', 'consequent', 'alternate'].every((key) => pure(field(key))),\n ],\n ['TSAsExpression', () => pure(field('expression'))],\n ['TSNonNullExpression', () => pure(field('expression'))],\n ['TSSatisfiesExpression', () => pure(field('expression'))],\n ]);\n\n return parts.get(type)?.() ?? false;\n }\n\n /**\n * Whether something that does more than read a value runs, inside `statement`, before `awaitNode` does.\n * Hoisting the `await` in front of the statement would then run it first.\n */\n static hasEffectBefore(opts: {\n statement: Rule.Node;\n awaitNode: unknown;\n sourceCode: SourceCode;\n }): boolean {\n const target = AwaitSupport.rangeOf({ node: opts.awaitNode });\n if (!target) {\n return true;\n }\n\n const visit = (node: unknown): boolean => {\n const range = AwaitSupport.rangeOf({ node });\n if (!range) {\n return false;\n }\n if (range[0] <= target[0] && target[1] <= range[1]) {\n const keys = opts.sourceCode.visitorKeys[nodeType({ node }) ?? ''] ?? [];\n\n return keys.some((key) => {\n const value = readField({ node, key });\n const entries = Array.isArray(value) ? value : [value];\n\n return entries.some((entry) => entry && entry !== opts.awaitNode && visit(entry));\n });\n }\n\n return range[1] <= target[0] && !AwaitSupport.isPure({ node });\n };\n\n return visit(opts.statement);\n }\n\n /** The leading whitespace of the line a node starts on. */\n static indentOf(opts: { node: Rule.Node; sourceCode: SourceCode }): string {\n const line = opts.sourceCode.lines[(opts.node.loc?.start.line ?? 1) - 1] ?? '';\n return /^\\s*/.exec(line)?.[0] ?? '';\n }\n\n /** The nearest function or the program that holds `node`: the scope a new name must be free in. */\n static scopeNodeOf(opts: { node: Rule.Node }): Rule.Node {\n let current: Rule.Node = opts.node;\n let parent = AwaitSupport.parentOf({ node: current });\n\n while (parent && !FUNCTION_TYPES.has(nodeType({ node: parent }) ?? '')) {\n if (!AwaitSupport.isNode(parent)) {\n break;\n }\n current = parent;\n parent = AwaitSupport.parentOf({ node: current });\n }\n\n return AwaitSupport.isNode(parent) ? parent : current;\n }\n\n /**\n * `base`, or `base2`, `base3`... the first word that does not appear in the function (or program) holding `node`\n * and that this lint pass has not handed out already: two fixes of one pass must not declare the same name.\n */\n static freshName(opts: {\n node: Rule.Node;\n base: string;\n sourceCode: SourceCode;\n taken: Map<unknown, Set<string>>;\n }): string {\n const scope = AwaitSupport.scopeNodeOf({ node: opts.node });\n const text = opts.sourceCode.getText(scope);\n const reserved = opts.taken.get(scope) ?? new Set<string>();\n\n for (let index = 1; ; index += 1) {\n const candidate = index === 1 ? opts.base : `${opts.base}${index}`;\n if (!reserved.has(candidate) && !new RegExp(`\\\\b${candidate}\\\\b`).test(text)) {\n reserved.add(candidate);\n opts.taken.set(scope, reserved);\n\n return candidate;\n }\n }\n }\n\n /**\n * The range to replace with the name that stands for an `await`: the `await` itself, widened over the parentheses\n * around it when they only grouped it (`(await f()).x`, `!(await f())`).\n */\n static replaceRangeOf(opts: { awaitNode: Rule.Node; sourceCode: SourceCode }): [number, number] {\n const { awaitNode, sourceCode } = opts;\n const before = sourceCode.getTokenBefore(awaitNode);\n const after = sourceCode.getTokenAfter(awaitNode);\n const parentType = nodeType({ node: AwaitSupport.parentOf({ node: awaitNode }) }) ?? '';\n const callee =\n parentType === 'CallExpression' &&\n readField({ node: AwaitSupport.parentOf({ node: awaitNode }), key: 'callee' }) === awaitNode;\n\n if (\n before?.value === '(' &&\n after?.value === ')' &&\n (GROUPING_PARENTS.has(parentType) || callee)\n ) {\n return [before.range[0], after.range[1]];\n }\n\n return [awaitNode.range?.[0] ?? 0, awaitNode.range?.[1] ?? 0];\n }\n}\n"]}
|
|
@@ -7,6 +7,8 @@ export declare class AstNodeTypes {
|
|
|
7
7
|
static readonly ARROW_FUNCTION_EXPRESSION = "ArrowFunctionExpression";
|
|
8
8
|
static readonly EXPORT_NAMED_DECLARATION = "ExportNamedDeclaration";
|
|
9
9
|
static readonly UNION_TYPE = "TSUnionType";
|
|
10
|
+
static readonly AWAIT_EXPRESSION = "AwaitExpression";
|
|
11
|
+
static readonly RETURN_STATEMENT = "ReturnStatement";
|
|
10
12
|
}
|
|
11
13
|
/** The ESLint namespace the house rules live under: `venizia/<rule>`. */
|
|
12
14
|
export declare const HOUSE_PLUGIN_NAMESPACE = "venizia";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../src/linters/house/common.ts"],"names":[],"mappings":"AAAA,8HAA8H;AAC9H,qBAAa,YAAY;IACvB,MAAM,CAAC,QAAQ,CAAC,cAAc,mBAAmB;IACjD,MAAM,CAAC,QAAQ,CAAC,eAAe,oBAAoB;IACnD,MAAM,CAAC,QAAQ,CAAC,oBAAoB,yBAAyB;IAC7D,MAAM,CAAC,QAAQ,CAAC,mBAAmB,wBAAwB;IAC3D,MAAM,CAAC,QAAQ,CAAC,yBAAyB,6BAA6B;IACtE,MAAM,CAAC,QAAQ,CAAC,wBAAwB,4BAA4B;IACpE,MAAM,CAAC,QAAQ,CAAC,UAAU,iBAAiB;
|
|
1
|
+
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../src/linters/house/common.ts"],"names":[],"mappings":"AAAA,8HAA8H;AAC9H,qBAAa,YAAY;IACvB,MAAM,CAAC,QAAQ,CAAC,cAAc,mBAAmB;IACjD,MAAM,CAAC,QAAQ,CAAC,eAAe,oBAAoB;IACnD,MAAM,CAAC,QAAQ,CAAC,oBAAoB,yBAAyB;IAC7D,MAAM,CAAC,QAAQ,CAAC,mBAAmB,wBAAwB;IAC3D,MAAM,CAAC,QAAQ,CAAC,yBAAyB,6BAA6B;IACtE,MAAM,CAAC,QAAQ,CAAC,wBAAwB,4BAA4B;IACpE,MAAM,CAAC,QAAQ,CAAC,UAAU,iBAAiB;IAC3C,MAAM,CAAC,QAAQ,CAAC,gBAAgB,qBAAqB;IACrD,MAAM,CAAC,QAAQ,CAAC,gBAAgB,qBAAqB;CACtD;AAED,yEAAyE;AACzE,eAAO,MAAM,sBAAsB,YAAY,CAAC;AAEhD,qHAAqH;AACrH,eAAO,MAAM,SAAS,GAAI,MAAM;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,KAAG,OAKhE,CAAC;AAEF,8EAA8E;AAC9E,eAAO,MAAM,QAAQ,GAAI,MAAM;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,KAAG,MAAM,GAAG,SAG3D,CAAC"}
|
|
@@ -10,6 +10,8 @@ class AstNodeTypes {
|
|
|
10
10
|
static { this.ARROW_FUNCTION_EXPRESSION = 'ArrowFunctionExpression'; }
|
|
11
11
|
static { this.EXPORT_NAMED_DECLARATION = 'ExportNamedDeclaration'; }
|
|
12
12
|
static { this.UNION_TYPE = 'TSUnionType'; }
|
|
13
|
+
static { this.AWAIT_EXPRESSION = 'AwaitExpression'; }
|
|
14
|
+
static { this.RETURN_STATEMENT = 'ReturnStatement'; }
|
|
13
15
|
}
|
|
14
16
|
exports.AstNodeTypes = AstNodeTypes;
|
|
15
17
|
/** The ESLint namespace the house rules live under: `venizia/<rule>`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../../src/linters/house/common.ts"],"names":[],"mappings":";;;AAAA,8HAA8H;AAC9H,MAAa,YAAY;aACP,mBAAc,GAAG,eAAe,CAAC;aACjC,oBAAe,GAAG,gBAAgB,CAAC;aACnC,yBAAoB,GAAG,qBAAqB,CAAC;aAC7C,wBAAmB,GAAG,oBAAoB,CAAC;aAC3C,8BAAyB,GAAG,yBAAyB,CAAC;aACtD,6BAAwB,GAAG,wBAAwB,CAAC;aACpD,eAAU,GAAG,aAAa,CAAC;;
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../../src/linters/house/common.ts"],"names":[],"mappings":";;;AAAA,8HAA8H;AAC9H,MAAa,YAAY;aACP,mBAAc,GAAG,eAAe,CAAC;aACjC,oBAAe,GAAG,gBAAgB,CAAC;aACnC,yBAAoB,GAAG,qBAAqB,CAAC;aAC7C,wBAAmB,GAAG,oBAAoB,CAAC;aAC3C,8BAAyB,GAAG,yBAAyB,CAAC;aACtD,6BAAwB,GAAG,wBAAwB,CAAC;aACpD,eAAU,GAAG,aAAa,CAAC;aAC3B,qBAAgB,GAAG,iBAAiB,CAAC;aACrC,qBAAgB,GAAG,iBAAiB,CAAC;;AATvD,oCAUC;AAED,yEAAyE;AAC5D,QAAA,sBAAsB,GAAG,SAAS,CAAC;AAEhD,qHAAqH;AAC9G,MAAM,SAAS,GAAG,CAAC,IAAoC,EAAW,EAAE;IACzE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAC3B,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI;QAC7D,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC;QACxB,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC,CAAC;AALW,QAAA,SAAS,aAKpB;AAEF,8EAA8E;AACvE,MAAM,QAAQ,GAAG,CAAC,IAAuB,EAAsB,EAAE;IACtE,MAAM,IAAI,GAAG,IAAA,iBAAS,EAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;IACzD,OAAO,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AACrD,CAAC,CAAC;AAHW,QAAA,QAAQ,YAGnB","sourcesContent":["/** The estree node types the house rules visit - computed visitor keys, so the names stay PascalCase as ESLint needs them. */\nexport class AstNodeTypes {\n static readonly NEW_EXPRESSION = 'NewExpression';\n static readonly CALL_EXPRESSION = 'CallExpression';\n static readonly FUNCTION_DECLARATION = 'FunctionDeclaration';\n static readonly FUNCTION_EXPRESSION = 'FunctionExpression';\n static readonly ARROW_FUNCTION_EXPRESSION = 'ArrowFunctionExpression';\n static readonly EXPORT_NAMED_DECLARATION = 'ExportNamedDeclaration';\n static readonly UNION_TYPE = 'TSUnionType';\n static readonly AWAIT_EXPRESSION = 'AwaitExpression';\n static readonly RETURN_STATEMENT = 'ReturnStatement';\n}\n\n/** The ESLint namespace the house rules live under: `venizia/<rule>`. */\nexport const HOUSE_PLUGIN_NAMESPACE = 'venizia';\n\n/** A field of an AST node, read without trusting its type: TypeScript nodes carry fields estree does not declare. */\nexport const readField = (opts: { node: unknown; key: string }): unknown => {\n const { node, key } = opts;\n return typeof node === 'object' && node !== null && key in node\n ? Reflect.get(node, key)\n : undefined;\n};\n\n/** The node's `type`, or `undefined` for anything that is not an AST node. */\nexport const nodeType = (opts: { node: unknown }): string | undefined => {\n const type = readField({ node: opts.node, key: 'type' });\n return typeof type === 'string' ? type : undefined;\n};\n"]}
|
|
@@ -13,4 +13,27 @@ import type { Linter } from 'eslint';
|
|
|
13
13
|
export declare const houseConfigs: Linter.Config[];
|
|
14
14
|
/** `houseConfigs` for a React project: `reactNamingConventionConfigs`, the house rules and `no-leaked-render`. */
|
|
15
15
|
export declare const reactHouseConfigs: Linter.Config[];
|
|
16
|
+
/**
|
|
17
|
+
* The async style rules, opt-in until every Venizia repository has been swept (the owner's rollout: the option in
|
|
18
|
+
* one release, the default in the next). Spread it next to `houseConfigs`:
|
|
19
|
+
*
|
|
20
|
+
* ```js
|
|
21
|
+
* export default [...houseConfigs, ...asyncStyleConfigs];
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* `await` stands alone as a statement or as the whole initializer of a declaration (`no-inline-await`), and a
|
|
25
|
+
* function returns the promise instead of `return await` (`no-return-await`). They apply to test files too.
|
|
26
|
+
*/
|
|
27
|
+
export declare const asyncStyleConfigs: Linter.Config[];
|
|
28
|
+
/**
|
|
29
|
+
* The hook async rules, opt-in like `asyncStyleConfigs`. Spread it next to `reactHouseConfigs`:
|
|
30
|
+
*
|
|
31
|
+
* ```js
|
|
32
|
+
* export default [...reactHouseConfigs, ...reactAsyncStyleConfigs];
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* A hook never gets an async function (`no-async-hook-callback`), and an effect callback returns a cleanup on every
|
|
36
|
+
* path or on none (`effect-cleanup-consistency`). Hooks live in `.ts` files too, so it covers all source files.
|
|
37
|
+
*/
|
|
38
|
+
export declare const reactAsyncStyleConfigs: Linter.Config[];
|
|
16
39
|
//# sourceMappingURL=configs.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configs.d.ts","sourceRoot":"","sources":["../../../src/linters/house/configs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"configs.d.ts","sourceRoot":"","sources":["../../../src/linters/house/configs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAsDrC;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAsD,CAAC;AAc/F,kHAAkH;AAClH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAI5C,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAS5C,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EASjD,CAAC"}
|