11import path from "node:path" ;
22import { parseForESLint } from "../lib/index.cjs" ;
3+ import unpad from "dedent" ;
34import { ESLint } from "eslint" ;
45import { itDummy , commonJS , IS_BABEL_8 } from "$repo-utils" ;
56
@@ -20,6 +21,36 @@ const PROPS_TO_REMOVE = [
2021 { key : "attributes" , type : "ImportExpression" } ,
2122] ;
2223
24+ // TODO: remove the ESLint token fixes after they are fixed in upstream
25+ function fixTSESLintTokens ( ast ) {
26+ const { tokens } = ast ;
27+ for ( let i = 0 ; i < tokens . length ; i ++ ) {
28+ const token = tokens [ i ] ;
29+ const { type, value } = token ;
30+ switch ( type ) {
31+ case "Identifier" :
32+ {
33+ if ( value . match ( / ^ \d .* n $ / ) ) {
34+ token . type = "Numeric" ;
35+ } else if ( value . match ( / ^ # / ) ) {
36+ token . type = "PrivateIdentifier" ;
37+ token . value = value . slice ( 1 ) ;
38+ }
39+ }
40+ break ;
41+ case "Keyword" :
42+ {
43+ if ( value === "null" ) {
44+ token . type = "Null" ;
45+ }
46+ }
47+ break ;
48+ default :
49+ break ;
50+ }
51+ }
52+ }
53+
2354function deeplyRemoveProperties ( obj , props ) {
2455 for ( const [ k , v ] of Object . entries ( obj ) ) {
2556 if (
@@ -72,6 +103,7 @@ function deeplyRemoveProperties(obj, props) {
72103 } ;
73104
74105 function parseAndAssertSame ( code , babelEcmaFeatures = null ) {
106+ code = unpad ( code ) ;
75107 const tsEstreeAST = tsEstree . parse ( code , tsEstreeOptions ) ;
76108 const babelAST = parseForESLint ( code , {
77109 eslintVisitorKeys : true ,
@@ -81,12 +113,19 @@ function deeplyRemoveProperties(obj, props) {
81113 babelOptions : {
82114 configFile : false ,
83115 parserOpts : {
84- plugins : [ "jsx" , "typescript" ] ,
116+ plugins : [
117+ "decorators" ,
118+ "decoratorAutoAccessors" ,
119+ "explicitResourceManagement" ,
120+ "jsx" ,
121+ "typescript" ,
122+ ] ,
85123 } ,
86124 } ,
87125 } ) . ast ;
88126
89127 deeplyRemoveProperties ( babelAST , PROPS_TO_REMOVE ) ;
128+ fixTSESLintTokens ( tsEstreeAST ) ;
90129 expect ( babelAST ) . toEqual ( tsEstreeAST ) ;
91130 }
92131
@@ -108,16 +147,36 @@ function deeplyRemoveProperties(obj, props) {
108147 [ "boolean" , "true" ] ,
109148 [ "boolean" , "false" ] ,
110149 [ "numeric" , "0" ] ,
111- // ["bigint", "0n"],
150+ [ "bigint" , "0n" ] ,
112151 [ "string" , `"string"` ] ,
113152 [ "regexp without flag" , `/foo/;` ] ,
114153 [ "regexp u flag" , `/foo/dgimsuy;` ] ,
115154 [ "regexp v flag" , `/foo/dgimsvy;` ] ,
116155 [ "identifier" , "i" ] ,
117156
157+ [ "null" , "null" ] ,
158+
159+ [
160+ "template with braces" ,
161+ `
162+ { \`\${foo} \${bar}\` }
163+ ` ,
164+ ] ,
165+
166+ [ "directive" , `"use strict";` ] ,
167+
168+ // https://github.com/typescript-eslint/typescript-eslint/issues/11026
169+ // ["empty program with line comment", "// single comment"],
170+ // ["empty program with block comment", " /* multiline\n * comment\n*/"],
171+
118172 [ "logical NOT" , `!0` ] ,
119173 [ "bitwise NOT" , `~0` ] ,
120174
175+ [ "nullish coalescing" , "a ?? b" ] ,
176+
177+ [ "yield expression" , "function *f() { yield; yield* f; yield f }" ] ,
178+ [ "await expression" , "async function f() { await f() }" ] ,
179+
121180 [ "function declaration" , "function f(p) {}" ] ,
122181 [ "function expression" , "0, function f(p) {}" ] ,
123182 [ "arrow function expression" , "() => {}" ] ,
@@ -131,49 +190,64 @@ function deeplyRemoveProperties(obj, props) {
131190 [ "class method" , "class C { m() {} }" ] ,
132191 [ "class property" , "class C { p; }" ] ,
133192 [ "class static block" , "class C { static {}; }" ] ,
193+ [ "class accessor" , "class C { accessor a = 0 }" ] ,
194+ [ "class decorators" , "@dec class C { @dec static p; @dec accessor a; }" ] ,
134195
135196 [ "variable declaration" , "var a = 0" ] ,
136197 [
137198 "variable declaration destructuring" ,
138199 "var [{ a: x = 0 }, ...b] = [{ a: 0 }]" ,
139200 ] ,
140- // pending cloneIdentifier support
141- // ["variable declaration destructuring shorthand", "let { a = 0 } = { a: 0 }"]
201+ [
202+ "variable declaration destructuring shorthand" ,
203+ "var { a = 0 } = { a: 0 }" ,
204+ ] ,
205+ [ "let declaration" , "let a = 0" ] ,
206+ [ "const declaration" , "const a = 0" ] ,
207+ [ "using declaration" , "{ using a = 0 }" ] ,
208+ [ "await using declaration" , "async () => { await using a = 0 }" ] ,
142209
143210 [ "assignment expression" , "x = 1" ] ,
144- // pending toAssignable support
145- // ["assignment expression destructuring", "[{ a: x = 0 }, ...b] = [{ a: 0 }]"],
211+ [
212+ "assignment expression destructuring" ,
213+ "[{ a: x = 0 }, ...b] = [{ a: 0 }]" ,
214+ ] ,
215+
216+ [ "spread element" , "var a = { b, ...[...c] }" ] ,
146217
147218 [ "async call expression" , "async ([ x ])" ] ,
148219
149220 [ "import declaration" , `import "foo"` ] ,
150221 [ "import declaration default" , `import foo from "foo"` ] ,
151- // pending cloneIdentifier support
152- // ["import declaration named", `import { foo } from "foo"`]
222+ [ "import declaration named" , `import { foo } from "foo"` ] ,
153223 [ "import declaration named as" , `import { foo as bar } from "foo"` ] ,
154224 [
155225 "import declaration with attributes" ,
156226 `import foo from "./foo.json" with { type: "json" }` ,
157227 ] ,
158228
159- // pending cloneIdentifier support
160- // ["export declaration", `const foo = 0;export { foo }`],
229+ [ "export declaration" , `const foo = 0;export { foo }` ] ,
161230 [ "export declaration as" , `const foo = 0;export { foo as bar }` ] ,
231+ [ "export const declaration" , `export const foo = 0` ] ,
232+ [ "export declaration from" , `export { foo } from "foo"` ] ,
162233 [ "export function declaration" , `export function foo() {}` ] ,
163234 [ "export class declaration" , `export class foo {}` ] ,
164235
165236 [ "member expression" , `foo.bar` ] ,
237+ [ "optional member expression" , `foo?.bar` ] ,
166238 [ "call expression" , `foo(bar)` ] ,
239+ [ "optional call expression" , `foo?.(bar)` ] ,
167240 [ "new expression" , `new foo` ] ,
241+
242+ [ "logical assignment" , "x ??= y ||= z &&= x" ] ,
168243 ] ) ( "%s: %s" , ( _ , input ) => {
169244 parseAndAssertSame ( input ) ;
170245 } ) ;
171246
172247 if ( IS_BABEL_8 ( ) ) {
173248 it . each ( [
174- // ["class private method", "class C { #m() {} }"],
249+ [ "class private method" , "class C { #m() {} }" ] ,
175250 [ "class abstract property" , "abstract class C { abstract p; }" ] ,
176- // ["class abstract private property", "abstract class C { abstract #p; }"]
177251 [ "class abstract method" , "abstract class C { abstract m(): void }" ] ,
178252 ] ) ( "%s: %s" , ( _ , input ) => {
179253 parseAndAssertSame ( input ) ;
0 commit comments