Skip to content

Commit

Permalink
feat(isolated-declarations): add ts error code to the error message
Browse files Browse the repository at this point in the history
  • Loading branch information
Dunqing committed Jun 19, 2024
1 parent 87f4ecc commit 11524c7
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 131 deletions.
7 changes: 2 additions & 5 deletions crates/oxc_isolated_declarations/src/declaration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -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()));
}
}
}
Expand Down
111 changes: 75 additions & 36 deletions crates/oxc_isolated_declarations/src/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -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)
}
10 changes: 4 additions & 6 deletions crates/oxc_isolated_declarations/src/inferrer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -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()));
}
}

Expand Down
131 changes: 64 additions & 67 deletions crates/oxc_isolated_declarations/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
}

Expand All @@ -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);
Expand Down
Loading

0 comments on commit 11524c7

Please sign in to comment.