diff --git a/crates/oxc_isolated_declarations/src/declaration.rs b/crates/oxc_isolated_declarations/src/declaration.rs index 0224aef395723..8d675b27865b0 100644 --- a/crates/oxc_isolated_declarations/src/declaration.rs +++ b/crates/oxc_isolated_declarations/src/declaration.rs @@ -2,13 +2,13 @@ use oxc_allocator::Box; #[allow(clippy::wildcard_imports)] use oxc_ast::ast::*; use oxc_ast::{syntax_directed_operations::BoundNames, Visit}; -use oxc_diagnostics::OxcDiagnostic; use oxc_span::{GetSpan, SPAN}; use oxc_syntax::scope::ScopeFlags; use crate::{ diagnostics::{ binding_element_export, inferred_type_of_expression, signature_computed_property_name, + variable_must_have_explicit_type, }, IsolatedDeclarations, }; @@ -82,10 +82,7 @@ impl<'a> IsolatedDeclarations<'a> { if init.is_none() && binding_type.is_none() { binding_type = Some(self.ast.ts_unknown_keyword(SPAN)); if !decl.init.as_ref().is_some_and(Expression::is_function) { - self.error( - OxcDiagnostic::error("Variable must have an explicit type annotation with --isolatedDeclarations.") - .with_label(decl.id.span()), - ); + self.error(variable_must_have_explicit_type(decl.id.span())); } } } diff --git a/crates/oxc_isolated_declarations/src/diagnostics.rs b/crates/oxc_isolated_declarations/src/diagnostics.rs index 4b763b09f485b..7e17b2907832b 100644 --- a/crates/oxc_isolated_declarations/src/diagnostics.rs +++ b/crates/oxc_isolated_declarations/src/diagnostics.rs @@ -1,102 +1,141 @@ use oxc_diagnostics::OxcDiagnostic; use oxc_span::{Atom, Span}; -pub fn method_must_have_explicit_return_type(span: Span) -> OxcDiagnostic { +pub fn function_must_have_explicit_return_type(span: Span) -> OxcDiagnostic { OxcDiagnostic::error( - "Method must have an explicit return type annotation with --isolatedDeclarations.", + "TS9007: Function must have an explicit return type annotation with --isolatedDeclarations.", ) .with_label(span) } -pub fn function_must_have_explicit_return_type(span: Span) -> OxcDiagnostic { +pub fn method_must_have_explicit_return_type(span: Span) -> OxcDiagnostic { OxcDiagnostic::error( - "Function must have an explicit return type annotation with --isolatedDeclarations.", + "TS9008: Method must have an explicit return type annotation with --isolatedDeclarations.", ) .with_label(span) } pub fn accessor_must_have_explicit_return_type(span: Span) -> OxcDiagnostic { OxcDiagnostic::error( - "At least one accessor must have an explicit return type annotation with --isolatedDeclarations.", + "TS9009: At least one accessor must have an explicit return type annotation with --isolatedDeclarations.", ) .with_label(span) } -pub fn property_must_have_explicit_type(span: Span) -> OxcDiagnostic { +pub fn variable_must_have_explicit_type(span: Span) -> OxcDiagnostic { OxcDiagnostic::error( - "Property must have an explicit type annotation with --isolatedDeclarations.", + "TS9010: Variable must have an explicit type annotation with --isolatedDeclarations.", ) .with_label(span) } -pub fn type_containing_private_name(name: &Atom<'_>, span: Span) -> OxcDiagnostic { - OxcDiagnostic::error(format!( - "Type containing private name '{name}' can't be used with --isolatedDeclarations." - )) +pub fn parameter_must_have_explicit_type(span: Span) -> OxcDiagnostic { + OxcDiagnostic::error( + "TS9011: Parameter must have an explicit type annotation with --isolatedDeclarations.", + ) .with_label(span) } -pub fn computed_property_name(span: Span) -> OxcDiagnostic { - OxcDiagnostic::error("Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.") +pub fn property_must_have_explicit_type(span: Span) -> OxcDiagnostic { + OxcDiagnostic::error( + "TS9012: Property must have an explicit type annotation with --isolatedDeclarations.", + ) + .with_label(span) +} + +pub fn inferred_type_of_expression(span: Span) -> OxcDiagnostic { + OxcDiagnostic::error("TS9013: Expression type can't be inferred with --isolatedDeclarations.") .with_label(span) } pub fn signature_computed_property_name(span: Span) -> OxcDiagnostic { - OxcDiagnostic::error("Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations.") + OxcDiagnostic::error("TS9014: Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations.") .with_label(span) } -pub fn enum_member_initializers(span: Span) -> OxcDiagnostic { - OxcDiagnostic::error("Enum member initializers must be computable without references to external symbols with --isolatedDeclarations.") - .with_label(span) +pub fn object_with_spread_assignments(span: Span) -> OxcDiagnostic { + OxcDiagnostic::error( + "TS9015: Objects that contain spread assignments can't be inferred with --isolatedDeclarations.", + ) + .with_label(span) } -pub fn extends_clause_expression(span: Span) -> OxcDiagnostic { - OxcDiagnostic::error("Extends clause can't contain an expression with --isolatedDeclarations.") - .with_label(span) +pub fn shorthand_property(span: Span) -> OxcDiagnostic { + OxcDiagnostic::error( + "TS9016: Objects that contain shorthand properties can't be inferred with --isolatedDeclarations.", + ) + .with_label(span) } -pub fn default_export_inferred(span: Span) -> OxcDiagnostic { - OxcDiagnostic::error("Default exports can't be inferred with --isolatedDeclarations.") +pub fn array_inferred(span: Span) -> OxcDiagnostic { + OxcDiagnostic::error("TS9017: Only const arrays can be inferred with --isolatedDeclarations.") .with_label(span) } -pub fn array_inferred(span: Span) -> OxcDiagnostic { - OxcDiagnostic::error("Arrays can't be inferred with --isolatedDeclarations.").with_label(span) +pub fn arrays_with_spread_elements(span: Span) -> OxcDiagnostic { + OxcDiagnostic::error( + "TS9018: Arrays with spread elements can't inferred with --isolatedDeclarations.", + ) + .with_label(span) } -pub fn shorthand_property(span: Span) -> OxcDiagnostic { +pub fn binding_element_export(span: Span) -> OxcDiagnostic { OxcDiagnostic::error( - "Objects that contain shorthand properties can't be inferred with --isolatedDeclarations.", + "TS9019: Binding elements can't be exported directly with --isolatedDeclarations.", ) .with_label(span) } -pub fn inferred_type_of_expression(span: Span) -> OxcDiagnostic { - OxcDiagnostic::error("Expression type can't be inferred with --isolatedDeclarations.") +pub fn enum_member_initializers(span: Span) -> OxcDiagnostic { + OxcDiagnostic::error("TS9020: Enum member initializers must be computable without references to external symbols with --isolatedDeclarations.") .with_label(span) } -pub fn inferred_type_of_class_expression(span: Span) -> OxcDiagnostic { - OxcDiagnostic::error("Class expression type can't be inferred with --isolatedDeclarations.") - .with_label(span) +pub fn extends_clause_expression(span: Span) -> OxcDiagnostic { + OxcDiagnostic::error( + "TS9021: Extends clause can't contain an expression with --isolatedDeclarations.", + ) + .with_label(span) } -pub fn parameter_must_have_explicit_type(span: Span) -> OxcDiagnostic { +pub fn inferred_type_of_class_expression(span: Span) -> OxcDiagnostic { OxcDiagnostic::error( - "Parameter must have an explicit type annotation with --isolatedDeclarations.", + "TS9022: Inference from class expressions is not supported with --isolatedDeclarations.", ) .with_label(span) } pub fn implicitly_adding_undefined_to_type(span: Span) -> OxcDiagnostic { OxcDiagnostic::error( - "Declaration emit for this parameter requires implicitly adding undefined to it's type. This is not supported with --isolatedDeclarations.", + "TS9025: Declaration emit for this parameter requires implicitly adding undefined to it's type. This is not supported with --isolatedDeclarations.", ) .with_label(span) } -pub fn binding_element_export(span: Span) -> OxcDiagnostic { - OxcDiagnostic::error("Binding elements can't be exported directly with --isolatedDeclarations.") +#[allow(dead_code)] +pub fn function_with_assigning_properties(span: Span) -> OxcDiagnostic { + OxcDiagnostic::error( + "TS9023: Assigning properties to functions without declaring them is not supported with --isolatedDeclarations. Add an explicit declaration for the properties assigned to this function.", + ) + .with_label(span) +} + +// TS9026: Declaration emit for this file requires preserving this import for augmentations. This is not supported with --isolatedDeclarations. +// This error requires cross-file checking, which we cannot support. + +pub fn default_export_inferred(span: Span) -> OxcDiagnostic { + OxcDiagnostic::error("TS9037: Default exports can't be inferred with --isolatedDeclarations.") + .with_label(span) +} + +pub fn computed_property_name(span: Span) -> OxcDiagnostic { + OxcDiagnostic::error("TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.") .with_label(span) } + +pub fn type_containing_private_name(name: &Atom<'_>, span: Span) -> OxcDiagnostic { + OxcDiagnostic::error(format!( + "TS9039: Type containing private name '{name}' can't be used with --isolatedDeclarations." + )) + .with_label(span) +} diff --git a/crates/oxc_isolated_declarations/src/inferrer.rs b/crates/oxc_isolated_declarations/src/inferrer.rs index fc6b9d4a72fc0..7d7cba7e39ae3 100644 --- a/crates/oxc_isolated_declarations/src/inferrer.rs +++ b/crates/oxc_isolated_declarations/src/inferrer.rs @@ -3,11 +3,12 @@ use oxc_ast::ast::{ ArrowFunctionExpression, BindingPatternKind, Expression, FormalParameter, Function, Statement, TSType, TSTypeAnnotation, }; -use oxc_diagnostics::OxcDiagnostic; use oxc_span::{GetSpan, SPAN}; use crate::{ - diagnostics::{array_inferred, inferred_type_of_class_expression}, + diagnostics::{ + array_inferred, inferred_type_of_class_expression, parameter_must_have_explicit_type, + }, return_type::FunctionReturnType, IsolatedDeclarations, }; @@ -79,10 +80,7 @@ impl<'a> IsolatedDeclarations<'a> { } else { if let Expression::TSAsExpression(expr) = &pattern.right { if !expr.type_annotation.is_keyword_or_literal() { - self.error( - OxcDiagnostic::error("Parameter must have an explicit type annotation with --isolatedDeclarations.") - .with_label(expr.type_annotation.span()) - ); + self.error(parameter_must_have_explicit_type(expr.type_annotation.span())); } } diff --git a/crates/oxc_isolated_declarations/src/types.rs b/crates/oxc_isolated_declarations/src/types.rs index f57630ac53e9f..c2b03417394b0 100644 --- a/crates/oxc_isolated_declarations/src/types.rs +++ b/crates/oxc_isolated_declarations/src/types.rs @@ -3,12 +3,12 @@ use oxc_ast::ast::{ ObjectExpression, ObjectPropertyKind, TSLiteral, TSMethodSignatureKind, TSTupleElement, TSType, TSTypeOperatorOperator, }; -use oxc_diagnostics::OxcDiagnostic; use oxc_span::{GetSpan, Span, SPAN}; use crate::{ diagnostics::{ - function_must_have_explicit_return_type, inferred_type_of_expression, shorthand_property, + arrays_with_spread_elements, function_must_have_explicit_return_type, + inferred_type_of_expression, object_with_spread_assignments, shorthand_property, }, function::get_function_span, IsolatedDeclarations, @@ -78,60 +78,61 @@ impl<'a> IsolatedDeclarations<'a> { is_const: bool, ) -> TSType<'a> { let members = - self.ast.new_vec_from_iter(expr.properties.iter().filter_map(|property| match property { - ObjectPropertyKind::ObjectProperty(object) => { - if self.report_property_key(&object.key, object.computed) { - return None; - } - - if object.shorthand { - self.error(shorthand_property(object.span)); - return None; - } - - if let Expression::FunctionExpression(function) = &object.value { - if !is_const && object.method { - let return_type = self.infer_function_return_type(function); - let params = self.transform_formal_parameters(&function.params); - return Some(self.ast.ts_method_signature( + self.ast.new_vec_from_iter(expr.properties.iter().filter_map( + |property| match property { + ObjectPropertyKind::ObjectProperty(object) => { + if self.report_property_key(&object.key, object.computed) { + return None; + } + + if object.shorthand { + self.error(shorthand_property(object.span)); + return None; + } + + if let Expression::FunctionExpression(function) = &object.value { + if !is_const && object.method { + let return_type = self.infer_function_return_type(function); + let params = self.transform_formal_parameters(&function.params); + return Some(self.ast.ts_method_signature( + object.span, + self.ast.copy(&object.key), + object.computed, + false, + TSMethodSignatureKind::Method, + self.ast.copy(&function.this_param), + params, + return_type, + self.ast.copy(&function.type_parameters), + )); + } + } + + let type_annotation = self.infer_type_from_expression(&object.value); + + if type_annotation.is_none() { + self.error(inferred_type_of_expression(object.value.span())); + return None; + } + + let property_signature = self.ast.ts_property_signature( object.span, - self.ast.copy(&object.key), - object.computed, false, - TSMethodSignatureKind::Method, - self.ast.copy(&function.this_param), - params, - return_type, - self.ast.copy(&function.type_parameters), - )); + false, + is_const, + self.ast.copy(&object.key), + type_annotation.map(|type_annotation| { + self.ast.ts_type_annotation(SPAN, type_annotation) + }), + ); + Some(property_signature) } - } - - let type_annotation = self.infer_type_from_expression(&object.value); - - if type_annotation.is_none() { - self.error(inferred_type_of_expression(object.value.span())); - return None; - } - - let property_signature = self.ast.ts_property_signature( - object.span, - false, - false, - is_const, - self.ast.copy(&object.key), - type_annotation - .map(|type_annotation| self.ast.ts_type_annotation(SPAN, type_annotation)), - ); - Some(property_signature) - }, - ObjectPropertyKind::SpreadProperty(spread) => { - self.error(OxcDiagnostic::error( - "Objects that contain spread assignments can't be inferred with --isolatedDeclarations.", - ).with_label(spread.span)); - None - } - })); + ObjectPropertyKind::SpreadProperty(spread) => { + self.error(object_with_spread_assignments(spread.span)); + None + } + }, + )); self.ast.ts_type_literal(SPAN, members) } @@ -141,21 +142,17 @@ impl<'a> IsolatedDeclarations<'a> { is_const: bool, ) -> TSType<'a> { let element_types = - self.ast.new_vec_from_iter(expr.elements.iter().filter_map(|element| { - match element { - ArrayExpressionElement::SpreadElement(spread) => { - self.error(OxcDiagnostic::error( - "Arrays with spread elements can't inferred with --isolatedDeclarations.", - ).with_label(spread.span)); - None - }, - ArrayExpressionElement::Elision(elision) => { - Some(TSTupleElement::from(self.ast.ts_undefined_keyword(elision.span))) - }, - _ => { - Some(TSTupleElement::from(self.transform_expression_to_ts_type(element.to_expression()))) - } + self.ast.new_vec_from_iter(expr.elements.iter().filter_map(|element| match element { + ArrayExpressionElement::SpreadElement(spread) => { + self.error(arrays_with_spread_elements(spread.span)); + None + } + ArrayExpressionElement::Elision(elision) => { + Some(TSTupleElement::from(self.ast.ts_undefined_keyword(elision.span))) } + _ => Some(TSTupleElement::from( + self.transform_expression_to_ts_type(element.to_expression()), + )), })); let ts_type = self.ast.ts_tuple_type(SPAN, element_types); diff --git a/crates/oxc_isolated_declarations/tests/snapshots/arrow-function-return-type.snap b/crates/oxc_isolated_declarations/tests/snapshots/arrow-function-return-type.snap index 4d2e4433f8e39..1949cf59f2a59 100644 --- a/crates/oxc_isolated_declarations/tests/snapshots/arrow-function-return-type.snap +++ b/crates/oxc_isolated_declarations/tests/snapshots/arrow-function-return-type.snap @@ -11,7 +11,7 @@ declare const C: unknown; ==================== Errors ==================== - x Function must have an explicit return type annotation with + x TS9007: Function must have an explicit return type annotation with | --isolatedDeclarations. ,-[2:10] 1 | function A() { @@ -20,7 +20,7 @@ declare const C: unknown; 3 | return C; `---- - x Function must have an explicit return type annotation with + x TS9007: Function must have an explicit return type annotation with | --isolatedDeclarations. ,-[7:11] 6 | @@ -29,7 +29,7 @@ declare const C: unknown; 8 | `---- - x Function must have an explicit return type annotation with + x TS9007: Function must have an explicit return type annotation with | --isolatedDeclarations. ,-[9:20] 8 | diff --git a/crates/oxc_isolated_declarations/tests/snapshots/function-parameters.snap b/crates/oxc_isolated_declarations/tests/snapshots/function-parameters.snap index 8049fdd996d31..aae53ee93da73 100644 --- a/crates/oxc_isolated_declarations/tests/snapshots/function-parameters.snap +++ b/crates/oxc_isolated_declarations/tests/snapshots/function-parameters.snap @@ -13,8 +13,8 @@ export declare function fnDeclBad3(p: T, rParam?: T, r2: T): void; ==================== Errors ==================== - x Declaration emit for this parameter requires implicitly adding undefined - | to it's type. This is not supported with --isolatedDeclarations. + x TS9025: Declaration emit for this parameter requires implicitly adding + | undefined to it's type. This is not supported with --isolatedDeclarations. ,-[6:30] 5 | // Incorrect 6 | export function fnDeclBad(p: T = [], rParam: T = "", r2: T): void { } @@ -22,8 +22,8 @@ export declare function fnDeclBad3(p: T, rParam?: T, r2: T): void; 7 | export function fnDeclBad2(p: T = [], r2: T): void { } `---- - x Declaration emit for this parameter requires implicitly adding undefined - | to it's type. This is not supported with --isolatedDeclarations. + x TS9025: Declaration emit for this parameter requires implicitly adding + | undefined to it's type. This is not supported with --isolatedDeclarations. ,-[6:41] 5 | // Incorrect 6 | export function fnDeclBad(p: T = [], rParam: T = "", r2: T): void { } @@ -31,8 +31,8 @@ export declare function fnDeclBad3(p: T, rParam?: T, r2: T): void; 7 | export function fnDeclBad2(p: T = [], r2: T): void { } `---- - x Declaration emit for this parameter requires implicitly adding undefined - | to it's type. This is not supported with --isolatedDeclarations. + x TS9025: Declaration emit for this parameter requires implicitly adding + | undefined to it's type. This is not supported with --isolatedDeclarations. ,-[7:31] 6 | export function fnDeclBad(p: T = [], rParam: T = "", r2: T): void { } 7 | export function fnDeclBad2(p: T = [], r2: T): void { } @@ -40,8 +40,8 @@ export declare function fnDeclBad3(p: T, rParam?: T, r2: T): void; 8 | export function fnDeclBad3(p: T = [], rParam?: T, r2: T): void { } `---- - x Declaration emit for this parameter requires implicitly adding undefined - | to it's type. This is not supported with --isolatedDeclarations. + x TS9025: Declaration emit for this parameter requires implicitly adding + | undefined to it's type. This is not supported with --isolatedDeclarations. ,-[8:31] 7 | export function fnDeclBad2(p: T = [], r2: T): void { } 8 | export function fnDeclBad3(p: T = [], rParam?: T, r2: T): void { } diff --git a/crates/oxc_isolated_declarations/tests/snapshots/infer-return-type.snap b/crates/oxc_isolated_declarations/tests/snapshots/infer-return-type.snap index ca60bb4388e78..470273d9f8559 100644 --- a/crates/oxc_isolated_declarations/tests/snapshots/infer-return-type.snap +++ b/crates/oxc_isolated_declarations/tests/snapshots/infer-return-type.snap @@ -11,7 +11,7 @@ declare function baz(); ==================== Errors ==================== - x Function must have an explicit return type annotation with + x TS9007: Function must have an explicit return type annotation with | --isolatedDeclarations. ,-[14:10] 13 | diff --git a/crates/oxc_isolated_declarations/tests/snapshots/non-exported-binding-elements.snap b/crates/oxc_isolated_declarations/tests/snapshots/non-exported-binding-elements.snap index d20aa07d94157..50d585442beef 100644 --- a/crates/oxc_isolated_declarations/tests/snapshots/non-exported-binding-elements.snap +++ b/crates/oxc_isolated_declarations/tests/snapshots/non-exported-binding-elements.snap @@ -10,7 +10,8 @@ export { c, d, e }; ==================== Errors ==================== - x Binding elements can't be exported directly with --isolatedDeclarations. + x TS9019: Binding elements can't be exported directly with + | --isolatedDeclarations. ,-[8:9] 7 | // Incorrect 8 | const { c, d } = { c: 1, d: 2 }; @@ -18,7 +19,8 @@ export { c, d, e }; 9 | const [ e ] = [4]; `---- - x Binding elements can't be exported directly with --isolatedDeclarations. + x TS9019: Binding elements can't be exported directly with + | --isolatedDeclarations. ,-[8:12] 7 | // Incorrect 8 | const { c, d } = { c: 1, d: 2 }; @@ -26,7 +28,8 @@ export { c, d, e }; 9 | const [ e ] = [4]; `---- - x Binding elements can't be exported directly with --isolatedDeclarations. + x TS9019: Binding elements can't be exported directly with + | --isolatedDeclarations. ,-[9:9] 8 | const { c, d } = { c: 1, d: 2 }; 9 | const [ e ] = [4]; diff --git a/crates/oxc_isolated_declarations/tests/snapshots/set-get-accessor.snap b/crates/oxc_isolated_declarations/tests/snapshots/set-get-accessor.snap index 0ab6aebbd938b..5c3aaaee73458 100644 --- a/crates/oxc_isolated_declarations/tests/snapshots/set-get-accessor.snap +++ b/crates/oxc_isolated_declarations/tests/snapshots/set-get-accessor.snap @@ -20,8 +20,8 @@ declare class ClsBad { ==================== Errors ==================== - x At least one accessor must have an explicit return type annotation with - | --isolatedDeclarations. + x TS9009: At least one accessor must have an explicit return type annotation + | with --isolatedDeclarations. ,-[21:7] 20 | class ClsBad { 21 | get a() {