feat(isolated-declarations): add ts error code to the error message (#3755)

This commit is contained in:
Dunqing 2024-06-19 14:33:29 +00:00
parent 94202de250
commit 4134de8dcf
9 changed files with 186 additions and 152 deletions

View file

@ -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()));
}
}
}

View file

@ -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 variable_must_have_explicit_type(span: Span) -> OxcDiagnostic {
OxcDiagnostic::error(
"TS9010: Variable must have an explicit type annotation with --isolatedDeclarations.",
)
.with_label(span)
}
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 property_must_have_explicit_type(span: Span) -> OxcDiagnostic {
OxcDiagnostic::error(
"Property 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."
))
.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.")
.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.")
.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 extends_clause_expression(span: Span) -> OxcDiagnostic {
OxcDiagnostic::error("Extends clause can't contain an expression with --isolatedDeclarations.")
.with_label(span)
}
pub fn default_export_inferred(span: Span) -> OxcDiagnostic {
OxcDiagnostic::error("Default exports can't 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 shorthand_property(span: Span) -> OxcDiagnostic {
OxcDiagnostic::error(
"Objects that contain shorthand properties can't be inferred with --isolatedDeclarations.",
"TS9012: Property must have an explicit type annotation with --isolatedDeclarations.",
)
.with_label(span)
}
pub fn inferred_type_of_expression(span: Span) -> OxcDiagnostic {
OxcDiagnostic::error("Expression type can't be inferred with --isolatedDeclarations.")
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("TS9014: Computed properties must be number or string literals, variables or dotted expressions 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 shorthand_property(span: Span) -> OxcDiagnostic {
OxcDiagnostic::error(
"TS9016: Objects that contain shorthand properties can't be inferred with --isolatedDeclarations.",
)
.with_label(span)
}
pub fn array_inferred(span: Span) -> OxcDiagnostic {
OxcDiagnostic::error("TS9017: Only const arrays can 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 binding_element_export(span: Span) -> OxcDiagnostic {
OxcDiagnostic::error(
"TS9019: Binding elements can't be exported directly with --isolatedDeclarations.",
)
.with_label(span)
}
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 extends_clause_expression(span: Span) -> OxcDiagnostic {
OxcDiagnostic::error(
"TS9021: Extends clause can't contain an expression 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 parameter_must_have_explicit_type(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)
}

View file

@ -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()));
}
}

View file

@ -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;
}
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 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(
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);

View file

@ -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 |

View file

@ -13,8 +13,8 @@ export declare function fnDeclBad3<T>(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<T>(p: T = [], rParam: T = "", r2: T): void { }
@ -22,8 +22,8 @@ export declare function fnDeclBad3<T>(p: T, rParam?: T, r2: T): void;
7 | export function fnDeclBad2<T>(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<T>(p: T = [], rParam: T = "", r2: T): void { }
@ -31,8 +31,8 @@ export declare function fnDeclBad3<T>(p: T, rParam?: T, r2: T): void;
7 | export function fnDeclBad2<T>(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<T>(p: T = [], rParam: T = "", r2: T): void { }
7 | export function fnDeclBad2<T>(p: T = [], r2: T): void { }
@ -40,8 +40,8 @@ export declare function fnDeclBad3<T>(p: T, rParam?: T, r2: T): void;
8 | export function fnDeclBad3<T>(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<T>(p: T = [], r2: T): void { }
8 | export function fnDeclBad3<T>(p: T = [], rParam?: T, r2: T): void { }

View file

@ -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 |

View file

@ -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];

View file

@ -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() {