Skip to content

Commit e83627a

Browse files
committed
chore: remove babel
1 parent 10f24cc commit e83627a

File tree

4 files changed

+95
-105
lines changed

4 files changed

+95
-105
lines changed

packages/vscode-wdio-worker/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@
2424
"clean": "shx rm -rf out dist coverage"
2525
},
2626
"dependencies": {
27-
"@babel/parser": "^7.27.0",
28-
"@babel/types": "^7.27.0",
27+
"@babel/parser": "^7.27.5",
2928
"@cucumber/gherkin": "^32.1.0",
3029
"@cucumber/messages": "^27.2.0",
3130
"@vscode-wdio/constants": "workspace:*",

packages/vscode-wdio-worker/src/config.ts

Lines changed: 71 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2,72 +2,93 @@ import fs from 'node:fs/promises'
22
import path from 'node:path'
33
import { pathToFileURL } from 'node:url'
44

5-
import * as parser from '@babel/parser'
6-
import * as t from '@babel/types'
7-
import recast from 'recast'
5+
import { parse, print, visit, types as t } from 'recast'
6+
// @ts-ignore
7+
import typescriptParser from 'recast/parsers/typescript'
88

99
const reporterIdentifierName = 'VscodeJsonReporter'
1010

1111
// This file is bundle as parser/ats.js at the package of vscode-webdriverio
1212
// So, the correct reporter path is parent directory
1313
const VSCODE_REPORTER_PATH = path.resolve(__dirname, '../reporter.cjs')
14+
15+
/**
16+
* Create AST nodes using ast-types builders
17+
*/
18+
const b = t.builders
19+
1420
/**
1521
* Since Windows cannot import by reporter file path due to issues with
1622
* the `initializePlugin` method of wdio-utils, the policy is to create a temporary configuration file.
1723
*/
1824
export async function createTempConfigFile(filename: string, outDir: string) {
1925
const source = await fs.readFile(filename, { encoding: 'utf8' })
20-
const ast = recast.parse(source, {
21-
parser: {
22-
parse(source: string) {
23-
return parser.parse(source, {
24-
sourceType: 'unambiguous',
25-
plugins: ['typescript', 'jsx', 'topLevelAwait'],
26-
})
27-
},
28-
},
26+
const ast = parse(source, {
27+
parser: typescriptParser,
2928
})
3029

31-
const reporterIdentifier = t.identifier(reporterIdentifierName)
32-
const reporterConfigIdentifier = t.identifier(`${reporterIdentifierName}.default || ${reporterIdentifierName}`)
33-
const reporterElement = t.arrayExpression([
30+
const reporterIdentifier = b.identifier(reporterIdentifierName)
31+
const reporterConfigIdentifier = b.identifier(`${reporterIdentifierName}.default || ${reporterIdentifierName}`)
32+
const reporterElement = b.arrayExpression([
3433
reporterConfigIdentifier,
35-
t.objectExpression([
36-
t.objectProperty(t.identifier('stdout'), t.booleanLiteral(true)),
37-
t.objectProperty(t.identifier('outputDir'), t.stringLiteral(outDir)),
34+
b.objectExpression([
35+
b.property('init', b.identifier('stdout'), b.literal(true)),
36+
b.property('init', b.identifier('outputDir'), b.literal(outDir)),
3837
]),
3938
])
4039
let hasReporterImport = false
4140

42-
function addOrUpdateReporters(configObject: t.Node) {
43-
if (!t.isObjectExpression(configObject)) {
41+
function addOrUpdateReporters(configObject: any) {
42+
if (!t.namedTypes.ObjectExpression.check(configObject)) {
4443
return
4544
}
4645

47-
const reportersProp = configObject.properties.find(
48-
(prop) =>
49-
t.isObjectProperty(prop) &&
50-
((t.isIdentifier(prop.key) && prop.key.name === 'reporters') ||
51-
(t.isStringLiteral(prop.key) && prop.key.value === 'reporters'))
52-
)
46+
// Find existing reporters property
47+
let reportersProp = null
48+
49+
for (let i = 0; i < configObject.properties.length; i++) {
50+
const prop = configObject.properties[i]
51+
52+
// Check for both Property and ObjectProperty nodes
53+
if (t.namedTypes.Property.check(prop) || t.namedTypes.ObjectProperty?.check?.(prop)) {
54+
const isReportersKey =
55+
(t.namedTypes.Identifier.check(prop.key) && prop.key.name === 'reporters') ||
56+
(t.namedTypes.Literal.check(prop.key) && prop.key.value === 'reporters')
57+
58+
if (isReportersKey) {
59+
reportersProp = prop
60+
break
61+
}
62+
}
63+
}
5364

54-
if (reportersProp && t.isObjectProperty(reportersProp) && t.isArrayExpression(reportersProp.value)) {
65+
if (reportersProp && t.namedTypes.ArrayExpression.check(reportersProp.value)) {
66+
// Add to existing reporters array
5567
reportersProp.value.elements.push(reporterElement)
68+
} else if (reportersProp) {
69+
// Replace existing non-array reporters with array including existing value
70+
const existingValue = reportersProp.value
71+
//@ts-ignore
72+
reportersProp.value = b.arrayExpression([existingValue, reporterElement])
5673
} else {
74+
// Add new reporters property
5775
configObject.properties.push(
58-
t.objectProperty(t.identifier('reporters'), t.arrayExpression([reporterElement]))
76+
b.property('init', b.identifier('reporters'), b.arrayExpression([reporterElement]))
5977
)
6078
}
6179
}
6280

63-
recast.types.visit(ast, {
81+
visit(ast, {
6482
visitImportDeclaration(path) {
6583
const { source, specifiers } = path.node
6684
if (
6785
source.value === pathToFileURL(VSCODE_REPORTER_PATH).href &&
6886
specifiers &&
6987
//@ts-ignore
70-
specifiers.some((s) => t.isImportDefaultSpecifier(s) && s.local.name === reporterIdentifierName)
88+
specifiers.some(
89+
//@ts-ignore
90+
(s: any) => t.namedTypes.ImportDefaultSpecifier.check(s) && s.local.name === reporterIdentifierName
91+
)
7192
) {
7293
hasReporterImport = true
7394
}
@@ -77,21 +98,20 @@ export async function createTempConfigFile(filename: string, outDir: string) {
7798
visitExportNamedDeclaration(path) {
7899
const decl = path.node.declaration
79100

80-
// @ts-ignore
81-
if (t.isVariableDeclaration(decl)) {
101+
if (t.namedTypes.VariableDeclaration.check(decl)) {
82102
const first = decl.declarations[0]
83103

84-
if (t.isVariableDeclarator(first)) {
104+
if (t.namedTypes.VariableDeclarator.check(first)) {
85105
const id = first.id
86106
const init = first.init
87107

88-
if (t.isIdentifier(id) && id.name === 'config') {
89-
if (t.isObjectExpression(init)) {
108+
if (t.namedTypes.Identifier.check(id) && id.name === 'config') {
109+
if (t.namedTypes.ObjectExpression.check(init)) {
90110
addOrUpdateReporters(init)
91111
} else if (
92-
t.isCallExpression(init) &&
112+
t.namedTypes.CallExpression.check(init) &&
93113
init.arguments.length > 0 &&
94-
t.isObjectExpression(init.arguments[0])
114+
t.namedTypes.ObjectExpression.check(init.arguments[0])
95115
) {
96116
const configObject = init.arguments[0]
97117
addOrUpdateReporters(configObject)
@@ -111,12 +131,10 @@ export async function createTempConfigFile(filename: string, outDir: string) {
111131
}
112132

113133
if (
114-
// @ts-ignore
115-
t.isMemberExpression(left) &&
116-
t.isIdentifier(left.object) &&
117-
t.isIdentifier(left.property) &&
118-
// @ts-ignore
119-
t.isObjectExpression(right)
134+
t.namedTypes.MemberExpression.check(left) &&
135+
t.namedTypes.Identifier.check(left.object) &&
136+
t.namedTypes.Identifier.check(left.property) &&
137+
t.namedTypes.ObjectExpression.check(right)
120138
) {
121139
const leftName = `${left.object.name}.${left.property.name}`
122140
if (['module.exports', 'exports.config'].includes(leftName)) {
@@ -128,13 +146,15 @@ export async function createTempConfigFile(filename: string, outDir: string) {
128146
},
129147

130148
visitCallExpression(path) {
131-
const node = path.node as t.Node
149+
const node = path.node
132150

133151
if (
134-
t.isCallExpression(node) &&
135-
t.isIdentifier(node.callee, { name: 'require' }) &&
152+
t.namedTypes.CallExpression.check(node) &&
153+
t.namedTypes.Identifier.check(node.callee) &&
154+
node.callee.name === 'require' &&
136155
node.arguments.length === 1 &&
137-
t.isStringLiteral(node.arguments[0]) &&
156+
t.namedTypes.Literal.check(node.arguments[0]) &&
157+
typeof node.arguments[0].value === 'string' &&
138158
node.arguments[0].value === pathToFileURL(VSCODE_REPORTER_PATH).href
139159
) {
140160
hasReporterImport = true
@@ -145,15 +165,15 @@ export async function createTempConfigFile(filename: string, outDir: string) {
145165
})
146166

147167
if (!hasReporterImport) {
148-
const importedModule = t.importDeclaration(
149-
[t.importDefaultSpecifier(reporterIdentifier)],
150-
t.stringLiteral(pathToFileURL(VSCODE_REPORTER_PATH).href)
168+
const importedModule = b.importDeclaration(
169+
[b.importDefaultSpecifier(reporterIdentifier)],
170+
b.literal(pathToFileURL(VSCODE_REPORTER_PATH).href)
151171
)
152172

153173
ast.program.body.unshift(importedModule)
154174
}
155175

156-
const output = recast.print(ast).code
176+
const output = print(ast).code
157177
const ext = path.extname(filename)
158178
const _filename = path.join(path.dirname(filename), `wdio-vscode-${new Date().getTime()}${ext}`)
159179
await fs.writeFile(_filename, output)

packages/vscode-wdio-worker/src/parsers/js.ts

Lines changed: 22 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import * as babelParser from '@babel/parser'
2-
import * as t from '@babel/types'
3-
import { parse, types } from 'recast'
1+
import { parse, visit, types as t } from 'recast'
2+
// @ts-ignore
3+
import typescriptParser from 'recast/parsers/typescript'
44
import type { TestData, SourceRange, WorkerMetaContext } from '@vscode-wdio/types/worker'
55

66
/**
7-
* Parse WebdriverIO test files and extract test cases using Recast and Babel parser
7+
* Parse WebdriverIO test files and extract test cases using Recast with TypeScript parser
88
*
99
* @param fileContent Content of the test file
1010
* @param uri File URI for error reporting
@@ -20,35 +20,9 @@ export function parseTestCases(this: WorkerMetaContext, fileContent: string, uri
2020
const testBlocksMap = new Map<string, TestData>()
2121

2222
try {
23-
// Parse the file content with Recast and Babel parser to handle TypeScript
23+
// Parse the file content with Recast TypeScript parser
2424
const ast = parse(fileContent, {
25-
parser: {
26-
parse: (source: string) => {
27-
try {
28-
return babelParser.parse(source, {
29-
sourceType: 'module',
30-
plugins: [
31-
'typescript',
32-
'jsx',
33-
'decorators-legacy',
34-
'classProperties',
35-
'exportDefaultFrom',
36-
'exportNamespaceFrom',
37-
'dynamicImport',
38-
'objectRestSpread',
39-
'optionalChaining',
40-
'nullishCoalescingOperator',
41-
],
42-
tokens: true,
43-
ranges: true,
44-
})
45-
} catch (parseError) {
46-
// Provide more detailed error information
47-
const errorMessage = (parseError as Error).message
48-
throw new Error(`Babel parser error: ${errorMessage}`)
49-
}
50-
},
51-
},
25+
parser: typescriptParser,
5226
})
5327

5428
// Process the AST to extract test blocks
@@ -65,15 +39,14 @@ export function parseTestCases(this: WorkerMetaContext, fileContent: string, uri
6539
* @param ast The parsed AST
6640
* @param testCases Array to store top-level test cases
6741
* @param testBlocksMap Map to track all test blocks for hierarchy building
68-
* @param fileContent Original file content for line calculations
6942
*/
7043
function processAst(ast: any, testCases: TestData[], testBlocksMap: Map<string, TestData>): void {
7144
// Stack to track current describe block context
7245
const blockStack: TestData[] = []
7346
const blockIdSet = new Set<string>()
7447

75-
// Traverse the AST
76-
types.visit(ast, {
48+
// Traverse the AST using recast's visit function
49+
visit(ast, {
7750
// Visit call expressions to find describe, it, and test blocks
7851
visitCallExpression(path) {
7952
const node = path.node
@@ -125,13 +98,14 @@ function processAst(ast: any, testCases: TestData[], testBlocksMap: Map<string,
12598
if (callbackArg) {
12699
// Handle both regular and async functions
127100
if (
128-
t.isArrowFunctionExpression(callbackArg as t.Node) ||
129-
t.isFunctionExpression(callbackArg as t.Node)
101+
t.namedTypes.ArrowFunctionExpression.check(callbackArg) ||
102+
t.namedTypes.FunctionExpression.check(callbackArg)
130103
) {
131-
const body = (callbackArg as t.ArrowFunctionExpression | t.FunctionExpression).body
104+
// @ts-ignore
105+
const body = callbackArg.body
132106

133107
// For arrow functions with expression body, we don't traverse
134-
if (t.isBlockStatement(body)) {
108+
if (t.namedTypes.BlockStatement.check(body)) {
135109
// For block statements, traverse the body
136110
this.traverse(path.get('arguments', 1))
137111
}
@@ -190,14 +164,14 @@ function createSourceRangeFromLocation(loc: any): SourceRange {
190164
*/
191165
function isTestBlockCall(node: any): boolean {
192166
// Direct call (describe, it, test)
193-
if (t.isIdentifier(node.callee) && ['describe', 'it', 'test'].includes(node.callee.name)) {
167+
if (t.namedTypes.Identifier.check(node.callee) && ['describe', 'it', 'test'].includes(node.callee.name)) {
194168
return true
195169
}
196170

197171
// Method chain call (describe.skip, it.only, etc.)
198172
if (
199-
t.isMemberExpression(node.callee) &&
200-
t.isIdentifier(node.callee.object) &&
173+
t.namedTypes.MemberExpression.check(node.callee) &&
174+
t.namedTypes.Identifier.check(node.callee.object) &&
201175
['describe', 'it', 'test'].includes(node.callee.object.name)
202176
) {
203177
return true
@@ -215,7 +189,7 @@ function isTestBlockCall(node: any): boolean {
215189
*/
216190
function getTestBlockType(node: any): 'describe' | 'it' | 'test' | null {
217191
// Direct call
218-
if (t.isIdentifier(node.callee)) {
192+
if (t.namedTypes.Identifier.check(node.callee)) {
219193
if (node.callee.name === 'describe') {
220194
return 'describe'
221195
}
@@ -225,7 +199,7 @@ function getTestBlockType(node: any): 'describe' | 'it' | 'test' | null {
225199
if (node.callee.name === 'test') {
226200
return 'test'
227201
}
228-
} else if (t.isMemberExpression(node.callee) && t.isIdentifier(node.callee.object)) {
202+
} else if (t.namedTypes.MemberExpression.check(node.callee) && t.namedTypes.Identifier.check(node.callee.object)) {
229203
// Method chain call (e.g., describe.skip, it.only)
230204

231205
if (node.callee.object.name === 'describe') {
@@ -255,17 +229,17 @@ function extractTestName(node: any): string | null {
255229
}
256230

257231
// String literal
258-
if (t.isStringLiteral(node)) {
232+
if (t.namedTypes.Literal.check(node) && typeof node.value === 'string') {
259233
return node.value
260234
}
261235

262236
// Template literal
263-
if (t.isTemplateLiteral(node)) {
264-
return node.quasis.map((q) => q.value.cooked).join('${...}')
237+
if (t.namedTypes.TemplateLiteral.check(node)) {
238+
return node.quasis.map((q: any) => q.value.cooked).join('${...}')
265239
}
266240

267241
// Binary expression (string concatenation)
268-
if (t.isBinaryExpression(node) && node.operator === '+') {
242+
if (t.namedTypes.BinaryExpression.check(node) && node.operator === '+') {
269243
const left = extractTestName(node.left)
270244
const right = extractTestName(node.right)
271245

pnpm-lock.yaml

Lines changed: 1 addition & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)