Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 27 additions & 9 deletions crates/oxc_isolated_declarations/src/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ use oxc_allocator::Box;
use oxc_span::{GetSpan, SPAN};

use crate::{
diagnostics::{computed_property_name, extends_clause_expression},
diagnostics::{
accessor_must_have_explicit_return_type, computed_property_name, extends_clause_expression,
method_must_have_explicit_return_type, property_must_have_explicit_type,
},
IsolatedDeclarations,
};

Expand Down Expand Up @@ -59,16 +62,17 @@ impl<'a> IsolatedDeclarations<'a> {
.as_ref()
.map(|type_annotation| self.ast.copy(type_annotation))
.or_else(|| {
let new_type = property
property
.value
.as_ref()
.and_then(|expr| self.infer_type_from_expression(expr))
.unwrap_or_else(|| {
// report error for has no type annotation
self.ast.ts_unknown_keyword(property.span)
});

Some(self.ast.ts_type_annotation(SPAN, new_type))
.and_then(|expr| {
let ts_type = self.infer_type_from_expression(expr);
if ts_type.is_none() {
self.error(property_must_have_explicit_type(property.key.span()));
}
ts_type
})
.map(|ts_type| self.ast.ts_type_annotation(SPAN, ts_type))
})
};

Expand Down Expand Up @@ -115,6 +119,20 @@ impl<'a> IsolatedDeclarations<'a> {

let type_annotation = self.infer_function_return_type(function);

if type_annotation.is_none() {
match definition.kind {
MethodDefinitionKind::Method => {
self.error(method_must_have_explicit_return_type(definition.key.span()));
}
MethodDefinitionKind::Get => {
self.error(accessor_must_have_explicit_return_type(definition.key.span()));
}
MethodDefinitionKind::Constructor | MethodDefinitionKind::Set => {}
}
}

// TODO: Infer the parameter type of the `set` method from the `get` method

let value = self.ast.function(
FunctionType::TSEmptyBodyFunctionExpression,
function.span,
Expand Down
8 changes: 7 additions & 1 deletion crates/oxc_isolated_declarations/src/declaration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ use oxc_diagnostics::OxcDiagnostic;
use oxc_span::{GetSpan, SPAN};
use oxc_syntax::scope::ScopeFlags;

use crate::{diagnostics::signature_computed_property_name, IsolatedDeclarations};
use crate::{
diagnostics::{inferred_type_of_expression, signature_computed_property_name},
IsolatedDeclarations,
};

impl<'a> IsolatedDeclarations<'a> {
pub fn transform_variable_declaration(
Expand Down Expand Up @@ -264,6 +267,9 @@ impl<'a> IsolatedDeclarations<'a> {

impl<'a> Visit<'a> for IsolatedDeclarations<'a> {
fn visit_ts_method_signature(&mut self, signature: &TSMethodSignature<'a>) {
if signature.return_type.is_none() {
self.error(inferred_type_of_expression(signature.span));
}
self.report_signature_property_key(&signature.key, signature.computed);
}
fn visit_ts_property_signature(&mut self, signature: &TSPropertySignature<'a>) {
Expand Down
60 changes: 51 additions & 9 deletions crates/oxc_isolated_declarations/src/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@
use oxc_ast::ast::Function;
use oxc_diagnostics::OxcDiagnostic;
use oxc_span::{Atom, Span};

pub fn function_must_have_explicit_return_type(func: &Function<'_>) -> OxcDiagnostic {
pub fn method_must_have_explicit_return_type(span: Span) -> OxcDiagnostic {
OxcDiagnostic::error(
"Method must have an explicit return type annotation with --isolatedDeclarations.",
)
.with_label(span)
}

pub fn function_must_have_explicit_return_type(span: Span) -> OxcDiagnostic {
OxcDiagnostic::error(
"Function must have an explicit return type annotation with --isolatedDeclarations.",
)
.with_label(func.id.as_ref().map_or_else(
|| {
let start = func.params.span.start;
Span::new(start, start)
},
|id| id.span,
))
.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.",
)
.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 {
Expand Down Expand Up @@ -41,3 +55,31 @@ 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.",
)
.with_label(span)
}

pub fn inferred_type_of_expression(span: Span) -> OxcDiagnostic {
OxcDiagnostic::error("Expression type can't be inferred with --isolatedDeclarations.")
.with_label(span)
}

// Inference from class expressions is not supported with --isolatedDeclarations.

pub fn inferred_type_of_class_expression(span: Span) -> OxcDiagnostic {
OxcDiagnostic::error("Class expression type can't be inferred with --isolatedDeclarations.")
.with_label(span)
}
17 changes: 15 additions & 2 deletions crates/oxc_isolated_declarations/src/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,19 @@ use oxc_ast::ast::*;
use oxc_allocator::Box;
use oxc_ast::ast::Function;
use oxc_diagnostics::OxcDiagnostic;
use oxc_span::SPAN;
use oxc_span::{Span, SPAN};

use crate::IsolatedDeclarations;
use crate::{diagnostics::function_must_have_explicit_return_type, IsolatedDeclarations};

impl<'a> IsolatedDeclarations<'a> {
pub fn transform_function(&mut self, func: &Function<'a>) -> Option<Box<'a, Function<'a>>> {
if func.modifiers.is_contains_declare() {
None
} else {
let return_type = self.infer_function_return_type(func);
if return_type.is_none() {
self.error(function_must_have_explicit_return_type(get_function_span(func)));
}
let params = self.transform_formal_parameters(&func.params);
Some(self.ast.function(
func.r#type,
Expand Down Expand Up @@ -126,3 +129,13 @@ impl<'a> IsolatedDeclarations<'a> {
)
}
}

pub fn get_function_span(func: &Function<'_>) -> Span {
func.id.as_ref().map_or_else(
|| {
let start = func.params.span.start;
Span::new(start, start)
},
|id| id.span,
)
}
39 changes: 19 additions & 20 deletions crates/oxc_isolated_declarations/src/inferrer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use oxc_diagnostics::OxcDiagnostic;
use oxc_span::{GetSpan, SPAN};

use crate::{
diagnostics::function_must_have_explicit_return_type, return_type::FunctionReturnType,
diagnostics::{array_inferred, inferred_type_of_class_expression},
return_type::FunctionReturnType,
IsolatedDeclarations,
};

Expand Down Expand Up @@ -35,6 +36,10 @@ impl<'a> IsolatedDeclarations<'a> {
Expression::ObjectExpression(expr) => {
Some(self.transform_object_expression_to_ts_type(expr, false))
}
Expression::ArrayExpression(expr) => {
self.error(array_inferred(expr.span));
Some(self.ast.ts_unknown_keyword(expr.span))
}
Expression::TSAsExpression(expr) => {
if expr.type_annotation.is_const_type_reference() {
Some(self.transform_expression_to_ts_type(&expr.expression))
Expand All @@ -43,14 +48,7 @@ impl<'a> IsolatedDeclarations<'a> {
}
}
Expression::ClassExpression(expr) => {
self.error(
OxcDiagnostic::error(
"
Inference from class expressions is not supported with --isolatedDeclarations.
",
)
.with_label(expr.span),
);
self.error(inferred_type_of_class_expression(expr.span));
Some(self.ast.ts_unknown_keyword(SPAN))
}
Expression::TSNonNullExpression(expr) => {
Expand Down Expand Up @@ -104,25 +102,17 @@ impl<'a> IsolatedDeclarations<'a> {
}

if function.r#async || function.generator {
self.error(function_must_have_explicit_return_type(function));
return None;
}

let return_type = FunctionReturnType::infer(
FunctionReturnType::infer(
self,
function
.body
.as_ref()
.unwrap_or_else(|| unreachable!("Only declare function can have no body")),
)
.map(|type_annotation| self.ast.ts_type_annotation(SPAN, type_annotation));

if return_type.is_none() {
self.error(function_must_have_explicit_return_type(function));

Some(self.ast.ts_type_annotation(SPAN, self.ast.ts_unknown_keyword(SPAN)))
} else {
return_type
}
.map(|type_annotation| self.ast.ts_type_annotation(SPAN, type_annotation))
}

pub fn infer_arrow_function_return_type(
Expand All @@ -133,13 +123,22 @@ impl<'a> IsolatedDeclarations<'a> {
return self.ast.copy(&function.return_type);
}

if function.r#async {
return None;
}

if function.r#async {
return None;
}

if function.expression {
if let Some(Statement::ExpressionStatement(stmt)) = function.body.statements.first() {
return self
.infer_type_from_expression(&stmt.expression)
.map(|type_annotation| self.ast.ts_type_annotation(SPAN, type_annotation));
}
}

FunctionReturnType::infer(self, &function.body)
.map(|type_annotation| self.ast.ts_type_annotation(SPAN, type_annotation))
}
Expand Down
7 changes: 6 additions & 1 deletion crates/oxc_isolated_declarations/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use oxc_allocator::Box;
use oxc_ast::Visit;
use oxc_span::{GetSpan, SPAN};

use crate::IsolatedDeclarations;
use crate::{diagnostics::default_export_inferred, IsolatedDeclarations};

impl<'a> IsolatedDeclarations<'a> {
pub fn transform_export_named_declaration(
Expand Down Expand Up @@ -46,6 +46,7 @@ impl<'a> IsolatedDeclarations<'a> {
} else {
// declare const _default: Type
let kind = VariableDeclarationKind::Const;
// TODO: create unique name for this
let name = self.ast.new_atom("_default");
let id = self
.ast
Expand All @@ -54,6 +55,10 @@ impl<'a> IsolatedDeclarations<'a> {
.infer_type_from_expression(expr)
.map(|ts_type| self.ast.ts_type_annotation(SPAN, ts_type));

if type_annotation.is_none() {
self.error(default_export_inferred(expr.span()));
}

let id = BindingPattern { kind: id, type_annotation, optional: false };
let declarations = self
.ast
Expand Down
29 changes: 27 additions & 2 deletions crates/oxc_isolated_declarations/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,23 @@ use oxc_ast::ast::{
TSTypeOperatorOperator,
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_span::SPAN;
use oxc_span::{GetSpan, SPAN};

use crate::IsolatedDeclarations;
use crate::{
diagnostics::{
function_must_have_explicit_return_type, inferred_type_of_expression, shorthand_property,
},
function::get_function_span,
IsolatedDeclarations,
};

impl<'a> IsolatedDeclarations<'a> {
pub fn transform_function_to_ts_type(&self, func: &Function<'a>) -> Option<TSType<'a>> {
let return_type = self.infer_function_return_type(func);
if return_type.is_none() {
self.error(function_must_have_explicit_return_type(get_function_span(func)));
}

let params = self.transform_formal_parameters(&func.params);

return_type.map(|return_type| {
Expand All @@ -29,6 +39,11 @@ impl<'a> IsolatedDeclarations<'a> {
func: &ArrowFunctionExpression<'a>,
) -> Option<TSType<'a>> {
let return_type = self.infer_arrow_function_return_type(func);

if return_type.is_none() {
self.error(function_must_have_explicit_return_type(func.span));
}

let params = self.transform_formal_parameters(&func.params);

return_type.map(|return_type| {
Expand Down Expand Up @@ -66,6 +81,11 @@ impl<'a> IsolatedDeclarations<'a> {
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);
Expand All @@ -86,6 +106,11 @@ impl<'a> IsolatedDeclarations<'a> {

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,
Expand Down