Skip to content

Commit

Permalink
feat(parser): apply preserveParens to TSParenthesizedType (#9653)
Browse files Browse the repository at this point in the history
closes #9616
  • Loading branch information
Boshen committed Mar 10, 2025
1 parent c174600 commit 638007b
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 10 deletions.
7 changes: 4 additions & 3 deletions crates/oxc_parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,15 +199,16 @@ pub struct ParseOptions {
/// [`return`]: oxc_ast::ast::ReturnStatement
pub allow_return_outside_function: bool,

/// Emit [`ParenthesizedExpression`]s in AST.
/// Emit [`ParenthesizedExpression`]s and [`TSParenthesizedType`] in AST.
///
/// If this option is `true`, parenthesized expressions are represented by
/// (non-standard) [`ParenthesizedExpression`] nodes that have a single `expression` property
/// containing the expression inside parentheses.
/// (non-standard) [`ParenthesizedExpression`] and [`TSParenthesizedType`] nodes
/// that have a single `expression` property containing the expression inside parentheses.
///
/// Default: `true`
///
/// [`ParenthesizedExpression`]: oxc_ast::ast::ParenthesizedExpression
/// [`TSParenthesizedType`]: oxc_ast::ast::TSParenthesizedType
pub preserve_parens: bool,

/// Allow V8 runtime calls in the AST.
Expand Down
6 changes: 5 additions & 1 deletion crates/oxc_parser/src/ts/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -936,7 +936,11 @@ impl<'a> ParserImpl<'a> {
self.bump_any(); // bump `(`
let ty = self.parse_ts_type()?;
self.expect(Kind::RParen)?;
Ok(self.ast.ts_type_parenthesized_type(self.end_span(span), ty))
Ok(if self.options.preserve_parens {
self.ast.ts_type_parenthesized_type(self.end_span(span), ty)
} else {
ty
})
}

fn parse_literal_type_node(&mut self, negative: bool) -> Result<TSType<'a>> {
Expand Down
6 changes: 3 additions & 3 deletions napi/parser/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,11 @@ export interface ParserOptions {
*/
astType?: 'js' | 'ts'
/**
* Emit `ParenthesizedExpression` in AST.
* Emit `ParenthesizedExpression` and `TSParenthesizedType` in AST.
*
* If this option is true, parenthesized expressions are represented by
* (non-standard) `ParenthesizedExpression` nodes that have a single `expression` property
* containing the expression inside parentheses.
* (non-standard) `ParenthesizedExpression` and `TSParenthesizedType` nodes that
* have a single `expression` property containing the expression inside parentheses.
*
* @default true
*/
Expand Down
6 changes: 3 additions & 3 deletions napi/parser/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ pub struct ParserOptions {
#[napi(ts_type = "'js' | 'ts'")]
pub ast_type: Option<String>,

/// Emit `ParenthesizedExpression` in AST.
/// Emit `ParenthesizedExpression` and `TSParenthesizedType` in AST.
///
/// If this option is true, parenthesized expressions are represented by
/// (non-standard) `ParenthesizedExpression` nodes that have a single `expression` property
/// containing the expression inside parentheses.
/// (non-standard) `ParenthesizedExpression` and `TSParenthesizedType` nodes that
/// have a single `expression` property containing the expression inside parentheses.
///
/// @default true
pub preserve_parens: Option<bool>,
Expand Down
20 changes: 20 additions & 0 deletions napi/parser/test/parse.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Worker } from 'node:worker_threads';
import { describe, expect, it } from 'vitest';

import { parseAsync, parseSync } from '../index.js';
import type { ExpressionStatement, TSTypeAliasDeclaration } from '../index.js';

describe('parse', () => {
const code = '/* comment */ foo';
Expand Down Expand Up @@ -244,6 +245,25 @@ describe('parse', () => {
});
});
});

describe('preserveParens', () => {
it('should include parens when true', () => {
let ret = parseSync('test.js', '(x)');
expect((ret.program.body[0] as ExpressionStatement).expression.type).toBe('ParenthesizedExpression');

ret = parseSync('test.ts', 'type Foo = (x)');
expect((ret.program.body[0] as TSTypeAliasDeclaration).typeAnnotation.type).toBe('TSParenthesizedType');
});

it('should omit parens when false', () => {
const options = { preserveParens: false };
let ret = parseSync('test.js', '(x)', options);
expect((ret.program.body[0] as ExpressionStatement).expression.type).toBe('Identifier');

ret = parseSync('test.ts', 'type Foo = (x)', options);
expect((ret.program.body[0] as TSTypeAliasDeclaration).typeAnnotation.type).toBe('TSTypeReference');
});
});
});

describe('UTF-16 span', () => {
Expand Down

0 comments on commit 638007b

Please sign in to comment.