diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e0e60ee6a3e..93652acb3e8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,24 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.18.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.17.0...v5.18.0) (2022-04-04) + + +### Bug Fixes + +* **eslint-plugin:** method-signature-style respect getter signature ([#4777](https://github.com/typescript-eslint/typescript-eslint/issues/4777)) ([12dd670](https://github.com/typescript-eslint/typescript-eslint/commit/12dd670bc8621867c5105d8892dba9f9550a2f35)) +* **visitor-keys:** add missing visitor keys ([#4731](https://github.com/typescript-eslint/typescript-eslint/issues/4731)) ([bb575a0](https://github.com/typescript-eslint/typescript-eslint/commit/bb575a0763f39b9b988a7c20afee7b5eeb64cba7)) + + +### Features + +* **eslint-plugin:** [no-shadow] ignoreOnInitialization option ([#4603](https://github.com/typescript-eslint/typescript-eslint/issues/4603)) ([068ea9b](https://github.com/typescript-eslint/typescript-eslint/commit/068ea9b8eb3072fb46a6035f29c68ce96a69008d)) +* **eslint-plugin:** [no-this-alias] report on assignment expressions ([#4718](https://github.com/typescript-eslint/typescript-eslint/issues/4718)) ([8329498](https://github.com/typescript-eslint/typescript-eslint/commit/83294989dad543351a26e95be8d11a91d348679a)) + + + + + # [5.17.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.16.0...v5.17.0) (2022-03-28) diff --git a/docs/README.md b/docs/README.md index aa14517ebd62..dfac81e925a2 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,7 +4,7 @@ sidebar_label: Getting Started slug: / --- -These docs will give you a quick overview of the project and all of its the pieces, as well as provide guides to help you get set up. +These docs will give you a quick overview of the project and all of its pieces, as well as provide guides to help you get set up. The docs are broken down into the following categories: diff --git a/docs/development/CUSTOM_RULES.md b/docs/development/CUSTOM_RULES.md index a101dadbd297..345e42c289ec 100644 --- a/docs/development/CUSTOM_RULES.md +++ b/docs/development/CUSTOM_RULES.md @@ -46,20 +46,23 @@ export const rule = createRule({ create(context) { return { FunctionDeclaration(node) { - if (/^[a-z]/.test(node.id.name)) { - context.report({ - messageId: 'uppercase', - node: node.id, - }); + if (node.id != null) { + if (/^[a-z]/.test(node.id.name)) { + context.report({ + messageId: 'uppercase', + node: node.id, + }); + } } }, }; }, + name: 'uppercase-first-declarations', meta: { docs: { - category: 'Best Practices', description: 'Function declaration names should start with an upper-case letter.', + recommended: 'warn', }, messages: { uppercase: 'Start this name with an upper-case letter.', @@ -67,6 +70,7 @@ export const rule = createRule({ type: 'suggestion', schema: [], }, + defaultOptions: [], }); ``` diff --git a/lerna.json b/lerna.json index fde7ffaa6778..89f5ea3e2164 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "5.17.0", + "version": "5.18.0", "npmClient": "yarn", "useWorkspaces": true, "stream": true diff --git a/packages/ast-spec/CHANGELOG.md b/packages/ast-spec/CHANGELOG.md index 96b7ebf5217b..3efccf0ffa5f 100644 --- a/packages/ast-spec/CHANGELOG.md +++ b/packages/ast-spec/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.18.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.17.0...v5.18.0) (2022-04-04) + +**Note:** Version bump only for package @typescript-eslint/ast-spec + + + + + # [5.17.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.16.0...v5.17.0) (2022-03-28) **Note:** Version bump only for package @typescript-eslint/ast-spec diff --git a/packages/ast-spec/package.json b/packages/ast-spec/package.json index 6dd8d4503f6d..e2bd51c4c2d6 100644 --- a/packages/ast-spec/package.json +++ b/packages/ast-spec/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/ast-spec", - "version": "5.17.0", + "version": "5.18.0", "description": "TypeScript-ESTree AST spec", "private": true, "keywords": [ diff --git a/packages/eslint-plugin-internal/CHANGELOG.md b/packages/eslint-plugin-internal/CHANGELOG.md index 2e9ca4f037bc..e88c909009d1 100644 --- a/packages/eslint-plugin-internal/CHANGELOG.md +++ b/packages/eslint-plugin-internal/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.18.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.17.0...v5.18.0) (2022-04-04) + +**Note:** Version bump only for package @typescript-eslint/eslint-plugin-internal + + + + + # [5.17.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.16.0...v5.17.0) (2022-03-28) **Note:** Version bump only for package @typescript-eslint/eslint-plugin-internal diff --git a/packages/eslint-plugin-internal/package.json b/packages/eslint-plugin-internal/package.json index 6f9a82cde1a7..156c9ba148de 100644 --- a/packages/eslint-plugin-internal/package.json +++ b/packages/eslint-plugin-internal/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/eslint-plugin-internal", - "version": "5.17.0", + "version": "5.18.0", "private": true, "main": "dist/index.js", "scripts": { @@ -14,8 +14,8 @@ }, "dependencies": { "@types/prettier": "*", - "@typescript-eslint/scope-manager": "5.17.0", - "@typescript-eslint/utils": "5.17.0", + "@typescript-eslint/scope-manager": "5.18.0", + "@typescript-eslint/utils": "5.18.0", "prettier": "*" } } diff --git a/packages/eslint-plugin-tslint/CHANGELOG.md b/packages/eslint-plugin-tslint/CHANGELOG.md index b603de44ba5a..e356a4514ace 100644 --- a/packages/eslint-plugin-tslint/CHANGELOG.md +++ b/packages/eslint-plugin-tslint/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.18.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.17.0...v5.18.0) (2022-04-04) + +**Note:** Version bump only for package @typescript-eslint/eslint-plugin-tslint + + + + + # [5.17.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.16.0...v5.17.0) (2022-03-28) **Note:** Version bump only for package @typescript-eslint/eslint-plugin-tslint diff --git a/packages/eslint-plugin-tslint/package.json b/packages/eslint-plugin-tslint/package.json index 0231788b4f6b..aaaa072aa8c0 100644 --- a/packages/eslint-plugin-tslint/package.json +++ b/packages/eslint-plugin-tslint/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/eslint-plugin-tslint", - "version": "5.17.0", + "version": "5.18.0", "main": "dist/index.js", "typings": "src/index.ts", "description": "TSLint wrapper plugin for ESLint", @@ -38,7 +38,7 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/utils": "5.17.0", + "@typescript-eslint/utils": "5.18.0", "lodash": "^4.17.21" }, "peerDependencies": { @@ -48,6 +48,6 @@ }, "devDependencies": { "@types/lodash": "*", - "@typescript-eslint/parser": "5.17.0" + "@typescript-eslint/parser": "5.18.0" } } diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index d2dbffd033ef..d54b733b40f1 100644 --- a/packages/eslint-plugin/CHANGELOG.md +++ b/packages/eslint-plugin/CHANGELOG.md @@ -3,6 +3,23 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.18.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.17.0...v5.18.0) (2022-04-04) + + +### Bug Fixes + +* **eslint-plugin:** method-signature-style respect getter signature ([#4777](https://github.com/typescript-eslint/typescript-eslint/issues/4777)) ([12dd670](https://github.com/typescript-eslint/typescript-eslint/commit/12dd670bc8621867c5105d8892dba9f9550a2f35)) + + +### Features + +* **eslint-plugin:** [no-shadow] ignoreOnInitialization option ([#4603](https://github.com/typescript-eslint/typescript-eslint/issues/4603)) ([068ea9b](https://github.com/typescript-eslint/typescript-eslint/commit/068ea9b8eb3072fb46a6035f29c68ce96a69008d)) +* **eslint-plugin:** [no-this-alias] report on assignment expressions ([#4718](https://github.com/typescript-eslint/typescript-eslint/issues/4718)) ([8329498](https://github.com/typescript-eslint/typescript-eslint/commit/83294989dad543351a26e95be8d11a91d348679a)) + + + + + # [5.17.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.16.0...v5.17.0) (2022-03-28) diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index d09ac65a7e7b..ac1a8e5a2ad6 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/eslint-plugin", - "version": "5.17.0", + "version": "5.18.0", "description": "TypeScript plugin for ESLint", "keywords": [ "eslint", @@ -44,9 +44,9 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/scope-manager": "5.17.0", - "@typescript-eslint/type-utils": "5.17.0", - "@typescript-eslint/utils": "5.17.0", + "@typescript-eslint/scope-manager": "5.18.0", + "@typescript-eslint/type-utils": "5.18.0", + "@typescript-eslint/utils": "5.18.0", "debug": "^4.3.2", "functional-red-black-tree": "^1.0.1", "ignore": "^5.1.8", diff --git a/packages/eslint-plugin/src/rules/method-signature-style.ts b/packages/eslint-plugin/src/rules/method-signature-style.ts index d9dfbdac4bd6..39ed66cd0729 100644 --- a/packages/eslint-plugin/src/rules/method-signature-style.ts +++ b/packages/eslint-plugin/src/rules/method-signature-style.ts @@ -115,6 +115,10 @@ export default util.createRule({ return { ...(mode === 'property' && { TSMethodSignature(methodNode): void { + if (methodNode.kind !== 'method') { + return; + } + const parent = methodNode.parent; const members = parent?.type === AST_NODE_TYPES.TSInterfaceBody diff --git a/packages/eslint-plugin/src/rules/no-shadow.ts b/packages/eslint-plugin/src/rules/no-shadow.ts index 3f13f587de16..a80a1b506732 100644 --- a/packages/eslint-plugin/src/rules/no-shadow.ts +++ b/packages/eslint-plugin/src/rules/no-shadow.ts @@ -18,6 +18,7 @@ type Options = [ allow?: string[]; builtinGlobals?: boolean; hoist?: 'all' | 'functions' | 'never'; + ignoreOnInitialization?: boolean; ignoreTypeValueShadow?: boolean; ignoreFunctionTypeParameterNameValueShadow?: boolean; }, @@ -49,6 +50,9 @@ export default util.createRule({ type: 'string', }, }, + ignoreOnInitialization: { + type: 'boolean', + }, ignoreTypeValueShadow: { type: 'boolean', }, @@ -68,6 +72,7 @@ export default util.createRule({ allow: [], builtinGlobals: false, hoist: 'functions', + ignoreOnInitialization: false, ignoreTypeValueShadow: true, ignoreFunctionTypeParameterNameValueShadow: true, }, @@ -314,6 +319,135 @@ export default util.createRule({ ); } + /** + * Checks whether or not a given location is inside of the range of a given node. + * @param node An node to check. + * @param location A location to check. + * @returns `true` if the location is inside of the range of the node. + */ + function isInRange( + node: TSESTree.Node | null, + location: number, + ): boolean | null { + return node && node.range[0] <= location && location <= node.range[1]; + } + + /** + * Searches from the current node through its ancestry to find a matching node. + * @param node a node to get. + * @param match a callback that checks whether or not the node verifies its condition or not. + * @returns the matching node. + */ + function findSelfOrAncestor( + node: TSESTree.Node | undefined, + match: (node: TSESTree.Node) => boolean, + ): TSESTree.Node | undefined { + let currentNode = node; + + while (currentNode && !match(currentNode)) { + currentNode = currentNode.parent; + } + return currentNode; + } + + /** + * Finds function's outer scope. + * @param scope Function's own scope. + * @returns Function's outer scope. + */ + function getOuterScope( + scope: TSESLint.Scope.Scope, + ): TSESLint.Scope.Scope | null { + const upper = scope.upper; + + if (upper?.type === 'function-expression-name') { + return upper.upper; + } + return upper; + } + + /** + * Checks if a variable and a shadowedVariable have the same init pattern ancestor. + * @param variable a variable to check. + * @param shadowedVariable a shadowedVariable to check. + * @returns Whether or not the variable and the shadowedVariable have the same init pattern ancestor. + */ + function isInitPatternNode( + variable: TSESLint.Scope.Variable, + shadowedVariable: TSESLint.Scope.Variable, + ): boolean { + const outerDef = shadowedVariable.defs[0]; + + if (!outerDef) { + return false; + } + + const { variableScope } = variable.scope; + + if ( + !( + (variableScope.block.type === + AST_NODE_TYPES.ArrowFunctionExpression || + variableScope.block.type === AST_NODE_TYPES.FunctionExpression) && + getOuterScope(variableScope) === shadowedVariable.scope + ) + ) { + return false; + } + + const fun = variableScope.block; + const { parent } = fun; + + const callExpression = findSelfOrAncestor( + parent, + node => node.type === AST_NODE_TYPES.CallExpression, + ); + + if (!callExpression) { + return false; + } + + let node: TSESTree.Node | undefined = outerDef.name; + const location = callExpression.range[1]; + + while (node) { + if (node.type === AST_NODE_TYPES.VariableDeclarator) { + if (isInRange(node.init, location)) { + return true; + } + if ( + (node.parent?.parent?.type === AST_NODE_TYPES.ForInStatement || + node.parent?.parent?.type === AST_NODE_TYPES.ForOfStatement) && + isInRange(node.parent.parent.right, location) + ) { + return true; + } + break; + } else if (node.type === AST_NODE_TYPES.AssignmentPattern) { + if (isInRange(node.right, location)) { + return true; + } + } else if ( + [ + AST_NODE_TYPES.FunctionDeclaration, + AST_NODE_TYPES.ClassDeclaration, + AST_NODE_TYPES.FunctionExpression, + AST_NODE_TYPES.ClassExpression, + AST_NODE_TYPES.ArrowFunctionExpression, + AST_NODE_TYPES.CatchClause, + AST_NODE_TYPES.ImportDeclaration, + AST_NODE_TYPES.ExportNamedDeclaration, + ].includes(node.type) + ) { + break; + } + + node = node.parent; + } + + return false; + } + /** * Checks if a variable is inside the initializer of scopeVar. * @@ -455,6 +589,10 @@ export default util.createRule({ (shadowed.identifiers.length > 0 || (options.builtinGlobals && isESLintGlobal)) && !isOnInitializer(variable, shadowed) && + !( + options.ignoreOnInitialization && + isInitPatternNode(variable, shadowed) + ) && !(options.hoist !== 'all' && isInTdz(variable, shadowed)) ) { context.report({ diff --git a/packages/eslint-plugin/src/rules/no-this-alias.ts b/packages/eslint-plugin/src/rules/no-this-alias.ts index 5c9c9f568811..5750b8209b11 100644 --- a/packages/eslint-plugin/src/rules/no-this-alias.ts +++ b/packages/eslint-plugin/src/rules/no-this-alias.ts @@ -48,11 +48,11 @@ export default util.createRule({ ], create(context, [{ allowDestructuring, allowedNames }]) { return { - "VariableDeclarator[init.type='ThisExpression']"( - node: TSESTree.VariableDeclarator, + "VariableDeclarator[init.type='ThisExpression'], AssignmentExpression[right.type='ThisExpression']"( + node: TSESTree.VariableDeclarator | TSESTree.AssignmentExpression, ): void { - const { id } = node; - + const id = + node.type === AST_NODE_TYPES.VariableDeclarator ? node.id : node.left; if (allowDestructuring && id.type !== AST_NODE_TYPES.Identifier) { return; } diff --git a/packages/eslint-plugin/tests/rules/method-signature-style.test.ts b/packages/eslint-plugin/tests/rules/method-signature-style.test.ts index e82ee2e750bd..065d15c61801 100644 --- a/packages/eslint-plugin/tests/rules/method-signature-style.test.ts +++ b/packages/eslint-plugin/tests/rules/method-signature-style.test.ts @@ -30,12 +30,24 @@ interface Test { ` interface Test { 'f!': (/* b */ x: any /* c */) => void; +} + `, + ` +interface Test { + get f(): number; +} + `, + ` +interface Test { + set f(value: number): void; } `, 'type Test = { readonly f: (a: string) => number };', "type Test = { ['f']?: (a: boolean) => void };", 'type Test = { readonly f?: (a?: T) => T };', "type Test = { readonly ['f']?: (a: T, b: T) => T };", + 'type Test = { get f(): number };', + 'type Test = { set f(value: number): void };', ...batchedSingleLineTests({ options: ['method'], code: noFormat` @@ -44,10 +56,14 @@ interface Test { interface Test { f(a: T): T } interface Test { ['f'](a: T, b: T): T } interface Test { 'f!'(/* b */ x: any /* c */): void } + interface Test { get f(): number } + interface Test { set f(value: number): void } type Test = { readonly f(a: string): number } type Test = { ['f']?(a: boolean): void } type Test = { readonly f?(a?: T): T } type Test = { readonly ['f']?(a: T, b: T): T } + type Test = { get f(): number } + type Test = { set f(value: number): void } `, }), ], diff --git a/packages/eslint-plugin/tests/rules/no-shadow.test.ts b/packages/eslint-plugin/tests/rules/no-shadow.test.ts index 635dff307e1f..69a69f2f70eb 100644 --- a/packages/eslint-plugin/tests/rules/no-shadow.test.ts +++ b/packages/eslint-plugin/tests/rules/no-shadow.test.ts @@ -202,6 +202,156 @@ function doThing(foo: number) {} `, options: [{ ignoreTypeValueShadow: true }], }, + { + code: 'const a = [].find(a => a);', + options: [{ ignoreOnInitialization: true }], + }, + { + code: ` +const a = [].find(function (a) { + return a; +}); + `, + options: [{ ignoreOnInitialization: true }], + }, + { + code: 'const [a = [].find(a => true)] = dummy;', + options: [{ ignoreOnInitialization: true }], + }, + { + code: 'const { a = [].find(a => true) } = dummy;', + options: [{ ignoreOnInitialization: true }], + }, + { + code: 'function func(a = [].find(a => true)) {}', + options: [{ ignoreOnInitialization: true }], + }, + { + code: ` +for (const a in [].find(a => true)) { +} + `, + options: [{ ignoreOnInitialization: true }], + }, + { + code: ` +for (const a of [].find(a => true)) { +} + `, + options: [{ ignoreOnInitialization: true }], + }, + { + code: "const a = [].map(a => true).filter(a => a === 'b');", + options: [{ ignoreOnInitialization: true }], + }, + { + code: ` +const a = [] + .map(a => true) + .filter(a => a === 'b') + .find(a => a === 'c'); + `, + options: [{ ignoreOnInitialization: true }], + }, + { + code: 'const { a } = (({ a }) => ({ a }))();', + options: [{ ignoreOnInitialization: true }], + }, + { + code: ` +const person = people.find(item => { + const person = item.name; + return person === 'foo'; +}); + `, + options: [{ ignoreOnInitialization: true }], + }, + { + code: 'var y = bar || foo(y => y);', + options: [{ ignoreOnInitialization: true }], + }, + { + code: 'var y = bar && foo(y => y);', + options: [{ ignoreOnInitialization: true }], + }, + { + code: 'var z = bar(foo(z => z));', + options: [{ ignoreOnInitialization: true }], + }, + { + code: 'var z = boo(bar(foo(z => z)));', + options: [{ ignoreOnInitialization: true }], + }, + { + code: ` +var match = function (person) { + return person.name === 'foo'; +}; +const person = [].find(match); + `, + options: [{ ignoreOnInitialization: true }], + }, + { + code: 'const a = foo(x || (a => {}));', + options: [{ ignoreOnInitialization: true }], + }, + { + code: 'const { a = 1 } = foo(a => {});', + options: [{ ignoreOnInitialization: true }], + }, + { + code: "const person = { ...people.find(person => person.firstName.startsWith('s')) };", + options: [{ ignoreOnInitialization: true }], + parserOptions: { ecmaVersion: 2021 }, + }, + { + code: ` +const person = { + firstName: people + .filter(person => person.firstName.startsWith('s')) + .map(person => person.firstName)[0], +}; + `, + options: [{ ignoreOnInitialization: true }], + parserOptions: { ecmaVersion: 2021 }, + }, + { + code: ` +() => { + const y = foo(y => y); +}; + `, + options: [{ ignoreOnInitialization: true }], + }, + { + code: 'const x = (x => x)();', + options: [{ ignoreOnInitialization: true }], + }, + { + code: 'var y = bar || (y => y)();', + options: [{ ignoreOnInitialization: true }], + }, + { + code: 'var y = bar && (y => y)();', + options: [{ ignoreOnInitialization: true }], + }, + { + code: 'var x = (x => x)((y => y)());', + options: [{ ignoreOnInitialization: true }], + }, + { + code: 'const { a = 1 } = (a => {})();', + options: [{ ignoreOnInitialization: true }], + }, + { + code: ` +() => { + const y = (y => y)(); +}; + `, + options: [{ ignoreOnInitialization: true }], + }, + { code: 'const [x = y => y] = [].map(y => y);' }, ], invalid: [ { @@ -1612,5 +1762,265 @@ declare module 'bar' { }, ], }, + { + code: ` +let x = foo((x, y) => {}); +let y; + `, + parserOptions: { ecmaVersion: 6 }, + options: [{ hoist: 'all' }], + errors: [ + { + messageId: 'noShadow', + data: { name: 'x' }, + type: AST_NODE_TYPES.Identifier, + }, + { + messageId: 'noShadow', + data: { + name: 'y', + shadowedLine: 2, + shadowedColumn: 5, + }, + type: AST_NODE_TYPES.Identifier, + }, + ], + }, + { + code: ` +const a = fn(() => { + class C { + fn() { + const a = 42; + return a; + } + } + return new C(); +}); + `, + parserOptions: { ecmaVersion: 6 }, + options: [{ ignoreOnInitialization: true }], + errors: [ + { + messageId: 'noShadow', + data: { name: 'a' }, + type: AST_NODE_TYPES.Identifier, + line: 5, + column: 13, + }, + ], + }, + { + code: 'function a() {}\nfoo(a => {});', + parserOptions: { ecmaVersion: 6 }, + options: [{ ignoreOnInitialization: true }], + errors: [ + { + messageId: 'noShadow', + data: { name: 'a' }, + type: AST_NODE_TYPES.Identifier, + line: 2, + column: 5, + }, + ], + }, + { + code: ` +const a = fn(() => { + function C() { + this.fn = function () { + const a = 42; + return a; + }; + } + return new C(); +}); + `, + parserOptions: { ecmaVersion: 6 }, + options: [{ ignoreOnInitialization: true }], + errors: [ + { + messageId: 'noShadow', + data: { name: 'a' }, + type: AST_NODE_TYPES.Identifier, + line: 5, + column: 13, + }, + ], + }, + { + code: ` +const x = foo(() => { + const bar = () => { + return x => {}; + }; + return bar; +}); + `, + parserOptions: { ecmaVersion: 6 }, + options: [{ ignoreOnInitialization: true }], + errors: [ + { + messageId: 'noShadow', + data: { name: 'x' }, + type: AST_NODE_TYPES.Identifier, + line: 4, + column: 12, + }, + ], + }, + { + code: ` +const x = foo(() => { + return { bar(x) {} }; +}); + `, + parserOptions: { ecmaVersion: 6 }, + options: [{ ignoreOnInitialization: true }], + errors: [ + { + messageId: 'noShadow', + data: { name: 'x' }, + type: AST_NODE_TYPES.Identifier, + line: 3, + column: 16, + }, + ], + }, + { + code: ` +const x = () => { + foo(x => x); +}; + `, + parserOptions: { ecmaVersion: 6 }, + options: [{ ignoreOnInitialization: true }], + errors: [ + { + messageId: 'noShadow', + data: { name: 'x' }, + type: AST_NODE_TYPES.Identifier, + line: 3, + column: 7, + }, + ], + }, + { + code: ` +const foo = () => { + let x; + bar(x => x); +}; + `, + parserOptions: { ecmaVersion: 6 }, + options: [{ ignoreOnInitialization: true }], + errors: [ + { + messageId: 'noShadow', + data: { name: 'x' }, + type: AST_NODE_TYPES.Identifier, + line: 4, + column: 7, + }, + ], + }, + { + code: ` +foo(() => { + const x = x => x; +}); + `, + parserOptions: { ecmaVersion: 6 }, + options: [{ ignoreOnInitialization: true }], + errors: [ + { + messageId: 'noShadow', + data: { name: 'x' }, + type: AST_NODE_TYPES.Identifier, + line: 3, + column: 13, + }, + ], + }, + { + code: ` +const foo = x => { + bar(x => {}); +}; + `, + parserOptions: { ecmaVersion: 6 }, + options: [{ ignoreOnInitialization: true }], + errors: [ + { + messageId: 'noShadow', + data: { name: 'x' }, + type: AST_NODE_TYPES.Identifier, + line: 3, + column: 7, + }, + ], + }, + { + code: ` +let x = ((x, y) => {})(); +let y; + `, + parserOptions: { ecmaVersion: 6 }, + options: [{ hoist: 'all' }], + errors: [ + { + messageId: 'noShadow', + data: { name: 'x' }, + type: AST_NODE_TYPES.Identifier, + }, + { + messageId: 'noShadow', + data: { name: 'y' }, + type: AST_NODE_TYPES.Identifier, + }, + ], + }, + { + code: ` +const a = (() => { + class C { + fn() { + const a = 42; + return a; + } + } + return new C(); +})(); + `, + parserOptions: { ecmaVersion: 6 }, + options: [{ ignoreOnInitialization: true }], + errors: [ + { + messageId: 'noShadow', + data: { name: 'a' }, + type: AST_NODE_TYPES.Identifier, + line: 5, + column: 13, + }, + ], + }, + { + code: ` +const x = () => { + (x => x)(); +}; + `, + parserOptions: { ecmaVersion: 6 }, + options: [{ ignoreOnInitialization: true }], + errors: [ + { + messageId: 'noShadow', + data: { name: 'x' }, + type: AST_NODE_TYPES.Identifier, + line: 3, + column: 4, + }, + ], + }, ], }); diff --git a/packages/eslint-plugin/tests/rules/no-this-alias.test.ts b/packages/eslint-plugin/tests/rules/no-this-alias.test.ts index 0a8f7340bca8..0d2832ec2ef1 100644 --- a/packages/eslint-plugin/tests/rules/no-this-alias.test.ts +++ b/packages/eslint-plugin/tests/rules/no-this-alias.test.ts @@ -66,6 +66,13 @@ declare module 'foo' { code: 'const self = this;', errors: [idError], }, + { + code: ` +let that; +that = this; + `, + errors: [idError], + }, { code: 'const { props, state } = this;', options: [ diff --git a/packages/eslint-plugin/typings/eslint-rules.d.ts b/packages/eslint-plugin/typings/eslint-rules.d.ts index 7e3b9db43e36..4c7b71a67ae9 100644 --- a/packages/eslint-plugin/typings/eslint-rules.d.ts +++ b/packages/eslint-plugin/typings/eslint-rules.d.ts @@ -374,6 +374,7 @@ declare module 'eslint/lib/rules/no-shadow' { builtinGlobals?: boolean; hoist?: 'all' | 'functions' | 'never'; allow?: string[]; + ignoreOnInitialization?: boolean; }, ], { diff --git a/packages/experimental-utils/CHANGELOG.md b/packages/experimental-utils/CHANGELOG.md index 3ec1fb5f0deb..71d730f80fc0 100644 --- a/packages/experimental-utils/CHANGELOG.md +++ b/packages/experimental-utils/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.18.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.17.0...v5.18.0) (2022-04-04) + +**Note:** Version bump only for package @typescript-eslint/experimental-utils + + + + + # [5.17.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.16.0...v5.17.0) (2022-03-28) **Note:** Version bump only for package @typescript-eslint/experimental-utils diff --git a/packages/experimental-utils/package.json b/packages/experimental-utils/package.json index 6461573e61a9..252ce0aa61f8 100644 --- a/packages/experimental-utils/package.json +++ b/packages/experimental-utils/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/experimental-utils", - "version": "5.17.0", + "version": "5.18.0", "description": "(Experimental) Utilities for working with TypeScript + ESLint together", "keywords": [ "eslint", @@ -38,7 +38,7 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/utils": "5.17.0" + "@typescript-eslint/utils": "5.18.0" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" diff --git a/packages/parser/CHANGELOG.md b/packages/parser/CHANGELOG.md index 54af23a02a56..8eb61aaeea5f 100644 --- a/packages/parser/CHANGELOG.md +++ b/packages/parser/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.18.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.17.0...v5.18.0) (2022-04-04) + +**Note:** Version bump only for package @typescript-eslint/parser + + + + + # [5.17.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.16.0...v5.17.0) (2022-03-28) **Note:** Version bump only for package @typescript-eslint/parser diff --git a/packages/parser/package.json b/packages/parser/package.json index 966628d108e9..b7eeeac1478d 100644 --- a/packages/parser/package.json +++ b/packages/parser/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/parser", - "version": "5.17.0", + "version": "5.18.0", "description": "An ESLint custom parser which leverages TypeScript ESTree", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -44,9 +44,9 @@ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "dependencies": { - "@typescript-eslint/scope-manager": "5.17.0", - "@typescript-eslint/types": "5.17.0", - "@typescript-eslint/typescript-estree": "5.17.0", + "@typescript-eslint/scope-manager": "5.18.0", + "@typescript-eslint/types": "5.18.0", + "@typescript-eslint/typescript-estree": "5.18.0", "debug": "^4.3.2" }, "devDependencies": { diff --git a/packages/scope-manager/CHANGELOG.md b/packages/scope-manager/CHANGELOG.md index 44a49da0e4f5..303997c57562 100644 --- a/packages/scope-manager/CHANGELOG.md +++ b/packages/scope-manager/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.18.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.17.0...v5.18.0) (2022-04-04) + +**Note:** Version bump only for package @typescript-eslint/scope-manager + + + + + # [5.17.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.16.0...v5.17.0) (2022-03-28) **Note:** Version bump only for package @typescript-eslint/scope-manager diff --git a/packages/scope-manager/package.json b/packages/scope-manager/package.json index 7133c16639be..d06efe9e579a 100644 --- a/packages/scope-manager/package.json +++ b/packages/scope-manager/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/scope-manager", - "version": "5.17.0", + "version": "5.18.0", "description": "TypeScript scope analyser for ESLint", "keywords": [ "eslint", @@ -39,12 +39,12 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/types": "5.17.0", - "@typescript-eslint/visitor-keys": "5.17.0" + "@typescript-eslint/types": "5.18.0", + "@typescript-eslint/visitor-keys": "5.18.0" }, "devDependencies": { "@types/glob": "*", - "@typescript-eslint/typescript-estree": "5.17.0", + "@typescript-eslint/typescript-estree": "5.18.0", "glob": "*", "jest-specific-snapshot": "*", "make-dir": "*", diff --git a/packages/shared-fixtures/CHANGELOG.md b/packages/shared-fixtures/CHANGELOG.md index 039a09d58bb1..c38dbd00a11f 100644 --- a/packages/shared-fixtures/CHANGELOG.md +++ b/packages/shared-fixtures/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.18.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.17.0...v5.18.0) (2022-04-04) + +**Note:** Version bump only for package @typescript-eslint/shared-fixtures + + + + + # [5.17.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.16.0...v5.17.0) (2022-03-28) **Note:** Version bump only for package @typescript-eslint/shared-fixtures diff --git a/packages/shared-fixtures/package.json b/packages/shared-fixtures/package.json index 0ac5e65ed2b2..71cf26927113 100644 --- a/packages/shared-fixtures/package.json +++ b/packages/shared-fixtures/package.json @@ -1,5 +1,5 @@ { "name": "@typescript-eslint/shared-fixtures", - "version": "5.17.0", + "version": "5.18.0", "private": true } diff --git a/packages/type-utils/CHANGELOG.md b/packages/type-utils/CHANGELOG.md index dc7c1a037742..78a895f4620f 100644 --- a/packages/type-utils/CHANGELOG.md +++ b/packages/type-utils/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.18.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.17.0...v5.18.0) (2022-04-04) + +**Note:** Version bump only for package @typescript-eslint/type-utils + + + + + # [5.17.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.16.0...v5.17.0) (2022-03-28) **Note:** Version bump only for package @typescript-eslint/type-utils diff --git a/packages/type-utils/package.json b/packages/type-utils/package.json index 1fe0b75177ab..f790577c9a31 100644 --- a/packages/type-utils/package.json +++ b/packages/type-utils/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/type-utils", - "version": "5.17.0", + "version": "5.18.0", "description": "Type utilities for working with TypeScript + ESLint together", "keywords": [ "eslint", @@ -39,12 +39,12 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/utils": "5.17.0", + "@typescript-eslint/utils": "5.18.0", "debug": "^4.3.2", "tsutils": "^3.21.0" }, "devDependencies": { - "@typescript-eslint/parser": "5.17.0", + "@typescript-eslint/parser": "5.18.0", "typescript": "*" }, "peerDependencies": { diff --git a/packages/types/CHANGELOG.md b/packages/types/CHANGELOG.md index 05bab9244e96..254fecadcb36 100644 --- a/packages/types/CHANGELOG.md +++ b/packages/types/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.18.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.17.0...v5.18.0) (2022-04-04) + +**Note:** Version bump only for package @typescript-eslint/types + + + + + # [5.17.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.16.0...v5.17.0) (2022-03-28) **Note:** Version bump only for package @typescript-eslint/types diff --git a/packages/types/package.json b/packages/types/package.json index 5779b1d502a1..e0c5c4ed6d51 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/types", - "version": "5.17.0", + "version": "5.18.0", "description": "Types for the TypeScript-ESTree AST spec", "keywords": [ "eslint", diff --git a/packages/typescript-estree/CHANGELOG.md b/packages/typescript-estree/CHANGELOG.md index e03a57d7bc81..b17e479f930a 100644 --- a/packages/typescript-estree/CHANGELOG.md +++ b/packages/typescript-estree/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.18.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.17.0...v5.18.0) (2022-04-04) + +**Note:** Version bump only for package @typescript-eslint/typescript-estree + + + + + # [5.17.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.16.0...v5.17.0) (2022-03-28) **Note:** Version bump only for package @typescript-eslint/typescript-estree diff --git a/packages/typescript-estree/package.json b/packages/typescript-estree/package.json index 93474d4d8dc8..4d0e47c465d7 100644 --- a/packages/typescript-estree/package.json +++ b/packages/typescript-estree/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/typescript-estree", - "version": "5.17.0", + "version": "5.18.0", "description": "A parser that converts TypeScript source code into an ESTree compatible form", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -41,8 +41,8 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/types": "5.17.0", - "@typescript-eslint/visitor-keys": "5.17.0", + "@typescript-eslint/types": "5.18.0", + "@typescript-eslint/visitor-keys": "5.18.0", "debug": "^4.3.2", "globby": "^11.0.4", "is-glob": "^4.0.3", @@ -58,7 +58,7 @@ "@types/is-glob": "*", "@types/semver": "*", "@types/tmp": "*", - "@typescript-eslint/shared-fixtures": "5.17.0", + "@typescript-eslint/shared-fixtures": "5.18.0", "glob": "*", "jest-specific-snapshot": "*", "make-dir": "*", diff --git a/packages/utils/CHANGELOG.md b/packages/utils/CHANGELOG.md index bdb3c35770da..7051abc014a8 100644 --- a/packages/utils/CHANGELOG.md +++ b/packages/utils/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.18.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.17.0...v5.18.0) (2022-04-04) + +**Note:** Version bump only for package @typescript-eslint/utils + + + + + # [5.17.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.16.0...v5.17.0) (2022-03-28) **Note:** Version bump only for package @typescript-eslint/utils diff --git a/packages/utils/package.json b/packages/utils/package.json index 72894210f46f..4d301b5e40b3 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/utils", - "version": "5.17.0", + "version": "5.18.0", "description": "Utilities for working with TypeScript + ESLint together", "keywords": [ "eslint", @@ -40,9 +40,9 @@ }, "dependencies": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.17.0", - "@typescript-eslint/types": "5.17.0", - "@typescript-eslint/typescript-estree": "5.17.0", + "@typescript-eslint/scope-manager": "5.18.0", + "@typescript-eslint/types": "5.18.0", + "@typescript-eslint/typescript-estree": "5.18.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" }, diff --git a/packages/visitor-keys/CHANGELOG.md b/packages/visitor-keys/CHANGELOG.md index 01701e3e95d1..5bd5a308f7b4 100644 --- a/packages/visitor-keys/CHANGELOG.md +++ b/packages/visitor-keys/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.18.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.17.0...v5.18.0) (2022-04-04) + + +### Bug Fixes + +* **visitor-keys:** add missing visitor keys ([#4731](https://github.com/typescript-eslint/typescript-eslint/issues/4731)) ([bb575a0](https://github.com/typescript-eslint/typescript-eslint/commit/bb575a0763f39b9b988a7c20afee7b5eeb64cba7)) + + + + + # [5.17.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.16.0...v5.17.0) (2022-03-28) **Note:** Version bump only for package @typescript-eslint/visitor-keys diff --git a/packages/visitor-keys/package.json b/packages/visitor-keys/package.json index efdf324e80a0..b7c9846355c2 100644 --- a/packages/visitor-keys/package.json +++ b/packages/visitor-keys/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/visitor-keys", - "version": "5.17.0", + "version": "5.18.0", "description": "Visitor keys used to help traverse the TypeScript-ESTree AST", "keywords": [ "eslint", @@ -38,7 +38,7 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/types": "5.17.0", + "@typescript-eslint/types": "5.18.0", "eslint-visitor-keys": "^3.0.0" }, "devDependencies": { diff --git a/packages/visitor-keys/src/visitor-keys.ts b/packages/visitor-keys/src/visitor-keys.ts index 85e424308197..3e49d2d1b484 100644 --- a/packages/visitor-keys/src/visitor-keys.ts +++ b/packages/visitor-keys/src/visitor-keys.ts @@ -49,7 +49,7 @@ const additionalKeys: AdditionalKeys = { Identifier: ['decorators', 'typeAnnotation'], ImportDeclaration: ['specifiers', 'source', 'assertions'], ImportExpression: ['source', 'attributes'], - MethodDefinition: ['decorators', 'key', 'value'], + MethodDefinition: ['decorators', 'key', 'value', 'typeParameters'], NewExpression: ['callee', 'typeParameters', 'arguments'], ObjectPattern: ['decorators', 'properties', 'typeAnnotation'], PropertyDefinition: ['decorators', 'key', 'typeAnnotation', 'value'], @@ -110,7 +110,7 @@ const additionalKeys: AdditionalKeys = { TSMethodSignature: ['typeParameters', 'key', 'params', 'returnType'], TSModuleBlock: ['body'], TSModuleDeclaration: ['id', 'body'], - TSNamedTupleMember: ['elementType'], + TSNamedTupleMember: ['label', 'elementType'], TSNamespaceExportDeclaration: ['id'], TSNeverKeyword: [], TSNonNullExpression: ['expression'], diff --git a/packages/website-eslint/CHANGELOG.md b/packages/website-eslint/CHANGELOG.md index 2c1a65156eae..c3bd98cf7ea5 100644 --- a/packages/website-eslint/CHANGELOG.md +++ b/packages/website-eslint/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.18.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.17.0...v5.18.0) (2022-04-04) + +**Note:** Version bump only for package @typescript-eslint/website-eslint + + + + + # [5.17.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.16.0...v5.17.0) (2022-03-28) **Note:** Version bump only for package @typescript-eslint/website-eslint diff --git a/packages/website-eslint/package.json b/packages/website-eslint/package.json index 9fb83656e647..2883fd831f9d 100644 --- a/packages/website-eslint/package.json +++ b/packages/website-eslint/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/website-eslint", - "version": "5.17.0", + "version": "5.18.0", "private": true, "description": "ESLint which works in browsers.", "engines": { @@ -16,19 +16,19 @@ "format": "prettier --write \"./**/*.{ts,js,json,md}\" --ignore-path ../../.prettierignore" }, "dependencies": { - "@typescript-eslint/types": "5.17.0", - "@typescript-eslint/utils": "5.17.0" + "@typescript-eslint/types": "5.18.0", + "@typescript-eslint/utils": "5.18.0" }, "devDependencies": { "@rollup/plugin-commonjs": "^21.0.1", "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-node-resolve": "^13.0.6", "@rollup/pluginutils": "^4.1.1", - "@typescript-eslint/eslint-plugin": "5.17.0", - "@typescript-eslint/parser": "5.17.0", - "@typescript-eslint/scope-manager": "5.17.0", - "@typescript-eslint/typescript-estree": "5.17.0", - "@typescript-eslint/visitor-keys": "5.17.0", + "@typescript-eslint/eslint-plugin": "5.18.0", + "@typescript-eslint/parser": "5.18.0", + "@typescript-eslint/scope-manager": "5.18.0", + "@typescript-eslint/typescript-estree": "5.18.0", + "@typescript-eslint/visitor-keys": "5.18.0", "eslint": "*", "rollup": "^2.59.0", "semver": "^7.3.5" diff --git a/packages/website-eslint/src/linter/CompilerHost.js b/packages/website-eslint/src/linter/CompilerHost.js index 2b7fdec25d07..f48c77109c96 100644 --- a/packages/website-eslint/src/linter/CompilerHost.js +++ b/packages/website-eslint/src/linter/CompilerHost.js @@ -1,9 +1,43 @@ -import { getDefaultLibFileName } from 'typescript'; +import { + getDefaultLibFileName, + ScriptKind, + createSourceFile, + ScriptTarget, +} from 'typescript'; + +function getScriptKind(isJsx, filePath) { + const extension = (/(\.[a-z]+)$/.exec(filePath)?.[0] || '').toLowerCase(); + + switch (extension) { + case '.ts': + return ScriptKind.TS; + case '.tsx': + return ScriptKind.TSX; + case '.js': + return ScriptKind.JS; + + case '.jsx': + return ScriptKind.JSX; + + case '.json': + return ScriptKind.JSON; + + default: + // unknown extension, force typescript to ignore the file extension, and respect the user's setting + return isJsx ? ScriptKind.TSX : ScriptKind.TS; + } +} export class CompilerHost { - constructor(files, sourceFiles) { - this.files = files; - this.sourceFiles = sourceFiles; + constructor(libs, isJsx) { + this.files = []; + this.isJsx = isJsx || false; + + if (libs) { + for (const [key, value] of libs) { + this.files[key] = value; + } + } } fileExists(name) { @@ -39,10 +73,20 @@ export class CompilerHost { } readFile(name) { - return this.files[name]; + if (this.fileExists(name)) { + return this.files[name]; + } else { + return ''; // fallback, in case if file is not available + } } getSourceFile(name) { - return this.sourceFiles[name]; + return createSourceFile( + name, + this.readFile(name), + ScriptTarget.Latest, + /* setParentNodes */ true, + getScriptKind(this.isJsx, name), + ); } } diff --git a/packages/website-eslint/src/linter/create-ast-program.js b/packages/website-eslint/src/linter/create-ast-program.js deleted file mode 100644 index ea0444fd2491..000000000000 --- a/packages/website-eslint/src/linter/create-ast-program.js +++ /dev/null @@ -1,44 +0,0 @@ -import { - createProgram, - createSourceFile, - ScriptTarget, - ScriptKind, - JsxEmit, - ModuleKind, -} from 'typescript'; -import { CompilerHost } from './CompilerHost'; - -export function createASTProgram(code, parserOptions) { - const isJsx = !!parserOptions?.ecmaFeatures?.jsx; - const fileName = isJsx ? '/demo.tsx' : '/demo.ts'; - const files = { - [fileName]: code, - }; - const sourceFiles = { - [fileName]: createSourceFile( - fileName, - code, - ScriptTarget.Latest, - true, - isJsx ? ScriptKind.TSX : ScriptKind.TS, - ), - }; - const compilerHost = new CompilerHost(files, sourceFiles); - const compilerOptions = { - noResolve: true, - strict: true, - target: ScriptTarget.Latest, - jsx: isJsx ? JsxEmit.React : undefined, - module: ModuleKind.ES2015, - }; - const program = createProgram( - Object.keys(files), - compilerOptions, - compilerHost, - ); - const ast = program.getSourceFile(fileName); - return { - ast, - program, - }; -} diff --git a/packages/website-eslint/src/linter/linter.js b/packages/website-eslint/src/linter/linter.js index aae8ecc0feda..6d88c341f9c0 100644 --- a/packages/website-eslint/src/linter/linter.js +++ b/packages/website-eslint/src/linter/linter.js @@ -5,15 +5,20 @@ import rules from '@typescript-eslint/eslint-plugin/dist/rules'; const PARSER_NAME = '@typescript-eslint/parser'; -export function loadLinter() { +export function loadLinter(libs, compilerOptions) { const linter = new Linter(); let storedAST; let storedTsAST; let storedScope; linter.defineParser(PARSER_NAME, { - parseForESLint(code, options) { - const toParse = parseForESLint(code, options); + parseForESLint(code, eslintOptions) { + const toParse = parseForESLint( + code, + eslintOptions, + compilerOptions, + libs, + ); storedAST = toParse.ast; storedTsAST = toParse.tsAst; storedScope = toParse.scopeManager; diff --git a/packages/website-eslint/src/linter/parser.js b/packages/website-eslint/src/linter/parser.js index 41c0b24baf10..fc637fe65b7d 100644 --- a/packages/website-eslint/src/linter/parser.js +++ b/packages/website-eslint/src/linter/parser.js @@ -1,42 +1,55 @@ import { analyze } from '@typescript-eslint/scope-manager/dist/analyze'; import { visitorKeys } from '@typescript-eslint/visitor-keys/dist/visitor-keys'; import { astConverter } from '@typescript-eslint/typescript-estree/dist/ast-converter'; -import { createASTProgram } from './create-ast-program.js'; import { extra } from './config.js'; +import { CompilerHost } from './CompilerHost'; +import { createProgram } from 'typescript'; -function parseAndGenerateServices(code, options) { - const { ast, program } = createASTProgram(code, options); - const { estree, astMaps } = astConverter( - ast, - { ...extra, code, jsx: options.jsx ?? false }, - true, - ); +export function createASTProgram(code, isJsx, compilerOptions, libs) { + const fileName = isJsx ? '/demo.tsx' : '/demo.ts'; + const compilerHost = new CompilerHost(libs, isJsx); + compilerHost.files[fileName] = code; + const program = createProgram( + Object.keys(compilerHost.files), + compilerOptions, + compilerHost, + ); + const ast = program.getSourceFile(fileName); return { - ast: estree, - tsAst: ast, - services: { - hasFullTypeInformation: true, - program, - esTreeNodeToTSNodeMap: astMaps.esTreeNodeToTSNodeMap, - tsNodeToESTreeNodeMap: astMaps.tsNodeToESTreeNodeMap, - }, + ast, + program, }; } -export function parseForESLint(code, parserOptions) { - const { ast, tsAst, services } = parseAndGenerateServices(code, { - ...parserOptions, - jsx: parserOptions.ecmaFeatures?.jsx ?? false, - useJSXTextNode: true, - projectFolderIgnoreList: [], - }); +export function parseForESLint(code, eslintOptions, compilerOptions, libs) { + const isJsx = eslintOptions.ecmaFeatures?.jsx ?? false; + + const { ast: tsAst, program } = createASTProgram( + code, + isJsx, + compilerOptions, + libs, + ); + + const { estree: ast, astMaps } = astConverter( + tsAst, + { ...extra, code, jsx: isJsx }, + true, + ); + + const services = { + hasFullTypeInformation: true, + program, + esTreeNodeToTSNodeMap: astMaps.esTreeNodeToTSNodeMap, + tsNodeToESTreeNodeMap: astMaps.tsNodeToESTreeNodeMap, + }; const scopeManager = analyze(ast, { ecmaVersion: - parserOptions.ecmaVersion === 'latest' ? 1e8 : parserOptions.ecmaVersion, - globalReturn: parserOptions.ecmaFeatures?.globalReturn ?? false, - sourceType: parserOptions.sourceType ?? 'script', + eslintOptions.ecmaVersion === 'latest' ? 1e8 : eslintOptions.ecmaVersion, + globalReturn: eslintOptions.ecmaFeatures?.globalReturn ?? false, + sourceType: eslintOptions.sourceType ?? 'script', }); return { diff --git a/packages/website-eslint/types/index.d.ts b/packages/website-eslint/types/index.d.ts index ed3e1e2422f8..429de7388fa4 100644 --- a/packages/website-eslint/types/index.d.ts +++ b/packages/website-eslint/types/index.d.ts @@ -1,6 +1,6 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import type { ParserOptions } from '@typescript-eslint/types'; -import type { SourceFile } from 'typescript'; +import type { SourceFile, CompilerOptions } from 'typescript'; export type LintMessage = TSESLint.Linter.LintMessage; export type RuleFix = TSESLint.RuleFix; @@ -22,7 +22,10 @@ export interface WebLinter { } export interface LinterLoader { - loadLinter(): WebLinter; + loadLinter( + libMap: Map, + compilerOptions: CompilerOptions, + ): WebLinter; } export type { diff --git a/packages/website/CHANGELOG.md b/packages/website/CHANGELOG.md index db3ac9ab9b99..7de164212c93 100644 --- a/packages/website/CHANGELOG.md +++ b/packages/website/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.18.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.17.0...v5.18.0) (2022-04-04) + +**Note:** Version bump only for package website + + + + + # [5.17.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.16.0...v5.17.0) (2022-03-28) diff --git a/packages/website/package.json b/packages/website/package.json index 9ebc0a790a5f..86d5a8a0bcd3 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -1,6 +1,6 @@ { "name": "website", - "version": "5.17.0", + "version": "5.18.0", "private": true, "scripts": { "build": "docusaurus build", @@ -24,7 +24,7 @@ "@docusaurus/theme-common": "^2.0.0-beta.15", "@docusaurus/theme-search-algolia": "^2.0.0-beta.15", "@mdx-js/react": "1.6.22", - "@typescript-eslint/website-eslint": "5.17.0", + "@typescript-eslint/website-eslint": "5.18.0", "clsx": "^1.1.1", "eslint": "*", "json5": "^2.2.0", diff --git a/packages/website/src/components/ast/serializer/serializerTS.ts b/packages/website/src/components/ast/serializer/serializerTS.ts index fd03d983ba76..b89d6e0e1a44 100644 --- a/packages/website/src/components/ast/serializer/serializerTS.ts +++ b/packages/website/src/components/ast/serializer/serializerTS.ts @@ -24,6 +24,8 @@ export const propsToFilter = [ 'transformFlags', 'resolvedModules', 'imports', + 'antecedent', + 'antecedents', ]; function isTsNode(value: unknown): value is Node { diff --git a/packages/website/src/components/config/ConfigTypeScript.tsx b/packages/website/src/components/config/ConfigTypeScript.tsx index 27cc2cbdd97b..b2c215c6b577 100644 --- a/packages/website/src/components/config/ConfigTypeScript.tsx +++ b/packages/website/src/components/config/ConfigTypeScript.tsx @@ -1,7 +1,6 @@ -import React, { useCallback } from 'react'; -import tsConfigOptions from '../tsConfigOptions.json'; +import React, { useCallback, useEffect, useState } from 'react'; -import ConfigEditor from './ConfigEditor'; +import ConfigEditor, { ConfigOptionsType } from './ConfigEditor'; import type { CompilerFlags } from '../types'; import { shallowEqual } from '../lib/shallowEqual'; @@ -11,11 +10,59 @@ interface ModalTypeScriptProps { readonly config?: CompilerFlags; } +interface OptionDeclarations { + name: string; + type?: unknown; + category?: { message: string }; + description?: { message: string }; +} + function checkOptions(item: [string, unknown]): item is [string, boolean] { return typeof item[1] === 'boolean'; } function ConfigTypeScript(props: ModalTypeScriptProps): JSX.Element { + const [tsConfigOptions, updateOptions] = useState([]); + + useEffect(() => { + if (window.ts) { + updateOptions( + Object.values( + // @ts-expect-error: definition is not fully correct + (window.ts.optionDeclarations as OptionDeclarations[]) + .filter( + item => + item.type === 'boolean' && + item.description && + item.category && + ![ + 'Command-line Options', + 'Modules', + 'Projects', + 'Compiler Diagnostics', + 'Editor Support', + 'Output Formatting', + 'Watch and Build Modes', + 'Source Map Options', + ].includes(item.category.message), + ) + .reduce>((group, item) => { + const category = item.category!.message; + group[category] = group[category] ?? { + heading: category, + fields: [], + }; + group[category].fields.push({ + key: item.name, + label: item.description!.message, + }); + return group; + }, {}), + ), + ); + } + }, [props.isOpen]); + const onClose = useCallback( (newConfig: Record) => { const cfg = Object.fromEntries( diff --git a/packages/website/src/components/editor/LoadedEditor.tsx b/packages/website/src/components/editor/LoadedEditor.tsx index a3e8395bc3d7..880cf79a8a7a 100644 --- a/packages/website/src/components/editor/LoadedEditor.tsx +++ b/packages/website/src/components/editor/LoadedEditor.tsx @@ -139,8 +139,12 @@ export const LoadedEditor: React.FC = ({ useEffect(() => { sandboxInstance.setCompilerSettings({ + noResolve: true, + strict: true, + target: main.languages.typescript.ScriptTarget.ESNext, + module: main.languages.typescript.ModuleKind.ESNext, ...tsConfig, - jsx: jsx ? 2 : 0, + jsx: jsx ? main.languages.typescript.JsxEmit.React : undefined, }); }, [jsx, sandboxInstance, JSON.stringify(tsConfig) /* todo: better way? */]); diff --git a/packages/website/src/components/editor/useSandboxServices.ts b/packages/website/src/components/editor/useSandboxServices.ts index ffd6aa686ffb..b64345124b87 100644 --- a/packages/website/src/components/editor/useSandboxServices.ts +++ b/packages/website/src/components/editor/useSandboxServices.ts @@ -47,7 +47,16 @@ export const useSandboxServices = ( setLoadedTs(props.ts); sandboxSingleton(props.ts) - .then(({ main, sandboxFactory, ts, linter }) => { + .then(async ({ main, sandboxFactory, ts, linter }) => { + const compilerOptions = { + noResolve: true, + strict: true, + target: main.languages.typescript.ScriptTarget.ESNext, + jsx: props.jsx ? main.languages.typescript.JsxEmit.React : undefined, + lib: ['ESNext'], + module: main.languages.typescript.ModuleKind.ESNext, + }; + const sandboxConfig: Partial = { text: '', monacoSettings: { @@ -57,15 +66,7 @@ export const useSandboxServices = ( scrollBeyondLastLine: false, smoothScrolling: true, }, - compilerOptions: { - noResolve: true, - strict: true, - target: main.languages.typescript.ScriptTarget.ESNext, - jsx: props.jsx - ? main.languages.typescript.JsxEmit.React - : undefined, - module: main.languages.typescript.ModuleKind.ESNext, - }, + compilerOptions: compilerOptions, domID: editorEmbedId, }; @@ -75,7 +76,14 @@ export const useSandboxServices = ( ts, ); - const webLinter = linter.loadLinter(); + const libMap = await sandboxInstance.tsvfs.createDefaultMapFromCDN( + sandboxInstance.getCompilerOptions(), + props.ts, + true, + window.ts, + ); + + const webLinter = linter.loadLinter(libMap, compilerOptions); props.onLoaded(webLinter.ruleNames, sandboxInstance.supportedVersions); diff --git a/packages/website/src/components/tsConfigOptions.json b/packages/website/src/components/tsConfigOptions.json deleted file mode 100644 index 8ddd3b6d35df..000000000000 --- a/packages/website/src/components/tsConfigOptions.json +++ /dev/null @@ -1,97 +0,0 @@ -[ - { - "heading": "Interop Constraints", - "fields": [ - { - "key": "isolatedModules", - "label": "Ensure that each file can be safely transpiled without relying on other imports." - }, - { - "key": "allowSyntheticDefaultImports", - "label": "Allow `import x from y` when a module doesn't have a default export." - }, - { - "key": "esModuleInterop", - "label": "Emit additional JavaScript to ease support for importing CommonJS modules. This enables allowSyntheticDefaultImports for type compatibility." - } - ] - }, - { - "heading": "Type Checking", - "fields": [ - { - "key": "strict", - "label": "Enable all strict type-checking options." - }, - { - "key": "noImplicitAny", - "label": "Enable error reporting for expressions and declarations with an implied any type.." - }, - { - "key": "strictNullChecks", - "label": "When type checking, take into account null and undefined." - }, - { - "key": "strictFunctionTypes", - "label": "When assigning functions, check to ensure parameters and the return values are subtype-compatible." - }, - { - "key": "strictBindCallApply", - "label": "Check that the arguments for bind, call, and apply methods match the original function." - }, - { - "key": "strictPropertyInitialization", - "label": "Check for class properties that are declared but not set in the constructor." - }, - { - "key": "noImplicitThis", - "label": "Enable error reporting when this is given the type any." - }, - { - "key": "alwaysStrict", - "label": "Ensure `use strict` is always emitted." - }, - { - "key": "noUnusedLocals", - "label": "Enable error reporting when a local variables aren't read." - }, - { - "key": "noUnusedParameters", - "label": "Raise an error when a function parameter isn't read." - }, - { - "key": "noImplicitReturns", - "label": "Enable error reporting for codepaths that do not explicitly return in a function." - }, - { - "key": "noFallthroughCasesInSwitch", - "label": "Enable error reporting for fallthrough cases in switch statements." - }, - { - "key": "allowUnusedLabels", - "label": "Disable error reporting for unused labels." - }, - { - "key": "allowUnreachableCode", - "label": "Disable error reporting for unreachable code." - } - ] - }, - { - "heading": "Language and Environment", - "fields": [ - { - "key": "experimentalDecorators", - "label": "Enable experimental support for TC39 stage 2 draft decorators." - }, - { - "key": "emitDecoratorMetadata", - "label": "Emit design-type metadata for decorated declarations in source files." - }, - { - "key": "noLib", - "label": "Disable including any library files, including the default lib.d.ts." - } - ] - } -] diff --git a/packages/website/src/css/custom.css b/packages/website/src/css/custom.css index ade3524adb2f..fc3611513ce3 100644 --- a/packages/website/src/css/custom.css +++ b/packages/website/src/css/custom.css @@ -19,7 +19,6 @@ html:root { --ifm-code-font-size: 95%; --ifm-color-info: var(--ifm-color-primary-dark); --ifm-link-color: var(--ifm-color-primary-dark); - --ifm-link-color: var(--ifm-color-primary-dark); --code-line-decoration: rgba(53, 120, 229, 0.1); --code-editor-bg: #ffffff; @@ -27,7 +26,7 @@ html:root { --docsearch-muted-color: #666; } -html[data-theme='dark'] { +html[data-theme='dark']:root { --ifm-color-feedback-background: #f0f8ff; --ifm-color-primary: #4e89e8; --ifm-color-primary-dark: #144697; @@ -41,7 +40,6 @@ html[data-theme='dark'] { --ifm-code-color: rgb(248, 248, 242); --ifm-color-info: var(--ifm-color-primary-light); --ifm-link-color: var(--ifm-color-primary-light); - --ifm-link-color: var(--ifm-color-primary-light); --ifm-menu-color-active: var(--ifm-color-primary-light); --ifm-navbar-link-hover-color: var(--ifm-color-primary-light); diff --git a/yarn.lock b/yarn.lock index 05ea3f1c11ba..a86d7ab53d08 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3578,9 +3578,9 @@ integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g== "@rollup/plugin-commonjs@^21.0.1": - version "21.0.2" - resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-21.0.2.tgz#0b9c539aa1837c94abfaf87945838b0fc8564891" - integrity sha512-d/OmjaLVO4j/aQX69bwpWPpbvI3TJkQuxoAk7BH8ew1PyoMBLTOuvJTjzG8oEoW7drIIqB0KCJtfFLu/2GClWg== + version "21.0.3" + resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-21.0.3.tgz#287896c64926ef3d7f0013708dcdcc1223576ef0" + integrity sha512-ThGfwyvcLc6cfP/MWxA5ACF+LZCvsuhUq7V5134Az1oQWsiC7lNpLT4mJI86WQunK7BYmpUiHmMk2Op6OAHs0g== dependencies: "@rollup/pluginutils" "^3.1.0" commondir "^1.0.1" pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy