diff --git a/.cspell.json b/.cspell.json
index c6623037c42c..c5bd12a5c9ab 100644
--- a/.cspell.json
+++ b/.cspell.json
@@ -63,6 +63,7 @@
"bivariant",
"blockless",
"blurple",
+ "bradzacher",
"camelcase",
"Cena",
"codebases",
@@ -88,6 +89,8 @@
"IDE's",
"IIFE",
"IIFEs",
+ "jameshenry",
+ "joshuakgoldberg",
"linebreaks",
"lzstring",
"markdownlint",
@@ -95,6 +98,7 @@
"necroing",
"nocheck",
"noninteractive",
+ "Nrwl",
"nullish",
"onboarded",
"OOM",
diff --git a/.github/ISSUE_TEMPLATE/06-bug-report-other.yaml b/.github/ISSUE_TEMPLATE/06-bug-report-other.yaml
index a7da8ab04c37..c3ab6ee8df3b 100644
--- a/.github/ISSUE_TEMPLATE/06-bug-report-other.yaml
+++ b/.github/ISSUE_TEMPLATE/06-bug-report-other.yaml
@@ -38,6 +38,7 @@ body:
- parser
- rule-tester
- scope-manager
+ - typescript-eslint
- typescript-estree
- utils
- website
diff --git a/.github/ISSUE_TEMPLATE/07-enhancement-other.yaml b/.github/ISSUE_TEMPLATE/07-enhancement-other.yaml
index f383970cf440..b3ae91962b1c 100644
--- a/.github/ISSUE_TEMPLATE/07-enhancement-other.yaml
+++ b/.github/ISSUE_TEMPLATE/07-enhancement-other.yaml
@@ -28,6 +28,7 @@ body:
- parser
- scope-manager
- type-utils
+ - typescript-eslint
- typescript-estree
- utils
- website
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6af7a8de8ca0..9951a2cc4bcd 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -14,7 +14,7 @@ concurrency:
cancel-in-progress: true
env:
- PRIMARY_NODE_VERSION: '>=20.6.1'
+ PRIMARY_NODE_VERSION: 20
# Only set the read-write token if we are on the main branch
NX_CLOUD_ACCESS_TOKEN: ${{ (github.event_name == 'push' && github.ref == 'refs/heads/main') && secrets.NX_CLOUD_ACCESS_TOKEN || '' }}
@@ -171,6 +171,7 @@ jobs:
'rule-schema-to-typescript-types',
'scope-manager',
'type-utils',
+ 'typescript-eslint',
'typescript-estree',
'utils',
'visitor-keys',
diff --git a/.github/workflows/semantic-pr-titles.yml b/.github/workflows/semantic-pr-titles.yml
index 3ebb03d6fb2a..fceee3e45519 100644
--- a/.github/workflows/semantic-pr-titles.yml
+++ b/.github/workflows/semantic-pr-titles.yml
@@ -35,6 +35,7 @@ jobs:
scope-manager
type-utils
types
+ typescript-eslint
typescript-estree
utils
visitor-keys
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 088f152496b4..9fcad86bf4e0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,35 @@
+## 6.21.0 (2024-02-05)
+
+
+### 🚀 Features
+
+- export plugin metadata ([#8331](https://github.com/typescript-eslint/typescript-eslint/pull/8331))
+- allow `parserOptions.project: false` ([#8339](https://github.com/typescript-eslint/typescript-eslint/pull/8339))
+- **eslint-plugin:** add rule prefer-find ([#8216](https://github.com/typescript-eslint/typescript-eslint/pull/8216))
+- **typescript-estree:** forbid duplicated accessibility modifiers ([#8257](https://github.com/typescript-eslint/typescript-eslint/pull/8257))
+- **utils:** improve eslint types ([#8344](https://github.com/typescript-eslint/typescript-eslint/pull/8344))
+
+### 🩹 Fixes
+
+- **ast-spec:** add `JSXElement` type to the `JSXAttribute['value']` ([#8285](https://github.com/typescript-eslint/typescript-eslint/pull/8285))
+- **eslint-plugin:** [no-unused-vars] don't report on types referenced in export assignment expression ([#8265](https://github.com/typescript-eslint/typescript-eslint/pull/8265))
+- **eslint-plugin:** [switch-exhaustiveness-check] better support for intersections, infinite types, non-union values ([#8250](https://github.com/typescript-eslint/typescript-eslint/pull/8250))
+- **eslint-plugin:** [consistent-type-imports] dont report on types used in export assignment expressions ([#8332](https://github.com/typescript-eslint/typescript-eslint/pull/8332))
+- **eslint-plugin:** [no-unnecessary-condition] handle left-hand optional with exactOptionalPropertyTypes option ([#8249](https://github.com/typescript-eslint/typescript-eslint/pull/8249))
+- **eslint-plugin:** [class-literal-property-style] allow getter when same key setter exists ([#8277](https://github.com/typescript-eslint/typescript-eslint/pull/8277))
+- **eslint-plugin:** [no-unnecessary-type-assertion] provide valid fixes for assertions with extra tokens before `as` keyword ([#8326](https://github.com/typescript-eslint/typescript-eslint/pull/8326))
+- **rule-tester:** fix a phantom dependency on the "semver" package ([#8260](https://github.com/typescript-eslint/typescript-eslint/pull/8260))
+
+### ❤️ Thank You
+
+- auvred @auvred
+- Brad Zacher @bradzacher
+- Kirk Waiblinger @kirkwaiblinger
+- Pete Gonzalez @octogonz
+- YeonJuan @yeonjuan
+
+You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.
+
## 6.20.0 (2024-01-29)
diff --git a/docs/linting/Troubleshooting.mdx b/docs/linting/Troubleshooting.mdx
index 526a79e03c63..36d8798ceab3 100644
--- a/docs/linting/Troubleshooting.mdx
+++ b/docs/linting/Troubleshooting.mdx
@@ -174,6 +174,17 @@ You can see that the type of `condition` is actually the literal type `false` by
If the IDE provides different type information from typescript-eslint's report, then make sure that the TypeScript setup used for your IDE, typescript-eslint, and `tsc` are the same: the same TypeScript version, the same type-checking compiler options, and the same files being included in the project. For example, if a type is declared in another file but that file is not included, the type will become `any`, and cause our `no-unsafe-*` rules to report.
+## Can I use ESLint's `--cache` with typescript-eslint?
+
+[ESLint's `--cache` option](https://eslint.org/docs/latest/use/command-line-interface#caching) caches on a per-file basis.
+You can use it, but it will only work reliably for untyped rules -- and even then, not always.
+
+Any ESLint rule that checks logic across files, including many rules from `eslint-plugin-import`, creates cross-file dependencies.
+[Typed lint rules](./Typed_Linting.mdx) almost always have dependencies on types across files in practice.
+ESLint's caching doesn't account for those cross-file dependencies.
+
+We don't recommend using `--cache`.
+
## I use a framework (like Vue) that requires custom file extensions, and I get errors like "You should add `parserOptions.extraFileExtensions` to your config"
You can use `parserOptions.extraFileExtensions` to specify an array of non-TypeScript extensions to allow, for example:
@@ -240,22 +251,22 @@ For example, you can ban enums (or some variation of) using one of the following
// ban all enums
{
"selector": "TSEnumDeclaration",
- "message": "My reason for not using any enums at all"
+ "message": "My reason for not using any enums at all",
},
// ban just const enums
{
"selector": "TSEnumDeclaration[const=true]",
- "message": "My reason for not using const enums"
+ "message": "My reason for not using const enums",
},
// ban just non-const enums
{
"selector": "TSEnumDeclaration:not([const=true])",
- "message": "My reason for not using non-const enums"
- }
- ]
- }
+ "message": "My reason for not using non-const enums",
+ },
+ ],
+ },
}
```
diff --git a/docs/linting/typed-linting/Monorepos.mdx b/docs/linting/typed-linting/Monorepos.mdx
index 43f688062b79..6c172cb29398 100644
--- a/docs/linting/typed-linting/Monorepos.mdx
+++ b/docs/linting/typed-linting/Monorepos.mdx
@@ -23,14 +23,14 @@ If its `include` paths cannot include all files to be linted, we suggest creatin
"extends": "./tsconfig.json",
"compilerOptions": {
// ensure that nobody can accidentally use this config for a build
- "noEmit": true
+ "noEmit": true,
},
"include": [
// whatever paths you intend to lint
"src",
"test",
- "tools"
- ]
+ "tools",
+ ],
}
```
diff --git a/docs/maintenance/Team.mdx b/docs/maintenance/Team.mdx
new file mode 100644
index 000000000000..3fd2d66d8a80
--- /dev/null
+++ b/docs/maintenance/Team.mdx
@@ -0,0 +1,98 @@
+---
+id: team
+title: Team
+---
+
+import { TeamBioDivider } from '@site/src/components/team/TeamBioDivider';
+import { TeamBioList } from '@site/src/components/team/TeamBioList';
+
+The typescript-eslint organization is an independent open source project. Its
+members are volunteer open source developers dedicated to making the
+TypeScript linting experience great.
+
+
+
+## Maintainers
+
+
+
+
+
+## Committers
+
+
+
+
+
+## Join Us
+
+We're always looking for developers to add to the team.
+If you're interest in becoming a committer, go ahead and get started with our [Contributing guide](../Contributing.mdx).
+[Contributor Tiers](./Contributor_Tiers.mdx) describes the expectations for entering and then staying at any contributor tier.
+
+
+
+## Sponsor Us
+
+As an independent open source project, funding for our work comes from the community.
+We're eternally grateful to every individual and organization able to help us keep working.
+
+See [`.github/SPONSORSHIPS.md`](https://github.com/typescript-eslint/typescript-eslint/blob/main/.github/SPONSORSHIPS.md) for documentation on how and why to sponsor us.
+
+You can find our biggest sponsors on [typescript-eslint.io > Financial Contributors](https://typescript-eslint.io/#financial-contributors).
+More can be found on [our Open Collective](https://opencollective.com/typescript-eslint).
diff --git a/docs/packages/Parser.mdx b/docs/packages/Parser.mdx
index 5d5860493103..062c7aa247a0 100644
--- a/docs/packages/Parser.mdx
+++ b/docs/packages/Parser.mdx
@@ -45,8 +45,8 @@ interface ParserOptions {
jsxFragmentName?: string | null;
jsxPragma?: string | null;
lib?: string[];
- programs?: import('typescript').Program;
- project?: string | string[] | true;
+ programs?: import('typescript').Program[];
+ project?: string | string[] | boolean | null;
projectFolderIgnoreList?: string[];
tsconfigRootDir?: string;
warnOnUnsupportedTypeScriptVersion?: boolean;
@@ -212,13 +212,17 @@ This option allows you to provide a path to your project's `tsconfig.json`. **Th
// array of paths and/or glob patterns
project: ['./packages/**/tsconfig.json', './separate-package/tsconfig.json'];
+
+ // ways to disable type-aware linting (useful for overrides configs)
+ project: false;
+ project: null;
```
- If `true`, each source file's parse will find the nearest `tsconfig.json` file to that source file.
- This is done by checking that source file's directory tree for the nearest `tsconfig.json`.
-- If you use project references, TypeScript will not automatically use project references to resolve files. This means that you will have to add each referenced tsconfig to the `project` field either separately, or via a glob.
+- If you use project references, TypeScript will **not** automatically use project references to resolve files. This means that you will have to add each referenced tsconfig to the `project` field either separately, or via a glob.
- Note that using wide globs `**` in your `parserOptions.project` may cause performance implications. Instead of globs that use `**` to recursively check all folders, prefer paths that use a single `*` at a time. For more info see [#2611](https://github.com/typescript-eslint/typescript-eslint/issues/2611).
@@ -237,8 +241,8 @@ This option allows you to provide a path to your project's `tsconfig.json`. **Th
// etc
// if you have a mixed JS/TS codebase, don't forget to include your JS files
- "src/**/*.js"
- ]
+ "src/**/*.js",
+ ],
}
```
diff --git a/docs/packages/TypeScript_ESTree.mdx b/docs/packages/TypeScript_ESTree.mdx
index 27122374bd18..f589cb8f6605 100644
--- a/docs/packages/TypeScript_ESTree.mdx
+++ b/docs/packages/TypeScript_ESTree.mdx
@@ -209,8 +209,10 @@ interface ParseAndGenerateServicesOptions extends ParseOptions {
* Absolute (or relative to `tsconfigRootDir`) paths to the tsconfig(s),
* or `true` to find the nearest tsconfig.json to the file.
* If this is provided, type information will be returned.
+ *
+ * If set to `false`, `null`, or `undefined`, type information will not be returned.
*/
- project?: string | string[] | true;
+ project?: string[] | string | boolean | null;
/**
* If you provide a glob (or globs) to the project option, you can use this option to ignore certain folders from
diff --git a/nx.json b/nx.json
index d85a0833983e..0f59cb4dec09 100644
--- a/nx.json
+++ b/nx.json
@@ -42,6 +42,7 @@
"inputs": [
"default",
"{workspaceRoot}/.eslintrc.js",
+ "{workspaceRoot}/package.json",
"{workspaceRoot}/yarn.lock",
"{workspaceRoot}/.eslintignore",
{
diff --git a/package.json b/package.json
index f43185c96c6c..23da68e6698e 100644
--- a/package.json
+++ b/package.json
@@ -32,7 +32,7 @@
"clean": "nx run-many --target=clean",
"format": "prettier --write .",
"generate-breaking-changes": "npx nx run eslint-plugin:generate-breaking-changes",
- "generate-configs": "npx nx run eslint-plugin:generate:configs",
+ "generate-configs": "npx nx run repo-tools:generate-configs",
"generate-contributors": "npx nx run repo-tools:generate-contributors",
"generate-sponsors": "npx nx run repo-tools:generate-sponsors",
"generate-website-dts": "npx nx run website:generate-website-dts",
@@ -63,14 +63,14 @@
"@nx/eslint": "17.2.8",
"@nx/jest": "17.2.8",
"@nx/workspace": "17.2.8",
- "@prettier/sync": "^0.3.0",
+ "@prettier/sync": "^0.5.0",
"@swc/core": "^1.3.68",
"@swc/jest": "^0.2.26",
"@types/babel__code-frame": "^7.0.3",
"@types/babel__core": "^7.20.1",
"@types/debug": "^4.1.8",
"@types/is-glob": "^4.0.2",
- "@types/jest": "29.5.11",
+ "@types/jest": "29.5.12",
"@types/jest-specific-snapshot": "^0.5.6",
"@types/marked": "^5.0.0",
"@types/natural-compare": "^1.4.1",
@@ -79,22 +79,23 @@
"@types/semver": "^7.5.0",
"@types/tmp": "^0.2.3",
"@types/yargs": "^17.0.32",
+ "@typescript-eslint/eslint-plugin-internal": "workspace:^",
"console-fail-test": "^0.2.3",
"cross-fetch": "^4.0.0",
"cspell": "^7.0.0",
"downlevel-dts": ">=0.11.0",
- "eslint": "^8.47.0",
+ "eslint": "^8.56.0",
"eslint-plugin-deprecation": "^2.0.0",
"eslint-plugin-eslint-comments": "^3.2.0",
- "eslint-plugin-eslint-plugin": "^5.1.0",
- "eslint-plugin-import": "^2.27.5",
- "eslint-plugin-jest": "^27.2.2",
- "eslint-plugin-jsdoc": "^46.9.1",
- "eslint-plugin-jsx-a11y": "^6.7.1",
- "eslint-plugin-react": "^7.32.2",
+ "eslint-plugin-eslint-plugin": "^5.2.1",
+ "eslint-plugin-import": "^2.29.1",
+ "eslint-plugin-jest": "^27.6.3",
+ "eslint-plugin-jsdoc": "^47.0.2",
+ "eslint-plugin-jsx-a11y": "^6.8.0",
+ "eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-simple-import-sort": "^10.0.0",
- "eslint-plugin-unicorn": "^48.0.1",
+ "eslint-plugin-unicorn": "^50.0.1",
"execa": "7.1.1",
"glob": "^10.3.3",
"husky": "^8.0.3",
@@ -104,11 +105,11 @@
"jest-specific-snapshot": "^8.0.0",
"lint-staged": "^15.0.0",
"make-dir": "^4.0.0",
- "markdownlint-cli": "^0.37.0",
+ "markdownlint-cli": "^0.39.0",
"ncp": "^2.0.0",
"netlify": "^13.1.9",
"nx": "17.2.8",
- "prettier": "3.1.0",
+ "prettier": "3.2.4",
"pretty-format": "^29.6.2",
"raw-loader": "^4.0.2",
"rimraf": "^5.0.1",
@@ -117,7 +118,8 @@
"tslint": "^6.1.3",
"tsx": "^4.6.2",
"typescript": ">=4.3.5 <5.4.0",
- "yargs": "17.7.1"
+ "typescript-eslint": "workspace:^",
+ "yargs": "17.7.2"
},
"resolutions": {
"@jest/create-cache-key-function": "^29",
diff --git a/packages/ast-spec/CHANGELOG.md b/packages/ast-spec/CHANGELOG.md
index f074d88c84ee..9e36fa5a8536 100644
--- a/packages/ast-spec/CHANGELOG.md
+++ b/packages/ast-spec/CHANGELOG.md
@@ -1,3 +1,28 @@
+## 6.21.0 (2024-02-05)
+
+
+### 🚀 Features
+
+- allow `parserOptions.project: false`
+
+- **typescript-estree:** forbid duplicated accessibility modifiers
+
+
+### 🩹 Fixes
+
+- **ast-spec:** add `JSXElement` type to the `JSXAttribute['value']`
+
+
+### ❤️ Thank You
+
+- auvred
+- Brad Zacher
+- Kirk Waiblinger
+- Pete Gonzalez
+- YeonJuan
+
+You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.
+
## 6.20.0 (2024-01-29)
This was a version bump only for ast-spec to align it with other projects, there were no code changes.
diff --git a/packages/ast-spec/package.json b/packages/ast-spec/package.json
index 4919b30dbe16..2a7472322744 100644
--- a/packages/ast-spec/package.json
+++ b/packages/ast-spec/package.json
@@ -1,6 +1,6 @@
{
"name": "@typescript-eslint/ast-spec",
- "version": "6.20.0",
+ "version": "6.21.0",
"description": "Complete specification for the TypeScript-ESTree AST",
"private": true,
"keywords": [
diff --git a/packages/ast-spec/src/element/MethodDefinition/fixtures/_error_/duplicated-accessibility-modifiers/fixture.ts b/packages/ast-spec/src/element/MethodDefinition/fixtures/_error_/duplicated-accessibility-modifiers/fixture.ts
new file mode 100644
index 000000000000..29db5140d271
--- /dev/null
+++ b/packages/ast-spec/src/element/MethodDefinition/fixtures/_error_/duplicated-accessibility-modifiers/fixture.ts
@@ -0,0 +1,3 @@
+class Foo {
+ public public bar() {};
+}
diff --git a/packages/ast-spec/src/element/MethodDefinition/fixtures/_error_/duplicated-accessibility-modifiers/snapshots/1-TSESTree-Error.shot b/packages/ast-spec/src/element/MethodDefinition/fixtures/_error_/duplicated-accessibility-modifiers/snapshots/1-TSESTree-Error.shot
new file mode 100644
index 000000000000..49db5284df5a
--- /dev/null
+++ b/packages/ast-spec/src/element/MethodDefinition/fixtures/_error_/duplicated-accessibility-modifiers/snapshots/1-TSESTree-Error.shot
@@ -0,0 +1,10 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AST Fixtures element MethodDefinition _error_ duplicated-accessibility-modifiers TSESTree - Error 1`] = `
+"TSError
+ 1 | class Foo {
+> 2 | public public bar() {};
+ | ^^^^^^ Accessibility modifier already seen.
+ 3 | }
+ 4 |"
+`;
diff --git a/packages/ast-spec/src/element/MethodDefinition/fixtures/_error_/duplicated-accessibility-modifiers/snapshots/2-Babel-Error.shot b/packages/ast-spec/src/element/MethodDefinition/fixtures/_error_/duplicated-accessibility-modifiers/snapshots/2-Babel-Error.shot
new file mode 100644
index 000000000000..e84a8adf3e77
--- /dev/null
+++ b/packages/ast-spec/src/element/MethodDefinition/fixtures/_error_/duplicated-accessibility-modifiers/snapshots/2-Babel-Error.shot
@@ -0,0 +1,3 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AST Fixtures element MethodDefinition _error_ duplicated-accessibility-modifiers Babel - Error 1`] = `[SyntaxError: Accessibility modifier already seen. (2:9)]`;
diff --git a/packages/ast-spec/src/element/MethodDefinition/fixtures/_error_/duplicated-accessibility-modifiers/snapshots/3-Alignment-Error.shot b/packages/ast-spec/src/element/MethodDefinition/fixtures/_error_/duplicated-accessibility-modifiers/snapshots/3-Alignment-Error.shot
new file mode 100644
index 000000000000..d87e3076b189
--- /dev/null
+++ b/packages/ast-spec/src/element/MethodDefinition/fixtures/_error_/duplicated-accessibility-modifiers/snapshots/3-Alignment-Error.shot
@@ -0,0 +1,3 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AST Fixtures element MethodDefinition _error_ duplicated-accessibility-modifiers Error Alignment 1`] = `"Both errored"`;
diff --git a/packages/ast-spec/src/element/MethodDefinition/fixtures/_error_/mixed-accessibility-modifiers/fixture.ts b/packages/ast-spec/src/element/MethodDefinition/fixtures/_error_/mixed-accessibility-modifiers/fixture.ts
new file mode 100644
index 000000000000..6d9a757a6c96
--- /dev/null
+++ b/packages/ast-spec/src/element/MethodDefinition/fixtures/_error_/mixed-accessibility-modifiers/fixture.ts
@@ -0,0 +1,3 @@
+class Foo {
+ public protected bar() {};
+}
diff --git a/packages/ast-spec/src/element/MethodDefinition/fixtures/_error_/mixed-accessibility-modifiers/snapshots/1-TSESTree-Error.shot b/packages/ast-spec/src/element/MethodDefinition/fixtures/_error_/mixed-accessibility-modifiers/snapshots/1-TSESTree-Error.shot
new file mode 100644
index 000000000000..adeb1e6df792
--- /dev/null
+++ b/packages/ast-spec/src/element/MethodDefinition/fixtures/_error_/mixed-accessibility-modifiers/snapshots/1-TSESTree-Error.shot
@@ -0,0 +1,10 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AST Fixtures element MethodDefinition _error_ mixed-accessibility-modifiers TSESTree - Error 1`] = `
+"TSError
+ 1 | class Foo {
+> 2 | public protected bar() {};
+ | ^^^^^^^^^ Accessibility modifier already seen.
+ 3 | }
+ 4 |"
+`;
diff --git a/packages/ast-spec/src/element/MethodDefinition/fixtures/_error_/mixed-accessibility-modifiers/snapshots/2-Babel-Error.shot b/packages/ast-spec/src/element/MethodDefinition/fixtures/_error_/mixed-accessibility-modifiers/snapshots/2-Babel-Error.shot
new file mode 100644
index 000000000000..223e5193276e
--- /dev/null
+++ b/packages/ast-spec/src/element/MethodDefinition/fixtures/_error_/mixed-accessibility-modifiers/snapshots/2-Babel-Error.shot
@@ -0,0 +1,3 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AST Fixtures element MethodDefinition _error_ mixed-accessibility-modifiers Babel - Error 1`] = `[SyntaxError: Accessibility modifier already seen. (2:9)]`;
diff --git a/packages/ast-spec/src/element/MethodDefinition/fixtures/_error_/mixed-accessibility-modifiers/snapshots/3-Alignment-Error.shot b/packages/ast-spec/src/element/MethodDefinition/fixtures/_error_/mixed-accessibility-modifiers/snapshots/3-Alignment-Error.shot
new file mode 100644
index 000000000000..957afbc76959
--- /dev/null
+++ b/packages/ast-spec/src/element/MethodDefinition/fixtures/_error_/mixed-accessibility-modifiers/snapshots/3-Alignment-Error.shot
@@ -0,0 +1,3 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AST Fixtures element MethodDefinition _error_ mixed-accessibility-modifiers Error Alignment 1`] = `"Both errored"`;
diff --git a/packages/ast-spec/src/element/PropertyDefinition/fixtures/_error_/duplicated-accessibility-modifiers/fixture.ts b/packages/ast-spec/src/element/PropertyDefinition/fixtures/_error_/duplicated-accessibility-modifiers/fixture.ts
new file mode 100644
index 000000000000..cfe758d6b422
--- /dev/null
+++ b/packages/ast-spec/src/element/PropertyDefinition/fixtures/_error_/duplicated-accessibility-modifiers/fixture.ts
@@ -0,0 +1,3 @@
+class Foo {
+ public public bar;
+}
diff --git a/packages/ast-spec/src/element/PropertyDefinition/fixtures/_error_/duplicated-accessibility-modifiers/snapshots/1-TSESTree-Error.shot b/packages/ast-spec/src/element/PropertyDefinition/fixtures/_error_/duplicated-accessibility-modifiers/snapshots/1-TSESTree-Error.shot
new file mode 100644
index 000000000000..6fbf0b6b8290
--- /dev/null
+++ b/packages/ast-spec/src/element/PropertyDefinition/fixtures/_error_/duplicated-accessibility-modifiers/snapshots/1-TSESTree-Error.shot
@@ -0,0 +1,10 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AST Fixtures element PropertyDefinition _error_ duplicated-accessibility-modifiers TSESTree - Error 1`] = `
+"TSError
+ 1 | class Foo {
+> 2 | public public bar;
+ | ^^^^^^ Accessibility modifier already seen.
+ 3 | }
+ 4 |"
+`;
diff --git a/packages/ast-spec/src/element/PropertyDefinition/fixtures/_error_/duplicated-accessibility-modifiers/snapshots/2-Babel-Error.shot b/packages/ast-spec/src/element/PropertyDefinition/fixtures/_error_/duplicated-accessibility-modifiers/snapshots/2-Babel-Error.shot
new file mode 100644
index 000000000000..1285ca65797e
--- /dev/null
+++ b/packages/ast-spec/src/element/PropertyDefinition/fixtures/_error_/duplicated-accessibility-modifiers/snapshots/2-Babel-Error.shot
@@ -0,0 +1,3 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AST Fixtures element PropertyDefinition _error_ duplicated-accessibility-modifiers Babel - Error 1`] = `[SyntaxError: Accessibility modifier already seen. (2:9)]`;
diff --git a/packages/ast-spec/src/element/PropertyDefinition/fixtures/_error_/duplicated-accessibility-modifiers/snapshots/3-Alignment-Error.shot b/packages/ast-spec/src/element/PropertyDefinition/fixtures/_error_/duplicated-accessibility-modifiers/snapshots/3-Alignment-Error.shot
new file mode 100644
index 000000000000..116d47b88301
--- /dev/null
+++ b/packages/ast-spec/src/element/PropertyDefinition/fixtures/_error_/duplicated-accessibility-modifiers/snapshots/3-Alignment-Error.shot
@@ -0,0 +1,3 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AST Fixtures element PropertyDefinition _error_ duplicated-accessibility-modifiers Error Alignment 1`] = `"Both errored"`;
diff --git a/packages/ast-spec/src/element/PropertyDefinition/fixtures/_error_/mixed-accessibility-modifiers/fixture.ts b/packages/ast-spec/src/element/PropertyDefinition/fixtures/_error_/mixed-accessibility-modifiers/fixture.ts
new file mode 100644
index 000000000000..a9715175b5ad
--- /dev/null
+++ b/packages/ast-spec/src/element/PropertyDefinition/fixtures/_error_/mixed-accessibility-modifiers/fixture.ts
@@ -0,0 +1,3 @@
+class Foo {
+ public protected bar;
+}
diff --git a/packages/ast-spec/src/element/PropertyDefinition/fixtures/_error_/mixed-accessibility-modifiers/snapshots/1-TSESTree-Error.shot b/packages/ast-spec/src/element/PropertyDefinition/fixtures/_error_/mixed-accessibility-modifiers/snapshots/1-TSESTree-Error.shot
new file mode 100644
index 000000000000..0786548487bd
--- /dev/null
+++ b/packages/ast-spec/src/element/PropertyDefinition/fixtures/_error_/mixed-accessibility-modifiers/snapshots/1-TSESTree-Error.shot
@@ -0,0 +1,10 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AST Fixtures element PropertyDefinition _error_ mixed-accessibility-modifiers TSESTree - Error 1`] = `
+"TSError
+ 1 | class Foo {
+> 2 | public protected bar;
+ | ^^^^^^^^^ Accessibility modifier already seen.
+ 3 | }
+ 4 |"
+`;
diff --git a/packages/ast-spec/src/element/PropertyDefinition/fixtures/_error_/mixed-accessibility-modifiers/snapshots/2-Babel-Error.shot b/packages/ast-spec/src/element/PropertyDefinition/fixtures/_error_/mixed-accessibility-modifiers/snapshots/2-Babel-Error.shot
new file mode 100644
index 000000000000..309038c6d169
--- /dev/null
+++ b/packages/ast-spec/src/element/PropertyDefinition/fixtures/_error_/mixed-accessibility-modifiers/snapshots/2-Babel-Error.shot
@@ -0,0 +1,3 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AST Fixtures element PropertyDefinition _error_ mixed-accessibility-modifiers Babel - Error 1`] = `[SyntaxError: Accessibility modifier already seen. (2:9)]`;
diff --git a/packages/ast-spec/src/element/PropertyDefinition/fixtures/_error_/mixed-accessibility-modifiers/snapshots/3-Alignment-Error.shot b/packages/ast-spec/src/element/PropertyDefinition/fixtures/_error_/mixed-accessibility-modifiers/snapshots/3-Alignment-Error.shot
new file mode 100644
index 000000000000..611da1f7d9ca
--- /dev/null
+++ b/packages/ast-spec/src/element/PropertyDefinition/fixtures/_error_/mixed-accessibility-modifiers/snapshots/3-Alignment-Error.shot
@@ -0,0 +1,3 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AST Fixtures element PropertyDefinition _error_ mixed-accessibility-modifiers Error Alignment 1`] = `"Both errored"`;
diff --git a/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/fixture.tsx b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/fixture.tsx
new file mode 100644
index 000000000000..898c2784387e
--- /dev/null
+++ b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/fixture.tsx
@@ -0,0 +1 @@
+bar />;
diff --git a/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/snapshots/1-TSESTree-AST.shot b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/snapshots/1-TSESTree-AST.shot
new file mode 100644
index 000000000000..eab486714e39
--- /dev/null
+++ b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/snapshots/1-TSESTree-AST.shot
@@ -0,0 +1,139 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AST Fixtures jsx JSXAttribute element-non-self-closing TSESTree - AST 1`] = `
+Program {
+ type: "Program",
+ body: [
+ ExpressionStatement {
+ type: "ExpressionStatement",
+ expression: JSXElement {
+ type: "JSXElement",
+ children: [],
+ closingElement: null,
+ openingElement: JSXOpeningElement {
+ type: "JSXOpeningElement",
+ attributes: [
+ JSXAttribute {
+ type: "JSXAttribute",
+ name: JSXIdentifier {
+ type: "JSXIdentifier",
+ name: "foo",
+
+ range: [5, 8],
+ loc: {
+ start: { column: 5, line: 1 },
+ end: { column: 8, line: 1 },
+ },
+ },
+ value: JSXElement {
+ type: "JSXElement",
+ children: [
+ JSXText {
+ type: "JSXText",
+ raw: "bar",
+ value: "bar",
+
+ range: [14, 17],
+ loc: {
+ start: { column: 14, line: 1 },
+ end: { column: 17, line: 1 },
+ },
+ },
+ ],
+ closingElement: JSXClosingElement {
+ type: "JSXClosingElement",
+ name: JSXIdentifier {
+ type: "JSXIdentifier",
+ name: "div",
+
+ range: [19, 22],
+ loc: {
+ start: { column: 19, line: 1 },
+ end: { column: 22, line: 1 },
+ },
+ },
+
+ range: [17, 23],
+ loc: {
+ start: { column: 17, line: 1 },
+ end: { column: 23, line: 1 },
+ },
+ },
+ openingElement: JSXOpeningElement {
+ type: "JSXOpeningElement",
+ attributes: [],
+ name: JSXIdentifier {
+ type: "JSXIdentifier",
+ name: "div",
+
+ range: [10, 13],
+ loc: {
+ start: { column: 10, line: 1 },
+ end: { column: 13, line: 1 },
+ },
+ },
+ selfClosing: false,
+
+ range: [9, 14],
+ loc: {
+ start: { column: 9, line: 1 },
+ end: { column: 14, line: 1 },
+ },
+ },
+
+ range: [9, 23],
+ loc: {
+ start: { column: 9, line: 1 },
+ end: { column: 23, line: 1 },
+ },
+ },
+
+ range: [5, 23],
+ loc: {
+ start: { column: 5, line: 1 },
+ end: { column: 23, line: 1 },
+ },
+ },
+ ],
+ name: JSXIdentifier {
+ type: "JSXIdentifier",
+ name: "App",
+
+ range: [1, 4],
+ loc: {
+ start: { column: 1, line: 1 },
+ end: { column: 4, line: 1 },
+ },
+ },
+ selfClosing: true,
+
+ range: [0, 26],
+ loc: {
+ start: { column: 0, line: 1 },
+ end: { column: 26, line: 1 },
+ },
+ },
+
+ range: [0, 26],
+ loc: {
+ start: { column: 0, line: 1 },
+ end: { column: 26, line: 1 },
+ },
+ },
+
+ range: [0, 27],
+ loc: {
+ start: { column: 0, line: 1 },
+ end: { column: 27, line: 1 },
+ },
+ },
+ ],
+ sourceType: "script",
+
+ range: [0, 28],
+ loc: {
+ start: { column: 0, line: 1 },
+ end: { column: 0, line: 2 },
+ },
+}
+`;
diff --git a/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/snapshots/2-TSESTree-Tokens.shot b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/snapshots/2-TSESTree-Tokens.shot
new file mode 100644
index 000000000000..53e9b6e6968a
--- /dev/null
+++ b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/snapshots/2-TSESTree-Tokens.shot
@@ -0,0 +1,156 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AST Fixtures jsx JSXAttribute element-non-self-closing TSESTree - Tokens 1`] = `
+[
+ Punctuator {
+ type: "Punctuator",
+ value: "<",
+
+ range: [0, 1],
+ loc: {
+ start: { column: 0, line: 1 },
+ end: { column: 1, line: 1 },
+ },
+ },
+ JSXIdentifier {
+ type: "JSXIdentifier",
+ value: "App",
+
+ range: [1, 4],
+ loc: {
+ start: { column: 1, line: 1 },
+ end: { column: 4, line: 1 },
+ },
+ },
+ JSXIdentifier {
+ type: "JSXIdentifier",
+ value: "foo",
+
+ range: [5, 8],
+ loc: {
+ start: { column: 5, line: 1 },
+ end: { column: 8, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: "=",
+
+ range: [8, 9],
+ loc: {
+ start: { column: 8, line: 1 },
+ end: { column: 9, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: "<",
+
+ range: [9, 10],
+ loc: {
+ start: { column: 9, line: 1 },
+ end: { column: 10, line: 1 },
+ },
+ },
+ JSXIdentifier {
+ type: "JSXIdentifier",
+ value: "div",
+
+ range: [10, 13],
+ loc: {
+ start: { column: 10, line: 1 },
+ end: { column: 13, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: ">",
+
+ range: [13, 14],
+ loc: {
+ start: { column: 13, line: 1 },
+ end: { column: 14, line: 1 },
+ },
+ },
+ JSXText {
+ type: "JSXText",
+ value: "bar",
+
+ range: [14, 17],
+ loc: {
+ start: { column: 14, line: 1 },
+ end: { column: 17, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: "<",
+
+ range: [17, 18],
+ loc: {
+ start: { column: 17, line: 1 },
+ end: { column: 18, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: "/",
+
+ range: [18, 19],
+ loc: {
+ start: { column: 18, line: 1 },
+ end: { column: 19, line: 1 },
+ },
+ },
+ JSXIdentifier {
+ type: "JSXIdentifier",
+ value: "div",
+
+ range: [19, 22],
+ loc: {
+ start: { column: 19, line: 1 },
+ end: { column: 22, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: ">",
+
+ range: [22, 23],
+ loc: {
+ start: { column: 22, line: 1 },
+ end: { column: 23, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: "/",
+
+ range: [24, 25],
+ loc: {
+ start: { column: 24, line: 1 },
+ end: { column: 25, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: ">",
+
+ range: [25, 26],
+ loc: {
+ start: { column: 25, line: 1 },
+ end: { column: 26, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: ";",
+
+ range: [26, 27],
+ loc: {
+ start: { column: 26, line: 1 },
+ end: { column: 27, line: 1 },
+ },
+ },
+]
+`;
diff --git a/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/snapshots/3-Babel-AST.shot b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/snapshots/3-Babel-AST.shot
new file mode 100644
index 000000000000..a4e6e9336d9a
--- /dev/null
+++ b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/snapshots/3-Babel-AST.shot
@@ -0,0 +1,139 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AST Fixtures jsx JSXAttribute element-non-self-closing Babel - AST 1`] = `
+Program {
+ type: "Program",
+ body: [
+ ExpressionStatement {
+ type: "ExpressionStatement",
+ expression: JSXElement {
+ type: "JSXElement",
+ children: [],
+ closingElement: null,
+ openingElement: JSXOpeningElement {
+ type: "JSXOpeningElement",
+ attributes: [
+ JSXAttribute {
+ type: "JSXAttribute",
+ name: JSXIdentifier {
+ type: "JSXIdentifier",
+ name: "foo",
+
+ range: [5, 8],
+ loc: {
+ start: { column: 5, line: 1 },
+ end: { column: 8, line: 1 },
+ },
+ },
+ value: JSXElement {
+ type: "JSXElement",
+ children: [
+ JSXText {
+ type: "JSXText",
+ raw: "bar",
+ value: "bar",
+
+ range: [14, 17],
+ loc: {
+ start: { column: 14, line: 1 },
+ end: { column: 17, line: 1 },
+ },
+ },
+ ],
+ closingElement: JSXClosingElement {
+ type: "JSXClosingElement",
+ name: JSXIdentifier {
+ type: "JSXIdentifier",
+ name: "div",
+
+ range: [19, 22],
+ loc: {
+ start: { column: 19, line: 1 },
+ end: { column: 22, line: 1 },
+ },
+ },
+
+ range: [17, 23],
+ loc: {
+ start: { column: 17, line: 1 },
+ end: { column: 23, line: 1 },
+ },
+ },
+ openingElement: JSXOpeningElement {
+ type: "JSXOpeningElement",
+ attributes: [],
+ name: JSXIdentifier {
+ type: "JSXIdentifier",
+ name: "div",
+
+ range: [10, 13],
+ loc: {
+ start: { column: 10, line: 1 },
+ end: { column: 13, line: 1 },
+ },
+ },
+ selfClosing: false,
+
+ range: [9, 14],
+ loc: {
+ start: { column: 9, line: 1 },
+ end: { column: 14, line: 1 },
+ },
+ },
+
+ range: [9, 23],
+ loc: {
+ start: { column: 9, line: 1 },
+ end: { column: 23, line: 1 },
+ },
+ },
+
+ range: [5, 23],
+ loc: {
+ start: { column: 5, line: 1 },
+ end: { column: 23, line: 1 },
+ },
+ },
+ ],
+ name: JSXIdentifier {
+ type: "JSXIdentifier",
+ name: "App",
+
+ range: [1, 4],
+ loc: {
+ start: { column: 1, line: 1 },
+ end: { column: 4, line: 1 },
+ },
+ },
+ selfClosing: true,
+
+ range: [0, 26],
+ loc: {
+ start: { column: 0, line: 1 },
+ end: { column: 26, line: 1 },
+ },
+ },
+
+ range: [0, 26],
+ loc: {
+ start: { column: 0, line: 1 },
+ end: { column: 26, line: 1 },
+ },
+ },
+
+ range: [0, 27],
+ loc: {
+ start: { column: 0, line: 1 },
+ end: { column: 27, line: 1 },
+ },
+ },
+ ],
+ sourceType: "script",
+
+ range: [0, 28],
+ loc: {
+ start: { column: 0, line: 1 },
+ end: { column: 0, line: 2 },
+ },
+}
+`;
diff --git a/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/snapshots/4-Babel-Tokens.shot b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/snapshots/4-Babel-Tokens.shot
new file mode 100644
index 000000000000..01f9e5c53588
--- /dev/null
+++ b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/snapshots/4-Babel-Tokens.shot
@@ -0,0 +1,156 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AST Fixtures jsx JSXAttribute element-non-self-closing Babel - Tokens 1`] = `
+[
+ Punctuator {
+ type: "Punctuator",
+ value: "<",
+
+ range: [0, 1],
+ loc: {
+ start: { column: 0, line: 1 },
+ end: { column: 1, line: 1 },
+ },
+ },
+ JSXIdentifier {
+ type: "JSXIdentifier",
+ value: "App",
+
+ range: [1, 4],
+ loc: {
+ start: { column: 1, line: 1 },
+ end: { column: 4, line: 1 },
+ },
+ },
+ JSXIdentifier {
+ type: "JSXIdentifier",
+ value: "foo",
+
+ range: [5, 8],
+ loc: {
+ start: { column: 5, line: 1 },
+ end: { column: 8, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: "=",
+
+ range: [8, 9],
+ loc: {
+ start: { column: 8, line: 1 },
+ end: { column: 9, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: "<",
+
+ range: [9, 10],
+ loc: {
+ start: { column: 9, line: 1 },
+ end: { column: 10, line: 1 },
+ },
+ },
+ JSXIdentifier {
+ type: "JSXIdentifier",
+ value: "div",
+
+ range: [10, 13],
+ loc: {
+ start: { column: 10, line: 1 },
+ end: { column: 13, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: ">",
+
+ range: [13, 14],
+ loc: {
+ start: { column: 13, line: 1 },
+ end: { column: 14, line: 1 },
+ },
+ },
+ JSXText {
+ type: "JSXText",
+ value: "bar",
+
+ range: [14, 17],
+ loc: {
+ start: { column: 14, line: 1 },
+ end: { column: 17, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: "<",
+
+ range: [17, 18],
+ loc: {
+ start: { column: 17, line: 1 },
+ end: { column: 18, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: "/",
+
+ range: [18, 19],
+ loc: {
+ start: { column: 18, line: 1 },
+ end: { column: 19, line: 1 },
+ },
+ },
+ JSXIdentifier {
+ type: "JSXIdentifier",
+ value: "div",
+
+ range: [19, 22],
+ loc: {
+ start: { column: 19, line: 1 },
+ end: { column: 22, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: ">",
+
+ range: [22, 23],
+ loc: {
+ start: { column: 22, line: 1 },
+ end: { column: 23, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: "/",
+
+ range: [24, 25],
+ loc: {
+ start: { column: 24, line: 1 },
+ end: { column: 25, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: ">",
+
+ range: [25, 26],
+ loc: {
+ start: { column: 25, line: 1 },
+ end: { column: 26, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: ";",
+
+ range: [26, 27],
+ loc: {
+ start: { column: 26, line: 1 },
+ end: { column: 27, line: 1 },
+ },
+ },
+]
+`;
diff --git a/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/snapshots/5-AST-Alignment-AST.shot b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/snapshots/5-AST-Alignment-AST.shot
new file mode 100644
index 000000000000..de99bf49c756
--- /dev/null
+++ b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/snapshots/5-AST-Alignment-AST.shot
@@ -0,0 +1,6 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AST Fixtures jsx JSXAttribute element-non-self-closing AST Alignment - AST 1`] = `
+"Snapshot Diff:
+Compared values have no visual difference."
+`;
diff --git a/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/snapshots/6-AST-Alignment-Tokens.shot b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/snapshots/6-AST-Alignment-Tokens.shot
new file mode 100644
index 000000000000..3bd6a3615c1d
--- /dev/null
+++ b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-non-self-closing/snapshots/6-AST-Alignment-Tokens.shot
@@ -0,0 +1,6 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AST Fixtures jsx JSXAttribute element-non-self-closing AST Alignment - Token 1`] = `
+"Snapshot Diff:
+Compared values have no visual difference."
+`;
diff --git a/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-self-closing/fixture.tsx b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-self-closing/fixture.tsx
new file mode 100644
index 000000000000..5581b85c881c
--- /dev/null
+++ b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-self-closing/fixture.tsx
@@ -0,0 +1 @@
+ />;
diff --git a/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-self-closing/snapshots/1-TSESTree-AST.shot b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-self-closing/snapshots/1-TSESTree-AST.shot
new file mode 100644
index 000000000000..664985ec64e6
--- /dev/null
+++ b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-self-closing/snapshots/1-TSESTree-AST.shot
@@ -0,0 +1,109 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AST Fixtures jsx JSXAttribute element-self-closing TSESTree - AST 1`] = `
+Program {
+ type: "Program",
+ body: [
+ ExpressionStatement {
+ type: "ExpressionStatement",
+ expression: JSXElement {
+ type: "JSXElement",
+ children: [],
+ closingElement: null,
+ openingElement: JSXOpeningElement {
+ type: "JSXOpeningElement",
+ attributes: [
+ JSXAttribute {
+ type: "JSXAttribute",
+ name: JSXIdentifier {
+ type: "JSXIdentifier",
+ name: "foo",
+
+ range: [5, 8],
+ loc: {
+ start: { column: 5, line: 1 },
+ end: { column: 8, line: 1 },
+ },
+ },
+ value: JSXElement {
+ type: "JSXElement",
+ children: [],
+ closingElement: null,
+ openingElement: JSXOpeningElement {
+ type: "JSXOpeningElement",
+ attributes: [],
+ name: JSXIdentifier {
+ type: "JSXIdentifier",
+ name: "div",
+
+ range: [10, 13],
+ loc: {
+ start: { column: 10, line: 1 },
+ end: { column: 13, line: 1 },
+ },
+ },
+ selfClosing: true,
+
+ range: [9, 16],
+ loc: {
+ start: { column: 9, line: 1 },
+ end: { column: 16, line: 1 },
+ },
+ },
+
+ range: [9, 16],
+ loc: {
+ start: { column: 9, line: 1 },
+ end: { column: 16, line: 1 },
+ },
+ },
+
+ range: [5, 16],
+ loc: {
+ start: { column: 5, line: 1 },
+ end: { column: 16, line: 1 },
+ },
+ },
+ ],
+ name: JSXIdentifier {
+ type: "JSXIdentifier",
+ name: "App",
+
+ range: [1, 4],
+ loc: {
+ start: { column: 1, line: 1 },
+ end: { column: 4, line: 1 },
+ },
+ },
+ selfClosing: true,
+
+ range: [0, 19],
+ loc: {
+ start: { column: 0, line: 1 },
+ end: { column: 19, line: 1 },
+ },
+ },
+
+ range: [0, 19],
+ loc: {
+ start: { column: 0, line: 1 },
+ end: { column: 19, line: 1 },
+ },
+ },
+
+ range: [0, 20],
+ loc: {
+ start: { column: 0, line: 1 },
+ end: { column: 20, line: 1 },
+ },
+ },
+ ],
+ sourceType: "script",
+
+ range: [0, 21],
+ loc: {
+ start: { column: 0, line: 1 },
+ end: { column: 0, line: 2 },
+ },
+}
+`;
diff --git a/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-self-closing/snapshots/2-TSESTree-Tokens.shot b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-self-closing/snapshots/2-TSESTree-Tokens.shot
new file mode 100644
index 000000000000..a854372f0ef6
--- /dev/null
+++ b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-self-closing/snapshots/2-TSESTree-Tokens.shot
@@ -0,0 +1,116 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AST Fixtures jsx JSXAttribute element-self-closing TSESTree - Tokens 1`] = `
+[
+ Punctuator {
+ type: "Punctuator",
+ value: "<",
+
+ range: [0, 1],
+ loc: {
+ start: { column: 0, line: 1 },
+ end: { column: 1, line: 1 },
+ },
+ },
+ JSXIdentifier {
+ type: "JSXIdentifier",
+ value: "App",
+
+ range: [1, 4],
+ loc: {
+ start: { column: 1, line: 1 },
+ end: { column: 4, line: 1 },
+ },
+ },
+ JSXIdentifier {
+ type: "JSXIdentifier",
+ value: "foo",
+
+ range: [5, 8],
+ loc: {
+ start: { column: 5, line: 1 },
+ end: { column: 8, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: "=",
+
+ range: [8, 9],
+ loc: {
+ start: { column: 8, line: 1 },
+ end: { column: 9, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: "<",
+
+ range: [9, 10],
+ loc: {
+ start: { column: 9, line: 1 },
+ end: { column: 10, line: 1 },
+ },
+ },
+ JSXIdentifier {
+ type: "JSXIdentifier",
+ value: "div",
+
+ range: [10, 13],
+ loc: {
+ start: { column: 10, line: 1 },
+ end: { column: 13, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: "/",
+
+ range: [14, 15],
+ loc: {
+ start: { column: 14, line: 1 },
+ end: { column: 15, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: ">",
+
+ range: [15, 16],
+ loc: {
+ start: { column: 15, line: 1 },
+ end: { column: 16, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: "/",
+
+ range: [17, 18],
+ loc: {
+ start: { column: 17, line: 1 },
+ end: { column: 18, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: ">",
+
+ range: [18, 19],
+ loc: {
+ start: { column: 18, line: 1 },
+ end: { column: 19, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: ";",
+
+ range: [19, 20],
+ loc: {
+ start: { column: 19, line: 1 },
+ end: { column: 20, line: 1 },
+ },
+ },
+]
+`;
diff --git a/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-self-closing/snapshots/3-Babel-AST.shot b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-self-closing/snapshots/3-Babel-AST.shot
new file mode 100644
index 000000000000..505e346e0b1f
--- /dev/null
+++ b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-self-closing/snapshots/3-Babel-AST.shot
@@ -0,0 +1,109 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AST Fixtures jsx JSXAttribute element-self-closing Babel - AST 1`] = `
+Program {
+ type: "Program",
+ body: [
+ ExpressionStatement {
+ type: "ExpressionStatement",
+ expression: JSXElement {
+ type: "JSXElement",
+ children: [],
+ closingElement: null,
+ openingElement: JSXOpeningElement {
+ type: "JSXOpeningElement",
+ attributes: [
+ JSXAttribute {
+ type: "JSXAttribute",
+ name: JSXIdentifier {
+ type: "JSXIdentifier",
+ name: "foo",
+
+ range: [5, 8],
+ loc: {
+ start: { column: 5, line: 1 },
+ end: { column: 8, line: 1 },
+ },
+ },
+ value: JSXElement {
+ type: "JSXElement",
+ children: [],
+ closingElement: null,
+ openingElement: JSXOpeningElement {
+ type: "JSXOpeningElement",
+ attributes: [],
+ name: JSXIdentifier {
+ type: "JSXIdentifier",
+ name: "div",
+
+ range: [10, 13],
+ loc: {
+ start: { column: 10, line: 1 },
+ end: { column: 13, line: 1 },
+ },
+ },
+ selfClosing: true,
+
+ range: [9, 16],
+ loc: {
+ start: { column: 9, line: 1 },
+ end: { column: 16, line: 1 },
+ },
+ },
+
+ range: [9, 16],
+ loc: {
+ start: { column: 9, line: 1 },
+ end: { column: 16, line: 1 },
+ },
+ },
+
+ range: [5, 16],
+ loc: {
+ start: { column: 5, line: 1 },
+ end: { column: 16, line: 1 },
+ },
+ },
+ ],
+ name: JSXIdentifier {
+ type: "JSXIdentifier",
+ name: "App",
+
+ range: [1, 4],
+ loc: {
+ start: { column: 1, line: 1 },
+ end: { column: 4, line: 1 },
+ },
+ },
+ selfClosing: true,
+
+ range: [0, 19],
+ loc: {
+ start: { column: 0, line: 1 },
+ end: { column: 19, line: 1 },
+ },
+ },
+
+ range: [0, 19],
+ loc: {
+ start: { column: 0, line: 1 },
+ end: { column: 19, line: 1 },
+ },
+ },
+
+ range: [0, 20],
+ loc: {
+ start: { column: 0, line: 1 },
+ end: { column: 20, line: 1 },
+ },
+ },
+ ],
+ sourceType: "script",
+
+ range: [0, 21],
+ loc: {
+ start: { column: 0, line: 1 },
+ end: { column: 0, line: 2 },
+ },
+}
+`;
diff --git a/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-self-closing/snapshots/4-Babel-Tokens.shot b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-self-closing/snapshots/4-Babel-Tokens.shot
new file mode 100644
index 000000000000..5da3b4ac7cb5
--- /dev/null
+++ b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-self-closing/snapshots/4-Babel-Tokens.shot
@@ -0,0 +1,116 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AST Fixtures jsx JSXAttribute element-self-closing Babel - Tokens 1`] = `
+[
+ Punctuator {
+ type: "Punctuator",
+ value: "<",
+
+ range: [0, 1],
+ loc: {
+ start: { column: 0, line: 1 },
+ end: { column: 1, line: 1 },
+ },
+ },
+ JSXIdentifier {
+ type: "JSXIdentifier",
+ value: "App",
+
+ range: [1, 4],
+ loc: {
+ start: { column: 1, line: 1 },
+ end: { column: 4, line: 1 },
+ },
+ },
+ JSXIdentifier {
+ type: "JSXIdentifier",
+ value: "foo",
+
+ range: [5, 8],
+ loc: {
+ start: { column: 5, line: 1 },
+ end: { column: 8, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: "=",
+
+ range: [8, 9],
+ loc: {
+ start: { column: 8, line: 1 },
+ end: { column: 9, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: "<",
+
+ range: [9, 10],
+ loc: {
+ start: { column: 9, line: 1 },
+ end: { column: 10, line: 1 },
+ },
+ },
+ JSXIdentifier {
+ type: "JSXIdentifier",
+ value: "div",
+
+ range: [10, 13],
+ loc: {
+ start: { column: 10, line: 1 },
+ end: { column: 13, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: "/",
+
+ range: [14, 15],
+ loc: {
+ start: { column: 14, line: 1 },
+ end: { column: 15, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: ">",
+
+ range: [15, 16],
+ loc: {
+ start: { column: 15, line: 1 },
+ end: { column: 16, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: "/",
+
+ range: [17, 18],
+ loc: {
+ start: { column: 17, line: 1 },
+ end: { column: 18, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: ">",
+
+ range: [18, 19],
+ loc: {
+ start: { column: 18, line: 1 },
+ end: { column: 19, line: 1 },
+ },
+ },
+ Punctuator {
+ type: "Punctuator",
+ value: ";",
+
+ range: [19, 20],
+ loc: {
+ start: { column: 19, line: 1 },
+ end: { column: 20, line: 1 },
+ },
+ },
+]
+`;
diff --git a/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-self-closing/snapshots/5-AST-Alignment-AST.shot b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-self-closing/snapshots/5-AST-Alignment-AST.shot
new file mode 100644
index 000000000000..f2e3d006593a
--- /dev/null
+++ b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-self-closing/snapshots/5-AST-Alignment-AST.shot
@@ -0,0 +1,6 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AST Fixtures jsx JSXAttribute element-self-closing AST Alignment - AST 1`] = `
+"Snapshot Diff:
+Compared values have no visual difference."
+`;
diff --git a/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-self-closing/snapshots/6-AST-Alignment-Tokens.shot b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-self-closing/snapshots/6-AST-Alignment-Tokens.shot
new file mode 100644
index 000000000000..c18356864d71
--- /dev/null
+++ b/packages/ast-spec/src/jsx/JSXAttribute/fixtures/element-self-closing/snapshots/6-AST-Alignment-Tokens.shot
@@ -0,0 +1,6 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AST Fixtures jsx JSXAttribute element-self-closing AST Alignment - Token 1`] = `
+"Snapshot Diff:
+Compared values have no visual difference."
+`;
diff --git a/packages/ast-spec/src/jsx/JSXAttribute/spec.ts b/packages/ast-spec/src/jsx/JSXAttribute/spec.ts
index 8fc8364c05fd..c8e52b244578 100644
--- a/packages/ast-spec/src/jsx/JSXAttribute/spec.ts
+++ b/packages/ast-spec/src/jsx/JSXAttribute/spec.ts
@@ -1,5 +1,6 @@
import type { AST_NODE_TYPES } from '../../ast-node-types';
import type { BaseNode } from '../../base/BaseNode';
+import type { JSXElement } from '../../expression/JSXElement/spec';
import type { JSXExpression } from '../../unions/JSXExpression';
import type { Literal } from '../../unions/Literal';
import type { JSXIdentifier } from '../JSXIdentifier/spec';
@@ -8,5 +9,5 @@ import type { JSXNamespacedName } from '../JSXNamespacedName/spec';
export interface JSXAttribute extends BaseNode {
type: AST_NODE_TYPES.JSXAttribute;
name: JSXIdentifier | JSXNamespacedName;
- value: JSXExpression | Literal | null;
+ value: JSXElement | JSXExpression | Literal | null;
}
diff --git a/packages/ast-spec/tsconfig.json b/packages/ast-spec/tsconfig.json
index f1eefac4eb93..7303adfd8021 100644
--- a/packages/ast-spec/tsconfig.json
+++ b/packages/ast-spec/tsconfig.json
@@ -2,9 +2,9 @@
"extends": "./tsconfig.build.json",
"compilerOptions": {
"composite": false,
- "rootDir": "."
+ "rootDir": ".",
},
"include": ["src", "typings", "tests", "tools", "**/fixtures/**/config.ts"],
"exclude": ["**/fixtures/**/fixture.ts", "**/fixtures/**/fixture.tsx"],
- "references": [{ "path": "../typescript-estree/tsconfig.build.json" }]
+ "references": [{ "path": "../typescript-estree/tsconfig.build.json" }],
}
diff --git a/packages/eslint-plugin-internal/CHANGELOG.md b/packages/eslint-plugin-internal/CHANGELOG.md
index 9987d209069c..d9e542e69b5e 100644
--- a/packages/eslint-plugin-internal/CHANGELOG.md
+++ b/packages/eslint-plugin-internal/CHANGELOG.md
@@ -1,3 +1,23 @@
+## 6.21.0 (2024-02-05)
+
+
+### 🚀 Features
+
+- export plugin metadata
+
+- allow `parserOptions.project: false`
+
+
+### ❤️ Thank You
+
+- auvred
+- Brad Zacher
+- Kirk Waiblinger
+- Pete Gonzalez
+- YeonJuan
+
+You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.
+
## 6.20.0 (2024-01-29)
This was a version bump only for eslint-plugin-internal to align it with other projects, there were no code changes.
diff --git a/packages/eslint-plugin-internal/package.json b/packages/eslint-plugin-internal/package.json
index 06347f372c2c..89505dd00858 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": "6.20.0",
+ "version": "6.21.0",
"private": true,
"main": "dist/index.js",
"scripts": {
@@ -14,10 +14,10 @@
},
"dependencies": {
"@prettier/sync": "*",
- "@typescript-eslint/rule-tester": "6.20.0",
- "@typescript-eslint/scope-manager": "6.20.0",
- "@typescript-eslint/type-utils": "6.20.0",
- "@typescript-eslint/utils": "6.20.0",
+ "@typescript-eslint/rule-tester": "6.21.0",
+ "@typescript-eslint/scope-manager": "6.21.0",
+ "@typescript-eslint/type-utils": "6.21.0",
+ "@typescript-eslint/utils": "6.21.0",
"prettier": "^3.0.3"
},
"devDependencies": {
diff --git a/packages/eslint-plugin-internal/src/index.ts b/packages/eslint-plugin-internal/src/index.ts
index 0802acef98a8..f92eb0b8fb93 100644
--- a/packages/eslint-plugin-internal/src/index.ts
+++ b/packages/eslint-plugin-internal/src/index.ts
@@ -1,5 +1,17 @@
+import type { Linter } from '@typescript-eslint/utils/ts-eslint';
+
import rules from './rules';
+// note - cannot migrate this to an import statement because it will make TSC copy the package.json to the dist folder
+const { name, version } = require('../package.json') as {
+ name: string;
+ version: string;
+};
+
export = {
rules,
-};
+ meta: {
+ name,
+ version,
+ },
+} satisfies Linter.Plugin;
diff --git a/packages/eslint-plugin-internal/src/rules/index.ts b/packages/eslint-plugin-internal/src/rules/index.ts
index 17a0a192bf84..c1143e7a6f8d 100644
--- a/packages/eslint-plugin-internal/src/rules/index.ts
+++ b/packages/eslint-plugin-internal/src/rules/index.ts
@@ -1,3 +1,5 @@
+import type { Linter } from '@typescript-eslint/utils/ts-eslint';
+
import noPoorlyTypedTsProps from './no-poorly-typed-ts-props';
import noTypescriptDefaultImport from './no-typescript-default-import';
import noTypescriptEstreeImport from './no-typescript-estree-import';
@@ -10,4 +12,4 @@ export default {
'no-typescript-estree-import': noTypescriptEstreeImport,
'plugin-test-formatting': pluginTestFormatting,
'prefer-ast-types-enum': preferASTTypesEnum,
-};
+} satisfies Linter.PluginRules;
diff --git a/packages/eslint-plugin-internal/src/rules/no-typescript-default-import.ts b/packages/eslint-plugin-internal/src/rules/no-typescript-default-import.ts
index 8c4676a32ad9..8ee08569518a 100644
--- a/packages/eslint-plugin-internal/src/rules/no-typescript-default-import.ts
+++ b/packages/eslint-plugin-internal/src/rules/no-typescript-default-import.ts
@@ -34,6 +34,11 @@ export default createRule({
},
defaultOptions: [],
create(context) {
+ if (context.filename.endsWith('mts')) {
+ // mts files will import "properly" and so default import is correct
+ return {};
+ }
+
return {
'ImportDeclaration > ImportDefaultSpecifier'(
node: TSESTree.ImportDefaultSpecifier,
diff --git a/packages/eslint-plugin-internal/tests/fixtures/tsconfig.json b/packages/eslint-plugin-internal/tests/fixtures/tsconfig.json
index 7e9126b848c7..93bd2daed8ac 100644
--- a/packages/eslint-plugin-internal/tests/fixtures/tsconfig.json
+++ b/packages/eslint-plugin-internal/tests/fixtures/tsconfig.json
@@ -6,7 +6,7 @@
"strict": true,
"esModuleInterop": true,
"lib": ["es2015", "es2017", "esnext"],
- "experimentalDecorators": true
+ "experimentalDecorators": true,
},
- "include": ["file.ts"]
+ "include": ["file.ts"],
}
diff --git a/packages/eslint-plugin-internal/tsconfig.json b/packages/eslint-plugin-internal/tsconfig.json
index cc78ba59388e..e6b1a56b81a0 100644
--- a/packages/eslint-plugin-internal/tsconfig.json
+++ b/packages/eslint-plugin-internal/tsconfig.json
@@ -3,8 +3,8 @@
"compilerOptions": {
"composite": false,
"target": "ES2022",
- "rootDir": "."
+ "rootDir": ".",
},
"include": ["src", "typings", "tests"],
- "references": [{ "path": "../utils/tsconfig.build.json" }]
+ "references": [{ "path": "../utils/tsconfig.build.json" }],
}
diff --git a/packages/eslint-plugin-tslint/CHANGELOG.md b/packages/eslint-plugin-tslint/CHANGELOG.md
index 41595443e428..6f58bc0e72d2 100644
--- a/packages/eslint-plugin-tslint/CHANGELOG.md
+++ b/packages/eslint-plugin-tslint/CHANGELOG.md
@@ -1,3 +1,23 @@
+## 6.21.0 (2024-02-05)
+
+
+### 🚀 Features
+
+- export plugin metadata
+
+- allow `parserOptions.project: false`
+
+
+### ❤️ Thank You
+
+- auvred
+- Brad Zacher
+- Kirk Waiblinger
+- Pete Gonzalez
+- YeonJuan
+
+You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.
+
## 6.20.0 (2024-01-29)
This was a version bump only for eslint-plugin-tslint to align it with other projects, there were no code changes.
diff --git a/packages/eslint-plugin-tslint/package.json b/packages/eslint-plugin-tslint/package.json
index 24e236920088..ab3e3c3cfd83 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": "6.20.0",
+ "version": "6.21.0",
"main": "dist/index.js",
"typings": "src/index.ts",
"description": "ESLint plugin that wraps a TSLint configuration and lints the whole source using TSLint",
@@ -46,7 +46,7 @@
"typecheck": "tsc -p tsconfig.json --noEmit"
},
"dependencies": {
- "@typescript-eslint/utils": "6.20.0"
+ "@typescript-eslint/utils": "6.21.0"
},
"peerDependencies": {
"eslint": "^7.0.0 || ^8.0.0",
@@ -55,7 +55,7 @@
},
"devDependencies": {
"@types/lodash": "*",
- "@typescript-eslint/parser": "6.20.0",
+ "@typescript-eslint/parser": "6.21.0",
"jest": "29.7.0",
"prettier": "^3.0.3",
"rimraf": "*"
diff --git a/packages/eslint-plugin-tslint/src/index.ts b/packages/eslint-plugin-tslint/src/index.ts
index a638ae2ba566..bc64dc8b53f4 100644
--- a/packages/eslint-plugin-tslint/src/index.ts
+++ b/packages/eslint-plugin-tslint/src/index.ts
@@ -1,9 +1,22 @@
+import type { Linter } from '@typescript-eslint/utils/ts-eslint';
+
import configRule from './rules/config';
+// note - cannot migrate this to an import statement because it will make TSC copy the package.json to the dist folder
+const { name, version } = require('../package.json') as {
+ name: string;
+ version: string;
+};
+
+export const meta: Linter.PluginMeta = {
+ name,
+ version,
+};
+
/**
* Expose a single rule called "config", which will be accessed in the user's eslint config files
* via "tslint/config"
*/
-export const rules = {
+export const rules: Linter.PluginRules = {
config: configRule,
};
diff --git a/packages/eslint-plugin-tslint/tests/fixtures/test-project/tsconfig.json b/packages/eslint-plugin-tslint/tests/fixtures/test-project/tsconfig.json
index fcd054ab4880..e901e843b118 100644
--- a/packages/eslint-plugin-tslint/tests/fixtures/test-project/tsconfig.json
+++ b/packages/eslint-plugin-tslint/tests/fixtures/test-project/tsconfig.json
@@ -4,6 +4,6 @@
"module": "commonjs",
"strict": true,
"noUnusedLocals": true,
- "noImplicitAny": true
- }
+ "noImplicitAny": true,
+ },
}
diff --git a/packages/eslint-plugin-tslint/tsconfig.json b/packages/eslint-plugin-tslint/tsconfig.json
index 4ba17c6d60ab..c2b862690de9 100644
--- a/packages/eslint-plugin-tslint/tsconfig.json
+++ b/packages/eslint-plugin-tslint/tsconfig.json
@@ -2,9 +2,9 @@
"extends": "./tsconfig.build.json",
"compilerOptions": {
"composite": false,
- "rootDir": "."
+ "rootDir": ".",
},
"include": ["src", "tests"],
"exclude": ["tests/fixtures"],
- "references": [{ "path": "../utils/tsconfig.build.json" }]
+ "references": [{ "path": "../utils/tsconfig.build.json" }],
}
diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md
index 1dda2647a499..95eabb622a86 100644
--- a/packages/eslint-plugin/CHANGELOG.md
+++ b/packages/eslint-plugin/CHANGELOG.md
@@ -1,3 +1,40 @@
+## 6.21.0 (2024-02-05)
+
+
+### 🚀 Features
+
+- export plugin metadata
+
+- allow `parserOptions.project: false`
+
+- **eslint-plugin:** add rule prefer-find
+
+
+### 🩹 Fixes
+
+- **eslint-plugin:** [no-unused-vars] don't report on types referenced in export assignment expression
+
+- **eslint-plugin:** [switch-exhaustiveness-check] better support for intersections, infinite types, non-union values
+
+- **eslint-plugin:** [consistent-type-imports] dont report on types used in export assignment expressions
+
+- **eslint-plugin:** [no-unnecessary-condition] handle left-hand optional with exactOptionalPropertyTypes option
+
+- **eslint-plugin:** [class-literal-property-style] allow getter when same key setter exists
+
+- **eslint-plugin:** [no-unnecessary-type-assertion] provide valid fixes for assertions with extra tokens before `as` keyword
+
+
+### ❤️ Thank You
+
+- auvred
+- Brad Zacher
+- Kirk Waiblinger
+- Pete Gonzalez
+- YeonJuan
+
+You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.
+
## 6.20.0 (2024-01-29)
diff --git a/packages/eslint-plugin/docs/rules/ban-tslint-comment.md b/packages/eslint-plugin/docs/rules/ban-tslint-comment.md
index eac42f6cdabf..c2529de6179f 100644
--- a/packages/eslint-plugin/docs/rules/ban-tslint-comment.md
+++ b/packages/eslint-plugin/docs/rules/ban-tslint-comment.md
@@ -16,7 +16,7 @@ Useful when migrating from TSLint to ESLint. Once TSLint has been removed, this
### ❌ Incorrect
-```js
+```ts
/* tslint:disable */
/* tslint:enable */
/* tslint:disable:rule1 rule2 rule3... */
@@ -28,7 +28,7 @@ someCode(); // tslint:disable-line
### ✅ Correct
-```js
+```ts
// This is a comment that just happens to mention tslint
/* This is a multiline comment that just happens to mention tslint */
someCode(); // This is a comment that just happens to mention tslint
diff --git a/packages/eslint-plugin/docs/rules/ban-types.md b/packages/eslint-plugin/docs/rules/ban-types.md
index 818528451e09..0539fb2dd2d8 100644
--- a/packages/eslint-plugin/docs/rules/ban-types.md
+++ b/packages/eslint-plugin/docs/rules/ban-types.md
@@ -114,15 +114,15 @@ Example configuration:
// add a custom message, AND tell the plugin how to fix it
"OldAPI": {
"message": "Use NewAPI instead",
- "fixWith": "NewAPI"
+ "fixWith": "NewAPI",
},
// un-ban a type that's banned by default
- "{}": false
+ "{}": false,
},
- "extendDefaults": true
- }
- ]
+ "extendDefaults": true,
+ },
+ ],
}
```
diff --git a/packages/eslint-plugin/docs/rules/consistent-type-assertions.md b/packages/eslint-plugin/docs/rules/consistent-type-assertions.md
index b453e7201aa6..7bd4412470e5 100644
--- a/packages/eslint-plugin/docs/rules/consistent-type-assertions.md
+++ b/packages/eslint-plugin/docs/rules/consistent-type-assertions.md
@@ -54,22 +54,22 @@ Examples of code for `{ assertionStyle: 'as', objectLiteralTypeAssertions: 'neve
#### ❌ Incorrect
```ts option='{ "assertionStyle": "as", "objectLiteralTypeAssertions": "never" }'
-const x = { ... } as T;
+const x = { foo: 1 } as T;
-function foo() {
- return { ... } as T;
+function bar() {
+ return { foo: 1 } as T;
}
```
#### ✅ Correct
```ts option='{ "assertionStyle": "as", "objectLiteralTypeAssertions": "never" }'
-const x: T = { ... };
-const y = { ... } as any;
-const z = { ... } as unknown;
+const x: T = { foo: 1 };
+const y = { foo: 1 } as any;
+const z = { foo: 1 } as unknown;
-function foo(): T {
- return { ... };
+function bar(): T {
+ return { foo: 1 };
}
```
@@ -82,23 +82,25 @@ Examples of code for `{ assertionStyle: 'as', objectLiteralTypeAssertions: 'allo
#### ❌ Incorrect
```ts option='{ "assertionStyle": "as", "objectLiteralTypeAssertions": "allow-as-parameter" }'
-const x = { ... } as T;
+const x = { foo: 1 } as T;
-function foo() {
- return { ... } as T;
+function bar() {
+ return { foo: 1 } as T;
}
```
#### ✅ Correct
```tsx option='{ "assertionStyle": "as", "objectLiteralTypeAssertions": "allow-as-parameter" }'
-const x: T = { ... };
-const y = { ... } as any;
-const z = { ... } as unknown;
-foo({ ... } as T);
-new Clazz({ ... } as T);
-function foo() { throw { bar: 5 } as Foo }
-const foo = ;
+const x: T = { foo: 1 };
+const y = { foo: 1 } as any;
+const z = { foo: 1 } as unknown;
+bar({ foo: 1 } as T);
+new Clazz({ foo: 1 } as T);
+function bar() {
+ throw { foo: 1 } as Foo;
+}
+const foo = ;
```
diff --git a/packages/eslint-plugin/docs/rules/explicit-function-return-type.md b/packages/eslint-plugin/docs/rules/explicit-function-return-type.md
index ad6b5598e557..d33de3e02b0e 100644
--- a/packages/eslint-plugin/docs/rules/explicit-function-return-type.md
+++ b/packages/eslint-plugin/docs/rules/explicit-function-return-type.md
@@ -76,17 +76,17 @@ If you are working on a codebase within which you lint non-TypeScript code (i.e.
{
"rules": {
// disable the rule for all files
- "@typescript-eslint/explicit-function-return-type": "off"
+ "@typescript-eslint/explicit-function-return-type": "off",
},
"overrides": [
{
// enable the rule specifically for TypeScript files
"files": ["*.ts", "*.mts", "*.cts", "*.tsx"],
"rules": {
- "@typescript-eslint/explicit-function-return-type": "error"
- }
- }
- ]
+ "@typescript-eslint/explicit-function-return-type": "error",
+ },
+ },
+ ],
}
```
@@ -143,7 +143,7 @@ type FuncType = () => string;
let arrowFn: FuncType = () => 'test';
-let funcExpr: FuncType = function() {
+let funcExpr: FuncType = function () {
return 'test';
};
@@ -163,19 +163,15 @@ let objectPropCast = {
foo: () => 1,
};
-declare functionWithArg(arg: () => number);
+declare function functionWithArg(arg: () => number);
functionWithArg(() => 1);
-declare functionWithObjectArg(arg: { method: () => number });
+declare function functionWithObjectArg(arg: { method: () => number });
functionWithObjectArg({
method() {
return 1;
},
});
-
-const Comp: FC = () => {
- return