Skip to content

Commit

Permalink
fix(isolated-declarations): inferring of UnrayExpression incorrectly (#…
Browse files Browse the repository at this point in the history
…3920)

close: #3914
  • Loading branch information
Dunqing committed Jun 26, 2024
1 parent 3db2553 commit 59ce38b
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 6 deletions.
4 changes: 4 additions & 0 deletions crates/oxc_ast/src/ast_impl/js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ impl<'a> Expression<'a> {
matches!(self, Self::StringLiteral(_) | Self::TemplateLiteral(_))
}

pub fn is_number_literal(&self) -> bool {
matches!(self, Self::NumericLiteral(_) | Self::BigIntLiteral(_))
}

pub fn is_specific_string_literal(&self, string: &str) -> bool {
match self {
Self::StringLiteral(s) => s.value == string,
Expand Down
16 changes: 14 additions & 2 deletions crates/oxc_isolated_declarations/src/inferrer.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use oxc_allocator::Box;
use oxc_ast::ast::{
ArrowFunctionExpression, BindingPatternKind, Expression, FormalParameter, Function, Statement,
TSType, TSTypeAnnotation,
TSType, TSTypeAnnotation, UnaryExpression,
};
use oxc_span::{GetSpan, SPAN};

Expand All @@ -14,6 +14,10 @@ use crate::{
};

impl<'a> IsolatedDeclarations<'a> {
pub fn can_infer_unary_expression(expr: &UnaryExpression<'a>) -> bool {
expr.operator.is_arithmetic() && expr.argument.is_number_literal()
}

pub fn infer_type_from_expression(&self, expr: &Expression<'a>) -> Option<TSType<'a>> {
match expr {
Expression::BooleanLiteral(_) => Some(self.ast.ts_boolean_keyword(SPAN)),
Expand Down Expand Up @@ -66,6 +70,13 @@ impl<'a> IsolatedDeclarations<'a> {
self.infer_type_from_expression(&expr.expression)
}
Expression::TSTypeAssertion(expr) => Some(self.ast.copy(&expr.type_annotation)),
Expression::UnaryExpression(expr) => {
if Self::can_infer_unary_expression(expr) {
self.infer_type_from_expression(&expr.argument)
} else {
None
}
}
_ => None,
}
}
Expand Down Expand Up @@ -136,12 +147,13 @@ impl<'a> IsolatedDeclarations<'a> {
.map(|type_annotation| self.ast.ts_type_annotation(SPAN, type_annotation))
}

pub fn is_need_to_infer_type_from_expression(expr: &Expression) -> bool {
pub fn is_need_to_infer_type_from_expression(expr: &Expression<'a>) -> bool {
match expr {
Expression::NumericLiteral(_)
| Expression::BigIntLiteral(_)
| Expression::StringLiteral(_) => false,
Expression::TemplateLiteral(lit) => !lit.expressions.is_empty(),
Expression::UnaryExpression(expr) => !Self::can_infer_unary_expression(expr),
_ => true,
}
}
Expand Down
13 changes: 10 additions & 3 deletions crates/oxc_isolated_declarations/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,16 @@ impl<'a> IsolatedDeclarations<'a> {
Expression::TemplateLiteral(lit) => self
.transform_template_to_string(lit)
.map(|string| self.ast.ts_literal_type(lit.span, TSLiteral::StringLiteral(string))),
Expression::UnaryExpression(expr) => Some(
self.ast.ts_literal_type(SPAN, TSLiteral::UnaryExpression(self.ast.copy(expr))),
),
Expression::UnaryExpression(expr) => {
if Self::can_infer_unary_expression(expr) {
Some(
self.ast
.ts_literal_type(SPAN, TSLiteral::UnaryExpression(self.ast.copy(expr))),
)
} else {
None
}
}
Expression::ArrayExpression(expr) => {
Some(self.transform_array_expression_to_ts_type(expr, true))
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
// Correct

// ParenthesizedExpression
const n = (0);
const s = ("");
const t = (``);
const b = (true);
const b = (true);

// UnaryExpression
let unaryA = +12;
const unaryB = -1_2n;

// Incorrect

// UnaryExpression
const unaryC = +"str"
const unaryD = typeof "str"
const unaryE = {E: -"str"} as const
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,36 @@ declare const n: number;
declare const s: string;
declare const t: string;
declare const b: boolean;
declare let unaryA: number;
declare const unaryB = -1_2n;
declare const unaryC: unknown;
declare const unaryD: unknown;
declare const unaryE: {};


==================== Errors ====================

x TS9010: Variable must have an explicit type annotation with
| --isolatedDeclarations.
,-[16:7]
15 | // UnaryExpression
16 | const unaryC = +"str"
: ^^^^^^
17 | const unaryD = typeof "str"
`----
x TS9010: Variable must have an explicit type annotation with
| --isolatedDeclarations.
,-[17:7]
16 | const unaryC = +"str"
17 | const unaryD = typeof "str"
: ^^^^^^
18 | const unaryE = {E: -"str"} as const
`----

x TS9013: Expression type can't be inferred with --isolatedDeclarations.
,-[18:20]
17 | const unaryD = typeof "str"
18 | const unaryE = {E: -"str"} as const
: ^^^^^^
`----

0 comments on commit 59ce38b

Please sign in to comment.