fix(linter): update typescript eslint dependency (#11112)

Co-authored-by: Miroslav Jonas <missing.manual@gmail.com>
This commit is contained in:
Laforge Thomas 2022-07-20 23:57:51 +02:00 committed by GitHub
parent 5f097b90ff
commit c117ad51ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 364 additions and 29 deletions

View File

@ -110,7 +110,7 @@
"@types/tmp": "^0.2.0",
"@types/yargs": "^17.0.10",
"@typescript-eslint/eslint-plugin": "^5.29.0",
"@typescript-eslint/experimental-utils": "^5.29.0",
"@typescript-eslint/utils": "^5.29.0",
"@typescript-eslint/parser": "^5.29.0",
"@xstate/immer": "^0.2.0",
"@xstate/inspect": "^0.5.1",

View File

@ -34,7 +34,7 @@
"dependencies": {
"@nrwl/devkit": "file:../devkit",
"@nrwl/workspace": "file:../workspace",
"@typescript-eslint/experimental-utils": "^5.29.0",
"@typescript-eslint/utils": "^5.29.0",
"chalk": "4.1.0",
"confusing-browser-globals": "^1.0.9",
"semver": "7.3.4"

View File

@ -1,7 +1,7 @@
import type { TSESLint } from '@typescript-eslint/experimental-utils';
import type { TSESLint } from '@typescript-eslint/utils';
import { existsSync } from 'fs';
import { WORKSPACE_PLUGIN_DIR, WORKSPACE_RULE_NAMESPACE } from './constants';
import { registerTsProject } from 'nx/src/utils/register';
import { WORKSPACE_PLUGIN_DIR, WORKSPACE_RULE_NAMESPACE } from './constants';
type ESLintRules = Record<string, TSESLint.RuleModule<string, unknown[]>>;

View File

@ -1,13 +1,13 @@
import type { FileData, ProjectGraph } from '@nrwl/devkit';
import { DependencyType } from '@nrwl/devkit';
import { TSESLint } from '@typescript-eslint/experimental-utils';
import { mapProjectGraphFiles } from '@nrwl/workspace/src/utils/runtime-lint-utils';
import * as parser from '@typescript-eslint/parser';
import { TSESLint } from '@typescript-eslint/utils';
import { vol } from 'memfs';
import { TargetProjectLocator } from 'nx/src/utils/target-project-locator';
import enforceModuleBoundaries, {
RULE_NAME as enforceModuleBoundariesRuleName,
} from '../../src/rules/enforce-module-boundaries';
import { TargetProjectLocator } from 'nx/src/utils/target-project-locator';
import { mapProjectGraphFiles } from '@nrwl/workspace/src/utils/runtime-lint-utils';
jest.mock('fs', () => require('memfs').fs);

View File

@ -1,10 +1,15 @@
import {
workspaceRoot,
joinPathFragments,
normalizePath,
ProjectGraphExternalNode,
ProjectGraphProjectNode,
workspaceRoot,
} from '@nrwl/devkit';
import { isRelativePath } from '@nrwl/workspace/src/utilities/fileutils';
import {
checkCircularPath,
findFilesInCircularPath,
} from '@nrwl/workspace/src/utils/graph-utils';
import {
DepConstraint,
findConstraintsFor,
@ -26,23 +31,15 @@ import {
onlyLoadChildren,
stringifyTags,
} from '@nrwl/workspace/src/utils/runtime-lint-utils';
import {
AST_NODE_TYPES,
TSESTree,
} from '@typescript-eslint/experimental-utils';
import { createESLintRule } from '../utils/create-eslint-rule';
import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/utils';
import { TargetProjectLocator } from 'nx/src/utils/target-project-locator';
import {
checkCircularPath,
findFilesInCircularPath,
} from '@nrwl/workspace/src/utils/graph-utils';
import { isRelativePath } from '@nrwl/workspace/src/utilities/fileutils';
import { basename, dirname, relative } from 'path';
import {
getBarrelEntryPointByImportScope,
getBarrelEntryPointProjectNode,
getRelativeImportPath,
} from '../utils/ast-utils';
import { createESLintRule } from '../utils/create-eslint-rule';
import { readProjectGraph } from '../utils/project-graph-utils';
type Options = [

View File

@ -1,3 +1,3 @@
import { ESLintUtils } from '@typescript-eslint/experimental-utils';
import { ESLintUtils } from '@typescript-eslint/utils';
export const createESLintRule = ESLintUtils.RuleCreator(() => ``);

View File

@ -76,6 +76,18 @@
"version": "14.2.3-beta.0",
"description": "Adds @swc/core and @swc-node as a dev dep if you are using them (repeated due to prior mistake)",
"factory": "./src/migrations/update-14-1-9/add-swc-deps-if-needed"
},
"experimental-to-utils-deps": {
"cli": "nx",
"version": "14.4.4",
"description": "Adds @typescript-eslint/utils as a dev dep",
"factory": "./src/migrations/update-14-4-4/experimental-to-utils-deps"
},
"experimental-to-utils-rules": {
"cli": "nx",
"version": "14.4.4",
"description": "Switch from @typescript-eslint/experimental-utils to @typescript-eslint/utils in all rules and rules.spec files",
"factory": "./src/migrations/update-14-4-4/experimental-to-utils-rules"
}
},
"packageJsonUpdates": {
@ -245,6 +257,14 @@
"version": "^5.29.0"
}
}
},
"14.4.4": {
"version": "14.4.4",
"packages": {
"@typescript-eslint/utils": {
"version": "^5.29.0"
}
}
}
}
}

View File

@ -17,7 +17,7 @@ exports[`@nrwl/linter:workspace-rule --dir should support creating the rule in a
* https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin/src/rules
*/
import { ESLintUtils } from '@typescript-eslint/experimental-utils';
import { ESLintUtils } from '@typescript-eslint/utils';
// NOTE: The rule will be available in ESLint configs as \\"@nrwl/nx/workspace/another-rule\\"
export const RULE_NAME = 'another-rule';
@ -42,7 +42,7 @@ export const rule = ESLintUtils.RuleCreator(() => __filename)({
`;
exports[`@nrwl/linter:workspace-rule --dir should support creating the rule in a nested directory 2`] = `
"import { TSESLint } from '@typescript-eslint/experimental-utils';
"import { TSESLint } from '@typescript-eslint/utils';
import { rule, RULE_NAME } from './another-rule';
const ruleTester = new TSESLint.RuleTester({
@ -73,7 +73,7 @@ exports[`@nrwl/linter:workspace-rule --dir should support creating the rule in a
* https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin/src/rules
*/
import { ESLintUtils } from '@typescript-eslint/experimental-utils';
import { ESLintUtils } from '@typescript-eslint/utils';
// NOTE: The rule will be available in ESLint configs as \\"@nrwl/nx/workspace/one-more-rule\\"
export const RULE_NAME = 'one-more-rule';
@ -98,7 +98,7 @@ export const rule = ESLintUtils.RuleCreator(() => __filename)({
`;
exports[`@nrwl/linter:workspace-rule --dir should support creating the rule in a nested directory with multiple levels of nesting 2`] = `
"import { TSESLint } from '@typescript-eslint/experimental-utils';
"import { TSESLint } from '@typescript-eslint/utils';
import { rule, RULE_NAME } from './one-more-rule';
const ruleTester = new TSESLint.RuleTester({
@ -129,7 +129,7 @@ exports[`@nrwl/linter:workspace-rule should generate the required files 1`] = `
* https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin/src/rules
*/
import { ESLintUtils } from '@typescript-eslint/experimental-utils';
import { ESLintUtils } from '@typescript-eslint/utils';
// NOTE: The rule will be available in ESLint configs as \\"@nrwl/nx/workspace/my-rule\\"
export const RULE_NAME = 'my-rule';
@ -154,7 +154,7 @@ export const rule = ESLintUtils.RuleCreator(() => __filename)({
`;
exports[`@nrwl/linter:workspace-rule should generate the required files 2`] = `
"import { TSESLint } from '@typescript-eslint/experimental-utils';
"import { TSESLint } from '@typescript-eslint/utils';
import { rule, RULE_NAME } from './my-rule';
const ruleTester = new TSESLint.RuleTester({

View File

@ -1,4 +1,4 @@
import { TSESLint } from '@typescript-eslint/experimental-utils';
import { TSESLint } from '@typescript-eslint/utils';
import { rule, RULE_NAME } from './<%= name %>';
const ruleTester = new TSESLint.RuleTester({

View File

@ -14,7 +14,7 @@
* https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin/src/rules
*/
import { ESLintUtils } from '@typescript-eslint/experimental-utils';
import { ESLintUtils } from '@typescript-eslint/utils';
// NOTE: The rule will be available in ESLint configs as "@nrwl/nx/workspace/<%= name %>"
export const RULE_NAME = '<%= name %>';

View File

@ -0,0 +1,36 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`addTypescriptEslintUtilsIfNeeded() should add @typescript-eslint/utils if plugins folder exists 1`] = `
"{
\\"name\\": \\"test-name\\",
\\"dependencies\\": {},
\\"devDependencies\\": {
\\"@typescript-eslint/utils\\": \\"^5.29.0\\"
}
}
"
`;
exports[`addTypescriptEslintUtilsIfNeeded() should not add @typescript-eslint/utils if plugins folder or experimental-utils dont exist 1`] = `"{\\"name\\":\\"test-name\\",\\"dependencies\\":{},\\"devDependencies\\":{}}"`;
exports[`addTypescriptEslintUtilsIfNeeded() should remove @typescript-eslint/experimental-utils from package.json devDependencies and add @typescript-eslint/utils 1`] = `
"{
\\"name\\": \\"test-name\\",
\\"dependencies\\": {},
\\"devDependencies\\": {
\\"@typescript-eslint/utils\\": \\"^5.29.0\\"
}
}
"
`;
exports[`addTypescriptEslintUtilsIfNeeded() should remove @typescript-eslint/experimental-utils from package.json devDependencies and add @typescript-eslint/utils 2`] = `
"{
\\"name\\": \\"test-name\\",
\\"dependencies\\": {},
\\"devDependencies\\": {
\\"@typescript-eslint/utils\\": \\"^5.29.0\\"
}
}
"
`;

View File

@ -0,0 +1,51 @@
import { updateJson } from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { WORKSPACE_PLUGIN_DIR } from '../../generators/workspace-rules-project/workspace-rules-project';
import addTypescriptEslintUtilsIfNeeded from './experimental-to-utils-deps';
describe('addTypescriptEslintUtilsIfNeeded()', () => {
it('should remove @typescript-eslint/experimental-utils from package.json devDependencies and add @typescript-eslint/utils', async () => {
const tree = createTreeWithEmptyWorkspace();
updateJson(tree, 'package.json', (json) => {
json.devDependencies['@typescript-eslint/experimental-utils'] = '12.3.4';
return json;
});
await addTypescriptEslintUtilsIfNeeded(tree);
expect(tree.read(`package.json`).toString('utf-8')).toMatchSnapshot();
});
it('should remove @typescript-eslint/experimental-utils from package.json devDependencies and add @typescript-eslint/utils', async () => {
const tree = createTreeWithEmptyWorkspace();
updateJson(tree, 'package.json', (json) => {
json.dependencies['@typescript-eslint/experimental-utils'] = '12.3.4';
return json;
});
await addTypescriptEslintUtilsIfNeeded(tree);
expect(tree.read(`package.json`).toString('utf-8')).toMatchSnapshot();
});
it('should add @typescript-eslint/utils if plugins folder exists', async () => {
const tree = createTreeWithEmptyWorkspace();
tree.write(
`${WORKSPACE_PLUGIN_DIR}/rules/my-rule.ts`,
'console.log("not important");'
);
await addTypescriptEslintUtilsIfNeeded(tree);
expect(tree.read(`package.json`).toString('utf-8')).toMatchSnapshot();
});
it('should not add @typescript-eslint/utils if plugins folder or experimental-utils dont exist', async () => {
const tree = createTreeWithEmptyWorkspace();
await addTypescriptEslintUtilsIfNeeded(tree);
expect(tree.read(`package.json`).toString('utf-8')).toMatchSnapshot();
});
});

View File

@ -0,0 +1,45 @@
import {
addDependenciesToPackageJson,
formatFiles,
readJson,
removeDependenciesFromPackageJson,
Tree,
} from '@nrwl/devkit';
import { WORKSPACE_PLUGIN_DIR } from '../../generators/workspace-rules-project/workspace-rules-project';
import { typescriptESLintVersion } from '../../utils/versions';
export default async function addTypescriptEslintUtilsIfNeeded(tree: Tree) {
try {
const packageJson = readJson(tree, 'package.json');
let removed = false;
if (packageJson.devDependencies['@typescript-eslint/experimental-utils']) {
await removeDependenciesFromPackageJson(
tree,
[],
['@typescript-eslint/experimental-utils']
);
removed = true;
}
if (packageJson.dependencies['@typescript-eslint/experimental-utils']) {
await removeDependenciesFromPackageJson(
tree,
['@typescript-eslint/experimental-utils'],
[]
);
removed = true;
}
if (removed || tree.exists(WORKSPACE_PLUGIN_DIR)) {
addDependenciesToPackageJson(
tree,
{},
{ '@typescript-eslint/utils': typescriptESLintVersion }
);
await formatFiles(tree);
}
return;
} catch {}
}

View File

@ -0,0 +1,135 @@
import { Tree } from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import experimentalToUtilsUpdate from './experimental-to-utils-rules';
describe('experimentalToUtilsUpdate()', () => {
let tree: Tree;
beforeEach(() => {
tree = createTreeWithEmptyWorkspace();
tree.write(
`tools/eslint-rules/rules/existing-rule.ts`,
`
import { ESLintUtils } from '@typescript-eslint/experimental-utils';
import { rule, RULE_NAME } from './existing-rule';
// NOTE: The rule will be available in ESLint configs as "@nrwl/nx/workspace/existing-rule"
export const RULE_NAME = 'existing-rule';
export const rule = ESLintUtils.RuleCreator(() => __filename)({
name: RULE_NAME,
meta: {
type: 'problem',
docs: {
description: \`\`,
recommended: 'error',
},
schema: [],
messages: {},
},
defaultOptions: [],
create(context) {
return {};
},
});
`
);
tree.write(
`tools/eslint-rules/rules/existing-rule.spec.ts`,
`
import { TSESLint } from '@typescript-eslint/experimental-utils';
import { rule, RULE_NAME } from './existing-rule';
const ruleTester = new TSESLint.RuleTester({
parser: require.resolve('@typescript-eslint/parser'),
});
ruleTester.run(RULE_NAME, rule, {
valid: [\`const example = true;\`],
invalid: [],
});
`
);
tree.write(
`tools/eslint-rules/rules/multi-import.ts`,
`
import { ESLintUtils } from '@typescript-eslint/experimental-utils';
import { TSESLint } from '@typescript-eslint/experimental-utils';
import { rule, RULE_NAME } from './existing-rule';
// NOTE: remaining code is irrelevant for this test
`
);
});
it('should switch import from @typescript-eslint/experimental-utils to @typescript-eslint/utils in rule and spec file', async () => {
await experimentalToUtilsUpdate(tree);
expect(
tree.read(`tools/eslint-rules/rules/existing-rule.ts`).toString('utf-8')
).toMatchInlineSnapshot(`
"
import { ESLintUtils } from '@typescript-eslint/utils';
import { rule, RULE_NAME } from './existing-rule';
// NOTE: The rule will be available in ESLint configs as \\"@nrwl/nx/workspace/existing-rule\\"
export const RULE_NAME = 'existing-rule';
export const rule = ESLintUtils.RuleCreator(() => __filename)({
name: RULE_NAME,
meta: {
type: 'problem',
docs: {
description: \`\`,
recommended: 'error',
},
schema: [],
messages: {},
},
defaultOptions: [],
create(context) {
return {};
},
});
"
`);
expect(
tree
.read(`tools/eslint-rules/rules/existing-rule.spec.ts`)
.toString('utf-8')
).toMatchInlineSnapshot(`
"
import { TSESLint } from '@typescript-eslint/utils';
import { rule, RULE_NAME } from './existing-rule';
const ruleTester = new TSESLint.RuleTester({
parser: require.resolve('@typescript-eslint/parser'),
});
ruleTester.run(RULE_NAME, rule, {
valid: [\`const example = true;\`],
invalid: [],
});
"
`);
});
it('should switch import from @typescript-eslint/experimental-utils to @typescript-eslint/utils on multiple imports', async () => {
await experimentalToUtilsUpdate(tree);
expect(
tree.read(`tools/eslint-rules/rules/multi-import.ts`).toString('utf-8')
).toMatchInlineSnapshot(`
"
import { ESLintUtils } from '@typescript-eslint/utils';
import { TSESLint } from '@typescript-eslint/utils';
import { rule, RULE_NAME } from './existing-rule';
// NOTE: remaining code is irrelevant for this test
"
`);
});
});

View File

@ -0,0 +1,39 @@
import { formatFiles, Tree, visitNotIgnoredFiles } from '@nrwl/devkit';
import { tsquery } from '@phenomnomnominal/tsquery';
function updateFile(fileAst: any, fileContents: string): string | undefined {
const importStatement: any[] = tsquery(
fileAst,
'ImportDeclaration StringLiteral[value=@typescript-eslint/experimental-utils]'
);
if (importStatement.length === 0) {
return;
}
const contentSlices = fileContents.split(
'@typescript-eslint/experimental-utils'
);
let updatedFileContents = '';
for (let i = 0; i < contentSlices.length / 2; i++) {
updatedFileContents += `${contentSlices[i]}@typescript-eslint/utils`;
}
updatedFileContents += contentSlices[contentSlices.length - 1];
return updatedFileContents;
}
export default async function experimentalToUtilsUpdate(tree: Tree) {
try {
visitNotIgnoredFiles(tree, 'tools/eslint-rules', (path) => {
if (path.endsWith('.ts')) {
const fileContents = tree.read(path).toString('utf-8');
const fileAst = tsquery.ast(fileContents);
const updatedContents = updateFile(fileAst, fileContents);
if (updatedContents) {
tree.write(path, updatedContents);
}
}
});
await formatFiles(tree);
} catch {}
}

View File

@ -1,4 +1,4 @@
import { TSESLint } from '@typescript-eslint/experimental-utils';
import { TSESLint } from '@typescript-eslint/utils';
import { rule, RULE_NAME } from './valid-schema-description';
const ruleTester = new TSESLint.RuleTester({

View File

@ -1,4 +1,4 @@
import { ESLintUtils } from '@typescript-eslint/experimental-utils';
import { ESLintUtils } from '@typescript-eslint/utils';
import type { AST } from 'jsonc-eslint-parser';
// NOTE: The rule will be available in ESLint configs as "@nrwl/nx/workspace/valid-schema-description"

View File

@ -6722,6 +6722,18 @@
eslint-scope "^5.1.1"
eslint-utils "^3.0.0"
"@typescript-eslint/utils@^5.29.0":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.30.6.tgz#1de2da14f678e7d187daa6f2e4cdb558ed0609dc"
integrity sha512-xFBLc/esUbLOJLk9jKv0E9gD/OH966M40aY9jJ8GiqpSkP2xOV908cokJqqhVd85WoIvHVHYXxSFE4cCSDzVvA==
dependencies:
"@types/json-schema" "^7.0.9"
"@typescript-eslint/scope-manager" "5.30.6"
"@typescript-eslint/types" "5.30.6"
"@typescript-eslint/typescript-estree" "5.30.6"
eslint-scope "^5.1.1"
eslint-utils "^3.0.0"
"@typescript-eslint/visitor-keys@5.10.1":
version "5.10.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.10.1.tgz#29102de692f59d7d34ecc457ed59ab5fc558010b"