diff --git a/apps/oxlint/src-js/generated/deserialize.js b/apps/oxlint/src-js/generated/deserialize.js index 16b6397a5d8e7..35be31eb2d812 100644 --- a/apps/oxlint/src-js/generated/deserialize.js +++ b/apps/oxlint/src-js/generated/deserialize.js @@ -58,7 +58,6 @@ function deserializeProgram(pos) { type: "Program", body: null, sourceType: deserializeModuleKind(pos + 137), - hashbang: null, get comments() { comments === null && initComments(); return comments; @@ -71,9 +70,8 @@ function deserializeProgram(pos) { end, range: [0, end], parent: null, - }); - program.hashbang = deserializeOptionHashbang(pos + 48); - let body = (program.body = deserializeVecDirective(pos + 80)); + }), + body = (program.body = deserializeVecDirective(pos + 80)); body.push(...deserializeVecStatement(pos + 104)); { let start; @@ -1506,19 +1504,6 @@ function deserializeDirective(pos) { return node; } -function deserializeHashbang(pos) { - let start, end; - return { - __proto__: NodeProto, - type: "Hashbang", - value: deserializeStr(pos + 8), - start: (start = deserializeU32(pos)), - end: (end = deserializeU32(pos + 4)), - range: [start, end], - parent, - }; -} - function deserializeBlockStatement(pos) { let start, end, @@ -5904,11 +5889,6 @@ function deserializeStr(pos) { return out; } -function deserializeOptionHashbang(pos) { - if (uint32[(pos + 8) >> 2] === 0 && uint32[(pos + 12) >> 2] === 0) return null; - return deserializeHashbang(pos); -} - function deserializeVecDirective(pos) { let arr = [], pos32 = pos >> 2; diff --git a/apps/oxlint/src-js/generated/types.d.ts b/apps/oxlint/src-js/generated/types.d.ts index 6f036ba1fa0f8..b2a61fdb8f615 100644 --- a/apps/oxlint/src-js/generated/types.d.ts +++ b/apps/oxlint/src-js/generated/types.d.ts @@ -11,7 +11,6 @@ export interface Program extends Span { type: "Program"; body: Array; sourceType: ModuleKind; - hashbang: Hashbang | null; comments: Comment[]; tokens: Token[]; parent: null; diff --git a/apps/oxlint/test/fixtures/sourceCode/plugin.ts b/apps/oxlint/test/fixtures/sourceCode/plugin.ts index 53e4c27a4d9f2..9df2d701efa3f 100644 --- a/apps/oxlint/test/fixtures/sourceCode/plugin.ts +++ b/apps/oxlint/test/fixtures/sourceCode/plugin.ts @@ -39,6 +39,9 @@ const createRule: Rule = { const { id } = stmt.declarations[0]; assert.strictEqual(id.type, "Identifier"); + // Check AST has no `hashbang` property + assert.strictEqual("hashbang" in ast, false); + context.report({ message: "create:\n" + diff --git a/crates/oxc_ast/src/serialize/mod.rs b/crates/oxc_ast/src/serialize/mod.rs index 168300e37cf32..d8c1f17d862a9 100644 --- a/crates/oxc_ast/src/serialize/mod.rs +++ b/crates/oxc_ast/src/serialize/mod.rs @@ -128,7 +128,9 @@ impl Program<'_> { type: 'Program', body: null, sourceType: DESER[ModuleKind](POS_OFFSET.source_type.module_kind), + /* IF !LINTER */ hashbang: null, + /* END_IF */ /* IF LINTER */ get comments() { if (comments === null) initComments(); @@ -145,7 +147,7 @@ impl Program<'_> { ...(PARENT && { parent: null }), }; - program.hashbang = DESER[Option](POS_OFFSET.hashbang); + if (!LINTER) program.hashbang = DESER[Option](POS_OFFSET.hashbang); const body = program.body = DESER[Vec](POS_OFFSET.directives); body.push(...DESER[Vec](POS_OFFSET.body)); diff --git a/tasks/ast_tools/src/generators/typescript.rs b/tasks/ast_tools/src/generators/typescript.rs index 8436420d52ef1..c8c587a8e07e5 100644 --- a/tasks/ast_tools/src/generators/typescript.rs +++ b/tasks/ast_tools/src/generators/typescript.rs @@ -477,13 +477,14 @@ fn amend_oxlint_types(code: &str) -> String { } } - let mut code = SPAN_REGEX.replace(code, SpanReplacer).into_owned(); - - // Add `comments` and `tokens` fields to `Program` - #[expect(clippy::items_after_statements)] - const HASHBANG_FIELD: &str = "hashbang: Hashbang | null;"; - let index = code.find(HASHBANG_FIELD).unwrap(); - code.insert_str(index + HASHBANG_FIELD.len(), "comments: Comment[]; tokens: Token[];"); + let code = SPAN_REGEX.replace(code, SpanReplacer).into_owned(); + + // Replace `hashbang` field in `Program` with `comments` and `tokens` fields + let old_len = code.len(); + #[expect(clippy::disallowed_methods, reason = "always results in replacement")] + let code = + code.replacen("hashbang: Hashbang | null;", "comments: Comment[]; tokens: Token[];", 1); + assert!(code.len() != old_len); // Check replacement was made // Make `parent` fields non-optional #[expect(clippy::disallowed_methods)]