diff --git a/.github/dependabot.yml b/.github/dependabot.yml index e3dd18fa4ac43..735158cfb260d 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -20,7 +20,6 @@ updates: - "patch" ignore: - dependency-name: "textwrap" - - dependency-name: "ezno-checker" # Enable when we have more resources # - package-ecosystem: "gitsubmodule" diff --git a/Cargo.lock b/Cargo.lock index 18af93174a7e6..ef253f003f0dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -109,21 +109,6 @@ version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" -[[package]] -name = "bimap" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46da4f7" - -[[package]] -name = "binary-serialize-derive" -version = "0.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d615dce242f5c93ae0af95f380ff2d72f2944158dc2fa81f5420bff9e70254" -dependencies = [ - "syn-helpers", -] - [[package]] name = "bitflags" version = "1.3.2" @@ -298,16 +283,6 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" -[[package]] -name = "codespan-reporting" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] - [[package]] name = "codspeed" version = "2.3.3" @@ -506,32 +481,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown 0.14.3", + "hashbrown", "lock_api", "once_cell", "parking_lot_core", ] -[[package]] -name = "derive-debug-extras" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0e7a68c77a933db6b8907154fbd45f15f6ccc11f796b00b04354b8899d9d131" -dependencies = [ - "syn-helpers", -] - -[[package]] -name = "derive-enum-from-into" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc2a1b7c0031fb651e9bc1fa4255da82747c187b9ac1dc36b3783d71fadd9d5" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "difference" version = "2.0.0" @@ -560,12 +515,6 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" -[[package]] -name = "either_n" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c91ae510829160d5cfb19eb4ae7b6e01d44b767ca8f727c6cee936e53cc9ae5" - [[package]] name = "encode_unicode" version = "0.3.6" @@ -590,28 +539,6 @@ dependencies = [ "encoding_rs", ] -[[package]] -name = "enum-variants-strings" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "208ec1cfed58007d641f74552a523a405cd374417ec65ba01fb89ab2796054a1" -dependencies = [ - "enum-variants-strings-derive", -] - -[[package]] -name = "enum-variants-strings-derive" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4acea45431925e008a911e3fded23d302c9eb81493e7b9cae0c5aa29a9342a5a" -dependencies = [ - "either_n", - "proc-macro2", - "quote", - "string-cases", - "syn 1.0.109", -] - [[package]] name = "env_logger" version = "0.10.1" @@ -630,15 +557,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" -[[package]] -name = "erased-serde" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c138974f9d5e7fe373eb04df7cae98833802ae4b11c24ac7039a21d5af4b26c" -dependencies = [ - "serde", -] - [[package]] name = "errno" version = "0.3.8" @@ -649,31 +567,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "ezno-checker" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce89c36282d2e7e84de91cca6c2c32ba11f4839ae8c73fb7cc0024411ab28521" -dependencies = [ - "bimap", - "binary-serialize-derive", - "derive-debug-extras", - "derive-enum-from-into", - "either", - "enum-variants-strings", - "erased-serde", - "indexmap 1.9.3", - "iterator-endiate", - "levenshtein", - "map_vec", - "once_cell", - "ordered-float", - "path-absolutize", - "serde", - "source-map", - "temporary-annex", -] - [[package]] name = "flate2" version = "1.0.28" @@ -861,12 +754,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - [[package]] name = "hashbrown" version = "0.14.3" @@ -941,16 +828,6 @@ dependencies = [ "serde", ] -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - [[package]] name = "indexmap" version = "2.1.0" @@ -958,7 +835,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown", "serde", ] @@ -994,12 +871,6 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb" -[[package]] -name = "iterator-endiate" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab947031a0a0cb37f982ef2a0ab3bacfd3de5ed97dd5c7e98bcc92bba357112" - [[package]] name = "itertools" version = "0.10.5" @@ -1065,12 +936,6 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -[[package]] -name = "levenshtein" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" - [[package]] name = "libc" version = "0.2.151" @@ -1144,15 +1009,6 @@ dependencies = [ "url", ] -[[package]] -name = "map_vec" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43e9839b06bd5129fa636a93cb53601ffae739b8ff115841374d110cafb02cad" -dependencies = [ - "serde", -] - [[package]] name = "matchers" version = "0.1.0" @@ -1395,15 +1251,6 @@ version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" -[[package]] -name = "ordered-float" -version = "3.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1e1c390732d15f1d48471625cd92d154e66db2c56645e29a9cd26f4699f72dc" -dependencies = [ - "num-traits", -] - [[package]] name = "ouroboros" version = "0.18.2" @@ -1514,7 +1361,6 @@ name = "oxc_cli" version = "0.0.0" dependencies = [ "bpaf", - "codespan-reporting", "glob", "ignore", "jemallocator", @@ -1527,7 +1373,6 @@ dependencies = [ "oxc_parser", "oxc_prettier", "oxc_span", - "oxc_type_synthesis", "pretty_assertions", "rayon", "regex", @@ -1793,7 +1638,7 @@ checksum = "497a89a4d3c44b9df9fade0e70cf46e79722bced1ddf6e3a02d1fec9e30ce161" dependencies = [ "dashmap", "dunce", - "indexmap 2.1.0", + "indexmap", "once_cell", "rustc-hash", "serde", @@ -1807,7 +1652,7 @@ name = "oxc_semantic" version = "0.5.0" dependencies = [ "bitflags 2.4.1", - "indexmap 2.1.0", + "indexmap", "itertools 0.12.0", "miette", "oxc_allocator", @@ -1837,7 +1682,7 @@ version = "0.5.0" dependencies = [ "bitflags 2.4.1", "dashmap", - "indexmap 2.1.0", + "indexmap", "oxc_index", "oxc_span", "phf", @@ -1864,7 +1709,7 @@ dependencies = [ name = "oxc_transform_conformance" version = "0.0.0" dependencies = [ - "indexmap 2.1.0", + "indexmap", "jemallocator", "mimalloc", "oxc_allocator", @@ -1898,18 +1743,6 @@ dependencies = [ "serde", ] -[[package]] -name = "oxc_type_synthesis" -version = "0.0.0" -dependencies = [ - "ezno-checker", - "oxc_allocator", - "oxc_ast", - "oxc_parser", - "oxc_span", - "oxc_syntax", -] - [[package]] name = "oxc_wasm" version = "0.0.0" @@ -1918,7 +1751,6 @@ dependencies = [ "oxc", "oxc_linter", "oxc_prettier", - "oxc_type_synthesis", "serde", "serde-wasm-bindgen", "wasm-bindgen", @@ -1948,24 +1780,6 @@ dependencies = [ "windows-targets 0.48.5", ] -[[package]] -name = "path-absolutize" -version = "3.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4af381fe79fa195b4909485d99f73a80792331df0625188e707854f0b3383f5" -dependencies = [ - "path-dedot", -] - -[[package]] -name = "path-dedot" -version = "3.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07ba0ad7e047712414213ff67533e6dd477af0a4e1d14fb52343e53d30ea9397" -dependencies = [ - "once_cell", -] - [[package]] name = "percent-encoding" version = "2.3.1" @@ -2457,7 +2271,7 @@ version = "1.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" dependencies = [ - "indexmap 2.1.0", + "indexmap", "itoa", "ryu", "serde", @@ -2480,7 +2294,7 @@ version = "0.9.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1bf28c79a99f70ee1f1d83d10c875d2e70618417fda01ad1785e027579d9d38" dependencies = [ - "indexmap 2.1.0", + "indexmap", "itoa", "ryu", "serde", @@ -2559,15 +2373,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "source-map" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fedd4de16a29859eebdc14368c1fc2f5227ba58e1fdaba748072bf80ed9c5a35" -dependencies = [ - "serde", -] - [[package]] name = "spin" version = "0.9.8" @@ -2586,12 +2391,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9557cb6521e8d009c51a8666f09356f4b817ba9ba0981a305bd86aee47bd35c" -[[package]] -name = "string-cases" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31d23461f9e0fbe756cf9d5a36be93740fe12c8b094409a5f78f0f912ee2b6f" - [[package]] name = "supports-color" version = "2.1.0" @@ -2642,24 +2441,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "syn-helpers" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2919350d44e7bdba75bf541da7a15c415a84fea1c823f37f0c48a6b0133639" -dependencies = [ - "either_n", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "temporary-annex" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e9c16d33fb2759286102fa235fd7029a8de2c2961165b2942c9cac81607a044" - [[package]] name = "termcolor" version = "1.4.0" @@ -2801,7 +2582,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.1.0", + "indexmap", "toml_datetime", "winnow", ] diff --git a/README.md b/README.md index 6e04a22109212..a34cecae3bab7 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,6 @@ where warm runs complete in 5 minutes. - [Minifier](#-minifier) - [Formatter](#-formatter) - [Transpiler](#-transpiler) -- [Ezno Type Checker](#-ezno-type-checker) ### 🔸 AST and Parser @@ -188,13 +187,6 @@ With the Oxc minifier, you can expect faster minification times without sacrific While [prettier] has established itself as the de facto code formatter for JavaScript, there is a significant demand in the developer community for a less opinionated alternative. Recognizing this need, our ambition is to undertake research and development to create a new JavaScript formatter that offers increased flexibility and customization options. Unfortunately we are currently lacking the resources to do so. -### 🔸 Ezno Type Checker - -Developed by @kaleidawave, [ezno] is a TypeScript checker written in Rust with a focus on static analysis and runtime performance. -You may read the [announcement blog post](https://kaleidawave.github.io/posts/introducing-ezno/) for more information. - -The type checker is available via `npx oxidation-compiler@latest check path` and the [playground][playground-url]. - --- ## ✍️ Contribute @@ -245,7 +237,7 @@ Special thanks go to And also -- [@kaleidawave](https://github.com/kaleidawave) for [Ezno Type Checker](#-ezno-type-checker) +- [@kaleidawave](https://github.com/kaleidawave) for [Ezno Type Checker](https://github.com/kaleidawave/ezno) - [@zackradisic](https://github.com/zackradisic) for [tyvm](https://github.com/zackradisic/tyvm) ## 📖 License @@ -308,7 +300,6 @@ Oxc partially copies code from the following projects, their licenses are listed [eslint-plugin-import]: https://www.npmjs.com/package/eslint-plugin-import [eslint-plugin-jest]: https://www.npmjs.com/package/eslint-plugin-jest [estree]: https://github.com/estree/estree -[ezno]: https://github.com/kaleidawave/ezno [google-closure-compiler]: https://github.com/google/closure-compiler [minification-benchmarks]: https://github.com/privatenumber/minification-benchmarks [npm-napi]: https://www.npmjs.com/package/oxc-parser diff --git a/crates/oxc_cli/Cargo.toml b/crates/oxc_cli/Cargo.toml index 46f1a969a4819..6ff953196370e 100644 --- a/crates/oxc_cli/Cargo.toml +++ b/crates/oxc_cli/Cargo.toml @@ -40,14 +40,10 @@ oxc_linter = { workspace = true } oxc_parser = { workspace = true } oxc_prettier = { workspace = true } oxc_span = { workspace = true } -oxc_type_synthesis = { workspace = true } glob = { workspace = true } lazy_static = { workspace = true } regex = { workspace = true } -# TODO temp, for type check output, replace with Miette -codespan-reporting = "0.11.1" - ignore = { workspace = true, features = ["simd-accel"] } miette = { workspace = true } rayon = { workspace = true } diff --git a/crates/oxc_cli/src/command.rs b/crates/oxc_cli/src/command.rs index 1bb546d7a5a9b..6df646fe96d23 100644 --- a/crates/oxc_cli/src/command.rs +++ b/crates/oxc_cli/src/command.rs @@ -12,10 +12,6 @@ pub enum CliCommand { /// Format this repository #[bpaf(command)] Format(#[bpaf(external(format_options))] FormatOptions), - - /// Use Ezno to type check source code (experimental and work in progress) - #[bpaf(command)] - Check(#[bpaf(external(check_options))] CheckOptions), } impl CliCommand { @@ -27,7 +23,6 @@ impl CliCommand { Self::Format(options) => { Self::set_rayon_threads(options.misc_options.threads); } - Self::Check(_) => {} } } @@ -255,21 +250,6 @@ pub struct WarningOptions { pub max_warnings: Option, } -#[derive(Debug, Clone, Bpaf)] -pub struct CheckOptions { - /// Print called functions - #[bpaf(switch, hide_usage)] - pub print_called_functions: bool, - - /// Print types of expressions - #[bpaf(switch, hide_usage)] - pub print_expression_mappings: bool, - - /// File to type check - #[bpaf(positional("PATH"))] - pub path: PathBuf, -} - #[cfg(test)] mod misc_options { use super::{lint_command, MiscOptions}; diff --git a/crates/oxc_cli/src/lib.rs b/crates/oxc_cli/src/lib.rs index b7f3003e43800..228fad13d9508 100644 --- a/crates/oxc_cli/src/lib.rs +++ b/crates/oxc_cli/src/lib.rs @@ -4,7 +4,6 @@ mod format; mod lint; mod result; mod runner; -mod type_check; mod walk; pub use crate::{ @@ -13,5 +12,4 @@ pub use crate::{ lint::LintRunner, result::{CliRunResult, LintResult}, runner::Runner, - type_check::TypeCheckRunner, }; diff --git a/crates/oxc_cli/src/main.rs b/crates/oxc_cli/src/main.rs index cc77305d51204..a1eeb4ed05bb8 100644 --- a/crates/oxc_cli/src/main.rs +++ b/crates/oxc_cli/src/main.rs @@ -8,7 +8,7 @@ static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc; #[global_allocator] static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; -use oxc_cli::{CliCommand, CliRunResult, FormatRunner, LintRunner, Runner, TypeCheckRunner}; +use oxc_cli::{CliCommand, CliRunResult, FormatRunner, LintRunner, Runner}; fn main() -> CliRunResult { let options = oxc_cli::cli_command().fallback_to_usage().run(); @@ -16,6 +16,5 @@ fn main() -> CliRunResult { match options { CliCommand::Lint(options) => LintRunner::new(options).run(), CliCommand::Format(options) => FormatRunner::new(options).run(), - CliCommand::Check(options) => TypeCheckRunner::new(options).run(), } } diff --git a/crates/oxc_cli/src/type_check/mod.rs b/crates/oxc_cli/src/type_check/mod.rs deleted file mode 100644 index 902a1fbd1f2e5..0000000000000 --- a/crates/oxc_cli/src/type_check/mod.rs +++ /dev/null @@ -1,297 +0,0 @@ -use std::path::{Path, PathBuf}; - -use oxc_allocator::Allocator; -use oxc_parser::Parser; -use oxc_span::SourceType; -use oxc_type_synthesis::synthesize_program; - -use crate::{command::CheckOptions, runner::Runner, CliRunResult}; - -const PRELUDE: &str = " -type StringOrNumber = string | number; - -interface Operators { - Add(a: T, b: U): (T extends string ? string : U extends string ? string: number) & Ezno.ConstantFunction<'add'>; - - Mul(a: number, b: number): number & Ezno.ConstantFunction<'mul'>; - - StrictEqual(a: any, b: any): boolean & Ezno.ConstantFunction<'equal'>; -} - -interface Math { - sin(x: number): number & Ezno.ConstantFunction<'sin'>; -} - -interface string { - toUppercase(): string & Ezno.ConstantFunction<'uppercase'> -} - -interface Console { - log(msg: any): void; -} - -declare var Math: Math; -declare var console: Console; -"; - -/// TODO temp -#[derive(Debug)] -pub struct TypeCheckOptions { - pub path: PathBuf, - // TODO temp, for exhibition - pub print_expression_mappings: bool, - // TODO temp, for exhibition - pub print_called_functions: bool, -} - -pub struct TypeCheckRunner { - options: TypeCheckOptions, -} - -impl Runner for TypeCheckRunner { - type Options = CheckOptions; - - fn new(options: Self::Options) -> Self { - let options = TypeCheckOptions { - path: options.path, - print_expression_mappings: options.print_expression_mappings, - print_called_functions: options.print_called_functions, - }; - Self { options } - } - - /// # Panics - fn run(self) -> CliRunResult { - let now = std::time::Instant::now(); - - let path = Path::new(&self.options.path); - let source_text = PRELUDE.to_owned() - + &std::fs::read_to_string(path) - .unwrap_or_else(|_| panic!("{} not found", self.options.path.display())); - let allocator = Allocator::default(); - let source_type = SourceType::from_path(path).unwrap(); - - let ret = Parser::new(&allocator, &source_text, source_type).parse(); - - if ret.errors.is_empty() { - let (diagnostics, _events, types, mappings, root_env) = - synthesize_program(&ret.program, |_: &std::path::Path| None); - - let duration = now.elapsed(); - - if self.options.print_expression_mappings { - let mappings = mappings.print_type_mappings( - &source_text, - &root_env.into_general_environment(), - &types, - ); - eprintln!("{mappings}"); - } - if self.options.print_called_functions { - let called_functions = mappings.print_called_functions(&source_text); - eprintln!("{called_functions}"); - } - - // TODO - let number_of_diagnostics = 0; - type_check_output::print_diagnostics_container( - diagnostics, - self.options.path.display().to_string(), - source_text.clone(), - ); - CliRunResult::TypeCheckResult { duration, number_of_diagnostics } - } else { - let duration = now.elapsed(); - let number_of_diagnostics = ret.errors.len(); - for error in ret.errors { - let error = error.with_source_code(source_text.clone()); - println!("{error:?}"); - } - CliRunResult::TypeCheckResult { duration, number_of_diagnostics } - } - } -} - -mod type_check_output { - use std::iter; - - use codespan_reporting::{ - diagnostic::{Diagnostic, Label, Severity}, - files::SimpleFile, - term::{ - termcolor::{ColorChoice, StandardStream}, - Config, - }, - }; - use oxc_type_synthesis::{ - Diagnostic as TypeCheckDiagnostic, DiagnosticKind, DiagnosticsContainer, - }; - - #[allow(clippy::items_after_statements)] - pub(super) fn print_diagnostics_container( - diagnostic_container: DiagnosticsContainer, - path: String, - content: String, - ) { - let files = SimpleFile::new(path, content); - // let mut file_id_to_source_id = HashMap::::new(); - - // Handling adding filename-file id mappings - // for source_id in error_handler.sources() { - // let (filename, file_content) = source_id.get_file().unwrap(); - // let name = - // filename.strip_prefix(env::current_dir().unwrap()).unwrap_or(&filename).to_owned(); - // let file_id = files.add(name.display().to_string(), file_content); - // file_id_to_source_id.insert(source_id, file_id); - // } - - let writer = StandardStream::stderr(ColorChoice::Always); - let mut lock = writer.lock(); - - for diagnostic in diagnostic_container.into_iter().rev() { - // Conversion from Ezno -> codespan - let diagnostic = match diagnostic { - TypeCheckDiagnostic::Global { reason, kind } => Diagnostic { - severity: ezno_diagnostic_to_severity(&kind), - code: None, - message: reason, - labels: Vec::new(), - notes: Vec::default(), - }, - TypeCheckDiagnostic::Position { reason, position, kind } => Diagnostic { - severity: ezno_diagnostic_to_severity(&kind), - code: None, - message: String::default(), - labels: vec![Label::primary((), position).with_message(reason)], - notes: Vec::default(), - }, - TypeCheckDiagnostic::PositionWithAdditionLabels { - reason, - position, - labels, - kind, - } => { - let (labels, notes) = - labels.into_iter().partition::, _>(|(_, value)| value.is_some()); - - Diagnostic { - severity: ezno_diagnostic_to_severity(&kind), - code: None, - message: String::default(), - labels: iter::once(Label::primary((), position).with_message(reason)) - .chain(labels.into_iter().map(|(message, position)| { - let position = position.unwrap(); - Label::secondary((), position).with_message(message) - })) - .collect(), - notes: notes.into_iter().map(|(message, _)| message).collect(), - } - } - }; - - codespan_reporting::term::emit(&mut lock, &Config::default(), &files, &diagnostic) - .unwrap(); - } - - fn ezno_diagnostic_to_severity(kind: &DiagnosticKind) -> Severity { - match kind { - DiagnosticKind::Error => Severity::Error, - DiagnosticKind::Warning => Severity::Warning, - DiagnosticKind::Info => Severity::Note, - } - } - } -} - -// struct MietteEznoDiagnostic { -// diagnostic: EznoDiagnostic, -// severity: miette::Severity, -// // TODO temp -// source: &'static str, -// } - -// impl std::fmt::Debug for MietteEznoDiagnostic { -// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { -// f.debug_struct("MietteEznoDiagnostic").field("diagnostic", &"..").finish() -// } -// } - -// impl std::fmt::Display for MietteEznoDiagnostic { -// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { -// f.write_str(self.diagnostic.reason()) -// } -// } -// impl std::error::Error for MietteEznoDiagnostic {} - -// impl miette::Diagnostic for MietteEznoDiagnostic { -// fn code<'a>(&'a self) -> Option> { -// None -// } - -// fn severity(&self) -> Option { -// Some(self.severity) -// } - -// fn help<'a>(&'a self) -> Option> { -// None -// } - -// fn url<'a>(&'a self) -> Option> { -// None -// } - -// fn source_code(&self) -> Option<&dyn miette::SourceCode> { -// match self.diagnostic { -// EznoDiagnostic::Global(_) => None, -// EznoDiagnostic::Position { reason: _, ref pos } -// | EznoDiagnostic::PositionWithAdditionLabels { reason: _, labels: _, ref pos } => { -// // TODO temp -// None -// } -// } -// } - -// fn labels(&self) -> Option + '_>> { -// match self.diagnostic { -// // TODO temp -// EznoDiagnostic::Global(ref reason) => { -// Some(Box::new(iter::once(miette::LabeledSpan::new(Some(reason.clone()), 0, 0)))) -// } -// EznoDiagnostic::Position { ref reason, ref pos } => { -// Some(Box::new(iter::once(miette::LabeledSpan::new( -// Some(reason.clone()), -// pos.start as usize, -// pos.end as usize - pos.start as usize, -// )))) -// } -// EznoDiagnostic::PositionWithAdditionLabels { ref reason, ref labels, ref pos } => { -// Some(Box::new( -// iter::once(miette::LabeledSpan::new( -// Some(reason.clone()), -// pos.start as usize, -// pos.end as usize - pos.start as usize, -// )) -// .chain(labels.iter().map(|(label, pos)| { -// if let Some(pos) = pos { -// miette::LabeledSpan::new( -// Some(label.clone()), -// pos.start as usize, -// pos.end as usize - pos.start as usize, -// ) -// } else { -// miette::LabeledSpan::new(Some(label.clone()), 0, 0) -// } -// })), -// )) -// } -// } -// } - -// fn related<'a>(&'a self) -> Option + 'a>> { -// None -// } - -// fn diagnostic_source(&self) -> Option<&dyn miette::Diagnostic> { -// None -// } -// } diff --git a/crates/oxc_type_synthesis/Cargo.toml b/crates/oxc_type_synthesis/Cargo.toml deleted file mode 100644 index f7bcd965fd466..0000000000000 --- a/crates/oxc_type_synthesis/Cargo.toml +++ /dev/null @@ -1,28 +0,0 @@ -[package] -name = "oxc_type_synthesis" -version = "0.0.0" -authors.workspace = true -description.workspace = true -edition.workspace = true -homepage.workspace = true -keywords.workspace = true -license.workspace = true -repository.workspace = true -rust-version.workspace = true -categories.workspace = true - -[lints] -workspace = true - -[lib] -test = false -doctest = false - -[dependencies] -oxc_parser = { workspace = true } -oxc_ast = { workspace = true } -oxc_span = { workspace = true } -oxc_syntax = { workspace = true } -oxc_allocator = { workspace = true } - -ezno-checker = { version = "=0.0.4" } diff --git a/crates/oxc_type_synthesis/examples/check.rs b/crates/oxc_type_synthesis/examples/check.rs deleted file mode 100644 index c169dbc8e2ad3..0000000000000 --- a/crates/oxc_type_synthesis/examples/check.rs +++ /dev/null @@ -1,76 +0,0 @@ -use std::{env, path::Path}; - -use oxc_allocator::Allocator; -use oxc_parser::Parser; -use oxc_span::SourceType; -use oxc_type_synthesis::synthesize_program; - -const PRELUDE: &str = " -type StringOrNumber = string | number; - -interface Operators { - Add(a: T, b: U): (T extends string ? string : U extends string ? string: number) & Ezno.ConstantFunction<'add'>; - - Mul(a: number, b: number): number & Ezno.ConstantFunction<'mul'>; - - StrictEqual(a: any, b: any): boolean & Ezno.ConstantFunction<'equal'>; -} - -interface Math { - sin(x: number): number & Ezno.ConstantFunction<'sin'>; -} - -interface string { - toUppercase(): string & Ezno.ConstantFunction<'uppercase'> -} - -interface Console { - log(msg: any): void; -} - -declare var Math: Math; -declare var console: Console; -"; - -fn main() { - let name = env::args().nth(1).unwrap_or_else(|| "examples/demo.ts".to_string()); - let path = Path::new(&name); - let source_text = PRELUDE.to_owned() - + &std::fs::read_to_string(path).unwrap_or_else(|_| panic!("{name} not found")); - let allocator = Allocator::default(); - let source_type = SourceType::from_path(path).unwrap(); - let ret = Parser::new(&allocator, &source_text, source_type).parse(); - - if ret.errors.is_empty() { - println!("Program parsed"); - // println!("{}", serde_json::to_string_pretty(&ret.program).unwrap()); - - let (diagnostics, events, types, ..) = - synthesize_program(&ret.program, |_: &std::path::Path| None); - - let args: Vec<_> = env::args().collect(); - - if args.iter().any(|arg| arg == "--types") { - eprintln!("Types:"); - for item in types.into_vec_temp() { - eprintln!("\t{item:?}"); - } - } - if args.iter().any(|arg| arg == "--events") { - eprintln!("Events:"); - for item in events { - eprintln!("\t{item:?}"); - } - } - - eprintln!("Diagnostics:"); - for diag in diagnostics.into_iter() { - eprintln!("\t{}", diag.reason()); - } - } else { - for error in ret.errors { - let error = error.with_source_code(source_text.clone()); - println!("{error:?}"); - } - } -} diff --git a/crates/oxc_type_synthesis/examples/demo.ts b/crates/oxc_type_synthesis/examples/demo.ts deleted file mode 100644 index e7d796ce46b1e..0000000000000 --- a/crates/oxc_type_synthesis/examples/demo.ts +++ /dev/null @@ -1,41 +0,0 @@ -const a: 2 = 4; - -const b: 3 = 5 + 2; - -let c = 5; -c = 3; -let d: 2 = c; - -interface Car { - model: string, - power: number, - weight: number -} - -const car1: Car = { model: "Koenigsegg One:1", power: 1360, weight: 1360 } - -console.lag("log not lag") - -const weight: string = car1["we" + "ight"] - -if (car1.power === car1.weight) { - console.log("always here") -} - -function assertType(t: T): void; - -function getPerson(name: string) { - return { name } -} - -assertType<{name: "not ben" }>(getPerson("Ben")); - -function throwValue(value) { - throw value -} - -try { - throwValue("my error") -} catch (e) { - assertType<"different error">(e) -} diff --git a/crates/oxc_type_synthesis/src/expressions.rs b/crates/oxc_type_synthesis/src/expressions.rs deleted file mode 100644 index 80f88da9c4042..0000000000000 --- a/crates/oxc_type_synthesis/src/expressions.rs +++ /dev/null @@ -1,647 +0,0 @@ -use ezno_checker::{ - self, structures::functions::SynthesizedArgument, Assignable, CheckingData, Environment, - FSResolver, Instance, Property, Reference, RegisterAsType, RegisterOnExistingObject, TypeId, -}; -use oxc_ast::ast; -use oxc_span::GetSpan; -use oxc_syntax::operator::AssignmentOperator; - -use super::property_key_to_type; -use crate::{ - functions::{OxcArrowFunction, OxcFunction}, - oxc_span_to_source_map_span, - types::synthesize_type_annotation, -}; - -pub(crate) fn synthesize_expression( - expr: &ast::Expression, - environment: &mut Environment, - checking_data: &mut CheckingData, -) -> TypeId { - let instance = match expr { - ast::Expression::BooleanLiteral(boolean) => { - return checking_data - .types - .new_constant_type(ezno_checker::Constant::Boolean(boolean.value)); - } - ast::Expression::NullLiteral(_) => return TypeId::NULL_TYPE, - ast::Expression::BigintLiteral(big_int) => { - checking_data.raise_unimplemented_error( - "big int literal", - oxc_span_to_source_map_span(big_int.span), - ); - return TypeId::ERROR_TYPE; - } - ast::Expression::RegExpLiteral(regexp) => { - return checking_data.types.new_constant_type(ezno_checker::Constant::Regexp( - regexp.regex.pattern.to_string(), - )); - } - ast::Expression::NumberLiteral(number) => { - return checking_data.types.new_constant_type( - number - .value - .try_into() - .map(ezno_checker::Constant::Number) - .unwrap_or(ezno_checker::Constant::NaN), - ); - } - ast::Expression::StringLiteral(string) => { - return checking_data.types.new_constant_type(ezno_checker::Constant::String( - string.value.as_str().to_owned(), - )); - } - ast::Expression::TemplateLiteral(tl) => { - checking_data.raise_unimplemented_error( - "template literals", - oxc_span_to_source_map_span(tl.span), - ); - return TypeId::ERROR_TYPE; - } - ast::Expression::Identifier(identifier) => { - let result = environment.get_variable_or_error( - &identifier.name, - &oxc_span_to_source_map_span(identifier.span), - checking_data, - ); - - match result { - Ok(ok) => Instance::LValue(ok), - Err(err) => return err, - } - } - ast::Expression::MetaProperty(meta_prop) => { - checking_data.raise_unimplemented_error( - "meta_prop", - oxc_span_to_source_map_span(meta_prop.span), - ); - return TypeId::ERROR_TYPE; - } - ast::Expression::Super(super_item) => { - checking_data - .raise_unimplemented_error("super", oxc_span_to_source_map_span(super_item.span)); - return TypeId::ERROR_TYPE; - } - ast::Expression::ArrayExpression(array_expr) => { - checking_data.raise_unimplemented_error( - "array expression", - oxc_span_to_source_map_span(array_expr.span), - ); - return TypeId::ERROR_TYPE; - } - ast::Expression::AssignmentExpression(assignment) => { - Instance::RValue(synthesize_assignment(assignment, environment, checking_data)) - } - ast::Expression::AwaitExpression(r#await) => { - checking_data.raise_unimplemented_error( - "await expression", - oxc_span_to_source_map_span(r#await.span), - ); - return TypeId::ERROR_TYPE; - } - ast::Expression::BinaryExpression(bin_expr) => { - let value = synthesize_binary_expression( - &bin_expr.left, - bin_expr.operator, - &bin_expr.right, - checking_data, - environment, - ); - Instance::RValue(value) - } - ast::Expression::CallExpression(expr) => { - let parent = synthesize_expression(&expr.callee, environment, checking_data); - - let type_arguments = expr.type_parameters.as_ref().map(|tp| { - tp.params - .iter() - .map(|ta| { - ( - oxc_span_to_source_map_span(ta.span()), - synthesize_type_annotation(ta, environment, checking_data), - ) - }) - .collect() - }); - - let arguments: Vec = expr - .arguments - .iter() - .map(|arg| match arg { - ast::Argument::SpreadElement(expr) => { - checking_data.raise_unimplemented_error( - "spread argument", - oxc_span_to_source_map_span(expr.span), - ); - - SynthesizedArgument::NonSpread { - ty: TypeId::ERROR_TYPE, - position: oxc_span_to_source_map_span(expr.span), - } - } - ast::Argument::Expression(expr) => { - let ty = synthesize_expression(expr, environment, checking_data); - SynthesizedArgument::NonSpread { - ty, - position: oxc_span_to_source_map_span(GetSpan::span(expr)), - } - } - }) - .collect(); - - // TODO - let this_argument = None; - - let result = ezno_checker::call_type_handle_errors( - parent, - arguments, - this_argument, - type_arguments, - environment, - checking_data, - ezno_checker::events::CalledWithNew::None, - oxc_span_to_source_map_span(expr.span), - ); - Instance::RValue(result) - } - ast::Expression::ChainExpression(item) => { - checking_data.raise_unimplemented_error( - "chain expression", - oxc_span_to_source_map_span(item.span), - ); - return TypeId::ERROR_TYPE; - } - ast::Expression::ClassExpression(item) => { - checking_data.raise_unimplemented_error( - "class expression", - oxc_span_to_source_map_span(item.span), - ); - return TypeId::ERROR_TYPE; - } - ast::Expression::ConditionalExpression(item) => { - checking_data.raise_unimplemented_error( - "conditional expression", - oxc_span_to_source_map_span(item.span), - ); - return TypeId::ERROR_TYPE; - } - ast::Expression::FunctionExpression(func) => Instance::RValue(environment.new_function( - checking_data, - &OxcFunction(&**func, None), - RegisterAsType, - )), - ast::Expression::ImportExpression(item) => { - checking_data.raise_unimplemented_error( - "import expression", - oxc_span_to_source_map_span(item.span), - ); - return TypeId::ERROR_TYPE; - } - ast::Expression::LogicalExpression(item) => { - checking_data.raise_unimplemented_error( - "logical expression", - oxc_span_to_source_map_span(item.span), - ); - return TypeId::ERROR_TYPE; - } - ast::Expression::MemberExpression(expr) => match &**expr { - ast::MemberExpression::ComputedMemberExpression(comp) => { - let parent = synthesize_expression(&comp.object, environment, checking_data); - let property = synthesize_expression(&comp.expression, environment, checking_data); - Instance::RValue(environment.get_property_handle_errors( - parent, - property, - checking_data, - oxc_span_to_source_map_span(comp.span), - )) - } - ast::MemberExpression::StaticMemberExpression(expr) => { - let parent = synthesize_expression(&expr.object, environment, checking_data); - let property = checking_data.types.new_constant_type( - ezno_checker::Constant::String(expr.property.name.as_str().to_owned()), - ); - - Instance::RValue(environment.get_property_handle_errors( - parent, - property, - checking_data, - oxc_span_to_source_map_span(expr.span), - )) - } - ast::MemberExpression::PrivateFieldExpression(item) => { - checking_data.raise_unimplemented_error( - "private field expression", - oxc_span_to_source_map_span(item.span), - ); - return TypeId::ERROR_TYPE; - } - }, - ast::Expression::NewExpression(item) => { - checking_data.raise_unimplemented_error( - "new expression", - oxc_span_to_source_map_span(item.span), - ); - return TypeId::ERROR_TYPE; - } - ast::Expression::ObjectExpression(object) => { - Instance::RValue(synthesize_object(object, environment, checking_data)) - } - ast::Expression::ParenthesizedExpression(inner) => { - return synthesize_expression(&inner.expression, environment, checking_data); - } - ast::Expression::SequenceExpression(item) => { - checking_data.raise_unimplemented_error( - "sequence expression", - oxc_span_to_source_map_span(item.span), - ); - return TypeId::ERROR_TYPE; - } - ast::Expression::TaggedTemplateExpression(item) => { - checking_data.raise_unimplemented_error( - "tagged template literal expression", - oxc_span_to_source_map_span(item.span), - ); - return TypeId::ERROR_TYPE; - } - ast::Expression::ThisExpression(this) => { - checking_data.raise_unimplemented_error( - "this expression", - oxc_span_to_source_map_span(this.span), - ); - return TypeId::ERROR_TYPE; - } - ast::Expression::UnaryExpression(unary) => { - checking_data.raise_unimplemented_error( - "unary expression", - oxc_span_to_source_map_span(unary.span), - ); - return TypeId::ERROR_TYPE; - } - ast::Expression::UpdateExpression(update_expr) => { - let target = synthesize_simple_assignment_target_to_reference( - &update_expr.argument, - environment, - checking_data, - ); - let target = match target { - crate::PartiallyImplemented::Ok(target) => target, - crate::PartiallyImplemented::NotImplemented(item, span) => { - checking_data.raise_unimplemented_error(item, span); - return TypeId::ERROR_TYPE; - } - }; - // TODO need to cast as number... - let result = environment.assign_to_assignable_handle_errors( - Assignable::Reference(target), - ezno_checker::AssignmentKind::IncrementOrDecrement( - match update_expr.operator { - oxc_syntax::operator::UpdateOperator::Increment => { - ezno_checker::IncrementOrDecrement::Increment - } - oxc_syntax::operator::UpdateOperator::Decrement => { - ezno_checker::IncrementOrDecrement::Decrement - } - }, - match update_expr.prefix { - true => ezno_checker::AssignmentReturnStatus::New, - false => ezno_checker::AssignmentReturnStatus::Previous, - }, - ), - None::<&OxcExpression>, - oxc_span_to_source_map_span(update_expr.span), - checking_data, - ); - Instance::RValue(result) - } - ast::Expression::YieldExpression(item) => { - checking_data.raise_unimplemented_error( - "yield expression", - oxc_span_to_source_map_span(item.span), - ); - return TypeId::ERROR_TYPE; - } - ast::Expression::PrivateInExpression(item) => { - checking_data.raise_unimplemented_error( - "PrivateInExpression expression", - oxc_span_to_source_map_span(item.span), - ); - return TypeId::ERROR_TYPE; - } - ast::Expression::JSXElement(item) => { - checking_data.raise_unimplemented_error( - "JSXElement expression", - oxc_span_to_source_map_span(item.span), - ); - return TypeId::ERROR_TYPE; - } - ast::Expression::JSXFragment(item) => { - checking_data.raise_unimplemented_error( - "JSXFragment expression", - oxc_span_to_source_map_span(item.span), - ); - return TypeId::ERROR_TYPE; - } - ast::Expression::TSAsExpression(item) => { - checking_data.raise_unimplemented_error( - "TSAsExpression expression", - oxc_span_to_source_map_span(item.span), - ); - return TypeId::ERROR_TYPE; - } - ast::Expression::TSSatisfiesExpression(item) => { - let item_ty = synthesize_expression(&item.expression, environment, checking_data); - let to_satisfy = - synthesize_type_annotation(&item.type_annotation, environment, checking_data); - checking_data.check_satisfies( - item_ty, - to_satisfy, - oxc_span_to_source_map_span(item.span), - environment, - ); - return item_ty; - } - ast::Expression::TSTypeAssertion(item) => { - checking_data.raise_unimplemented_error( - "TSTypeAssertion expression", - oxc_span_to_source_map_span(item.span), - ); - return TypeId::ERROR_TYPE; - } - ast::Expression::TSNonNullExpression(item) => { - checking_data.raise_unimplemented_error( - "TSNonNullExpression expression", - oxc_span_to_source_map_span(item.span), - ); - return TypeId::ERROR_TYPE; - } - ast::Expression::TSInstantiationExpression(item) => { - checking_data.raise_unimplemented_error( - "TSInstantiationExpression expression", - oxc_span_to_source_map_span(item.span), - ); - return TypeId::ERROR_TYPE; - } - ast::Expression::ArrowExpression(func) => Instance::RValue(environment.new_function( - checking_data, - &OxcArrowFunction(&**func), - RegisterAsType, - )), - }; - - checking_data - .add_expression_mapping(oxc_span_to_source_map_span(expr.span()), instance.clone()); - - instance.get_value() -} - -fn synthesize_assignment( - expr: &ast::AssignmentExpression, - environment: &mut Environment, - checking_data: &mut CheckingData, -) -> TypeId { - let lhs = synthesize_assignment_target_to_assignable(&expr.left, environment, checking_data); - let lhs = match lhs { - crate::PartiallyImplemented::Ok(lhs) => lhs, - crate::PartiallyImplemented::NotImplemented(item, span) => { - checking_data.raise_unimplemented_error(item, span); - return TypeId::ERROR_TYPE; - } - }; - let operator = match expr.operator { - AssignmentOperator::Assign => ezno_checker::AssignmentKind::Assign, - AssignmentOperator::Addition => ezno_checker::AssignmentKind::Update( - ezno_checker::structures::operators::BinaryOperator::Add, - ), - AssignmentOperator::Multiplication => ezno_checker::AssignmentKind::Update( - ezno_checker::structures::operators::BinaryOperator::Multiply, - ), - AssignmentOperator::Subtraction - | AssignmentOperator::Division - | AssignmentOperator::Remainder - | AssignmentOperator::ShiftLeft - | AssignmentOperator::ShiftRight - | AssignmentOperator::ShiftRightZeroFill - | AssignmentOperator::BitwiseOR - | AssignmentOperator::BitwiseXOR - | AssignmentOperator::BitwiseAnd - | AssignmentOperator::LogicalAnd - | AssignmentOperator::LogicalOr - | AssignmentOperator::LogicalNullish - | AssignmentOperator::Exponential => { - checking_data.raise_unimplemented_error( - "this assignment operator", - oxc_span_to_source_map_span(expr.span), - ); - return TypeId::ERROR_TYPE; - } - }; - - environment.assign_to_assignable_handle_errors( - lhs, - operator, - Some(&OxcExpression(&expr.right)), - oxc_span_to_source_map_span(expr.span), - checking_data, - ) -} - -// TODO others need to be built into helper methods in the checker -fn synthesize_assignment_target_to_assignable( - target: &ast::AssignmentTarget, - environment: &mut Environment, - checking_data: &mut CheckingData, -) -> crate::PartiallyImplemented { - match target { - ast::AssignmentTarget::SimpleAssignmentTarget(simple) => { - match synthesize_simple_assignment_target_to_reference( - simple, - environment, - checking_data, - ) { - crate::PartiallyImplemented::Ok(reference) => { - crate::PartiallyImplemented::Ok(Assignable::Reference(reference)) - } - crate::PartiallyImplemented::NotImplemented(item, span) => { - crate::PartiallyImplemented::NotImplemented(item, span) - } - } - } - ast::AssignmentTarget::AssignmentTargetPattern(pattern) => match pattern { - ast::AssignmentTargetPattern::ArrayAssignmentTarget(array) => { - crate::PartiallyImplemented::NotImplemented( - "array assignment pattern", - oxc_span_to_source_map_span(array.span), - ) - } - ast::AssignmentTargetPattern::ObjectAssignmentTarget(object) => { - crate::PartiallyImplemented::NotImplemented( - "object assignment pattern", - oxc_span_to_source_map_span(object.span), - ) - } - }, - } -} - -fn synthesize_simple_assignment_target_to_reference( - simple: &ast::SimpleAssignmentTarget, - environment: &mut Environment, - checking_data: &mut CheckingData, -) -> crate::PartiallyImplemented { - match simple { - ast::SimpleAssignmentTarget::AssignmentTargetIdentifier(identifier) => { - crate::PartiallyImplemented::Ok(Reference::Variable( - identifier.name.as_str().to_owned(), - oxc_span_to_source_map_span(identifier.span), - )) - } - ast::SimpleAssignmentTarget::MemberAssignmentTarget(expr) => { - let (parent_ty, key_ty) = match &**expr { - ast::MemberExpression::ComputedMemberExpression(comp) => { - let property = - synthesize_expression(&comp.expression, environment, checking_data); - let parent = synthesize_expression(&comp.object, environment, checking_data); - (parent, property) - } - ast::MemberExpression::StaticMemberExpression(expr) => { - let parent = synthesize_expression(&expr.object, environment, checking_data); - let property = checking_data.types.new_constant_type( - ezno_checker::Constant::String(expr.property.name.as_str().to_owned()), - ); - (parent, property) - } - ast::MemberExpression::PrivateFieldExpression(item) => { - return crate::PartiallyImplemented::NotImplemented( - "private field expression", - oxc_span_to_source_map_span(item.span), - ); - } - }; - crate::PartiallyImplemented::Ok(Reference::Property { - on: parent_ty, - with: key_ty, - span: oxc_span_to_source_map_span(expr.span()), - }) - } - // TODO not sure if these exist...? - ast::SimpleAssignmentTarget::TSAsExpression(_) - | ast::SimpleAssignmentTarget::TSSatisfiesExpression(_) - | ast::SimpleAssignmentTarget::TSNonNullExpression(_) - | ast::SimpleAssignmentTarget::TSTypeAssertion(_) => { - crate::PartiallyImplemented::NotImplemented( - "left hand side typescript", - oxc_span_to_source_map_span(GetSpan::span(simple)), - ) - } - } -} - -/// TODO this logic needs to be moved to ezno-checker and -/// abstracted to use a builder pattern, which can be reused for array literals -pub(crate) fn synthesize_object( - object: &ast::ObjectExpression, - environment: &mut Environment, - checking_data: &mut CheckingData, -) -> TypeId { - let ty = environment.new_object(&mut checking_data.types, None); - for property in object.properties.iter() { - match property { - ast::ObjectPropertyKind::ObjectProperty(property) => { - let key_ty = property_key_to_type(&property.key, environment, checking_data); - let property = if let ast::Expression::FunctionExpression(func) = &property.value { - environment.new_function( - checking_data, - &OxcFunction(&**func, Some(property.kind)), - RegisterOnExistingObject, - ) - } else { - Property::Value(synthesize_expression( - &property.value, - environment, - checking_data, - )) - }; - environment.register_property(ty, key_ty, property); - } - ast::ObjectPropertyKind::SpreadProperty(spread) => checking_data - .raise_unimplemented_error( - "spread object property", - oxc_span_to_source_map_span(spread.span), - ), - } - } - ty -} - -fn synthesize_binary_expression( - lhs: &ast::Expression, - operator: oxc_syntax::operator::BinaryOperator, - rhs: &ast::Expression, - checking_data: &mut CheckingData, - environment: &mut Environment, -) -> TypeId { - let lhs_ty = synthesize_expression(lhs, environment, checking_data); - let rhs_ty = synthesize_expression(rhs, environment, checking_data); - use oxc_syntax::operator::BinaryOperator; - - let op = match operator { - BinaryOperator::StrictEquality => { - ezno_checker::structures::operators::BinaryOperator::RelationOperator( - ezno_checker::structures::operators::RelationOperator::Equal, - ) - } - BinaryOperator::Addition => ezno_checker::structures::operators::BinaryOperator::Add, - BinaryOperator::Multiplication => { - ezno_checker::structures::operators::BinaryOperator::Multiply - } - BinaryOperator::Equality - | BinaryOperator::Inequality - | BinaryOperator::StrictInequality - | BinaryOperator::LessThan - | BinaryOperator::LessEqualThan - | BinaryOperator::GreaterThan - | BinaryOperator::GreaterEqualThan - | BinaryOperator::ShiftLeft - | BinaryOperator::ShiftRight - | BinaryOperator::ShiftRightZeroFill - | BinaryOperator::Subtraction - | BinaryOperator::Division - | BinaryOperator::Remainder - | BinaryOperator::BitwiseOR - | BinaryOperator::BitwiseXOR - | BinaryOperator::BitwiseAnd - | BinaryOperator::In - | BinaryOperator::Instanceof - | BinaryOperator::Exponential => { - checking_data.raise_unimplemented_error( - "this operator", - oxc_span_to_source_map_span(lhs.span()), - ); - - return TypeId::ERROR_TYPE; - } - }; - ezno_checker::evaluate_binary_operator_handle_errors( - op, - (lhs_ty, oxc_span_to_source_map_span(GetSpan::span(lhs))), - (rhs_ty, oxc_span_to_source_map_span(GetSpan::span(rhs))), - environment, - checking_data, - ) -} - -struct OxcExpression<'a, 'b>(pub(crate) &'a ast::Expression<'b>); - -impl ezno_checker::SynthesizableExpression for OxcExpression<'_, '_> { - fn synthesize_expression( - &self, - environment: &mut Environment, - checking_data: &mut CheckingData, - ) -> TypeId { - synthesize_expression(self.0, environment, checking_data) - } - - fn get_position(&self) -> ezno_checker::Span { - oxc_span_to_source_map_span(self.0.span()) - } -} diff --git a/crates/oxc_type_synthesis/src/functions.rs b/crates/oxc_type_synthesis/src/functions.rs deleted file mode 100644 index 90a7383bd27e6..0000000000000 --- a/crates/oxc_type_synthesis/src/functions.rs +++ /dev/null @@ -1,285 +0,0 @@ -use ezno_checker::{ - context::VariableRegisterBehavior, - types::functions::{SynthesizedParameter, SynthesizedParameters}, - GenericTypeParameters, SynthesizableFunction, TypeId, -}; -use oxc_ast::ast; - -use crate::{ - oxc_span_to_source_map_span, - statements_and_declarations::{register_variable, synthesize_statements}, - types::synthesize_type_annotation, -}; - -pub(crate) struct OxcFunction<'a, 'b>(pub &'a ast::Function<'b>, pub Option); - -impl<'a, 'b> SynthesizableFunction for OxcFunction<'a, 'b> { - fn is_declare(&self) -> bool { - self.0.is_ts_declare_function() - } - - fn is_async(&self) -> bool { - self.0.modifiers.contains(ast::ModifierKind::Async) - } - - fn get_set_generator_or_none(&self) -> ezno_checker::GetSetGeneratorOrNone { - if self.0.generator { - ezno_checker::GetSetGeneratorOrNone::Generator - } else if let Some(prop_kind) = self.1 { - match prop_kind { - ast::PropertyKind::Init => ezno_checker::GetSetGeneratorOrNone::None, - ast::PropertyKind::Get => ezno_checker::GetSetGeneratorOrNone::Get, - ast::PropertyKind::Set => ezno_checker::GetSetGeneratorOrNone::Set, - } - } else { - ezno_checker::GetSetGeneratorOrNone::None - } - } - - fn id(&self) -> ezno_checker::context::FunctionId { - ezno_checker::context::FunctionId(oxc_span_to_source_map_span(self.0.span)) - } - - fn this_constraint( - &self, - _environment: &mut ezno_checker::Environment, - _checking_data: &mut ezno_checker::CheckingData, - ) -> Option { - // TODO - None - } - - fn parameters( - &self, - environment: &mut ezno_checker::Environment, - checking_data: &mut ezno_checker::CheckingData, - ) -> SynthesizedParameters { - synthesize_parameters(&self.0.params, environment, checking_data) - } - - fn body( - &self, - environment: &mut ezno_checker::Environment, - checking_data: &mut ezno_checker::CheckingData, - ) { - let body = self.0.body.as_ref().expect("trying to synthesize declare function"); - synthesize_statements(&body.statements, environment, checking_data); - } - - fn type_parameters( - &self, - environment: &mut ezno_checker::Environment, - checking_data: &mut ezno_checker::CheckingData, - ) -> Option { - let type_parameters = self.0.type_parameters.as_deref(); - synthesize_type_parameters(type_parameters, environment, checking_data) - } - - fn return_type_annotation( - &self, - environment: &mut ezno_checker::Environment, - checking_data: &mut ezno_checker::CheckingData, - ) -> Option<(TypeId, ezno_checker::Span)> { - self.0.return_type.as_ref().map(|ta| { - ( - synthesize_type_annotation(&ta.type_annotation, environment, checking_data), - oxc_span_to_source_map_span(ta.span), - ) - }) - } -} - -pub(crate) fn synthesize_type_parameters( - type_parameters: Option<&oxc_ast::ast::TSTypeParameterDeclaration>, - environment: &mut ezno_checker::Environment, - checking_data: &mut ezno_checker::CheckingData, -) -> Option { - type_parameters.as_ref().map(|params| { - params - .params - .iter() - .map(|ta| { - // TODO effects in a map :/ - let constraint_type = ta - .constraint - .as_ref() - .map(|ta| synthesize_type_annotation(ta, environment, checking_data)); - let default_type = ta - .default - .as_ref() - .map(|ta| synthesize_type_annotation(ta, environment, checking_data)); - environment.new_explicit_type_parameter( - ta.name.name.as_str(), - constraint_type, - default_type, - &mut checking_data.types, - ) - }) - .collect() - }) -} - -pub(crate) fn synthesize_parameters( - params: &ast::FormalParameters, - environment: &mut ezno_checker::Environment, - checking_data: &mut ezno_checker::CheckingData, -) -> SynthesizedParameters { - let (mut parameters, optional_parameters, rest_parameter) = (Vec::new(), Vec::new(), None); - - for param in params.items.iter() { - let annotation = - param.pattern.type_annotation.as_ref().map(|ta| { - synthesize_type_annotation(&ta.type_annotation, environment, checking_data) - }); - - let param_type = register_variable( - ¶m.pattern.kind, - ¶m.span, - environment, - checking_data, - VariableRegisterBehavior::FunctionParameter { annotation }, - ); - - match ¶m.pattern.kind { - p @ (ast::BindingPatternKind::BindingIdentifier(_) - | ast::BindingPatternKind::ObjectPattern(_) - | ast::BindingPatternKind::ArrayPattern(_)) => { - parameters.push(SynthesizedParameter { - name: match param_to_string(p) { - crate::PartiallyImplemented::Ok(name) => name, - crate::PartiallyImplemented::NotImplemented(item, span) => { - checking_data.raise_unimplemented_error(item, span); - "temp".into() - } - }, - ty: param_type, - position: oxc_span_to_source_map_span(param.span), - }); - } - ast::BindingPatternKind::AssignmentPattern(item) => checking_data - .raise_unimplemented_error( - "parameter with default value", - oxc_span_to_source_map_span(item.span), - ), - // ast::BindingPatternKind::RestElement(element) => { - // rest_parameter = Some(SynthesizedRestParameter { - // name: param_to_string(&element.argument.kind), - // item_type: param_type, - // position: oxc_span_to_source_map_span(element.span), - // }) - // } - } - } - - SynthesizedParameters { parameters, optional_parameters, rest_parameter } -} - -fn param_to_string(binding: &ast::BindingPatternKind) -> crate::PartiallyImplemented { - match binding { - ast::BindingPatternKind::BindingIdentifier(ident) => { - crate::PartiallyImplemented::Ok(ident.name.as_str().to_owned()) - } - ast::BindingPatternKind::ObjectPattern(param) => { - crate::PartiallyImplemented::NotImplemented( - "stringing complex parameters", - oxc_span_to_source_map_span(param.span), - ) - } - ast::BindingPatternKind::ArrayPattern(param) => { - crate::PartiallyImplemented::NotImplemented( - "stringing complex parameters", - oxc_span_to_source_map_span(param.span), - ) - } - ast::BindingPatternKind::AssignmentPattern(param) => { - crate::PartiallyImplemented::NotImplemented( - "stringing complex parameters", - oxc_span_to_source_map_span(param.span), - ) - } - } -} - -pub(crate) struct OxcArrowFunction<'a, 'b>(pub &'a ast::ArrowExpression<'b>); - -impl<'a, 'b> SynthesizableFunction for OxcArrowFunction<'a, 'b> { - fn is_declare(&self) -> bool { - false - } - - fn is_async(&self) -> bool { - self.0.r#async - } - - fn parameters( - &self, - environment: &mut ezno_checker::Environment, - checking_data: &mut ezno_checker::CheckingData, - ) -> SynthesizedParameters { - synthesize_parameters(&self.0.params, environment, checking_data) - } - - fn body( - &self, - environment: &mut ezno_checker::Environment, - checking_data: &mut ezno_checker::CheckingData, - ) { - if self.0.expression { - if let Some(ast::Statement::ExpressionStatement(expr)) = self.0.body.statements.get(0) { - let returned = crate::expressions::synthesize_expression( - &expr.expression, - environment, - checking_data, - ); - environment.return_value(returned) - } else { - unreachable!() - } - } else { - synthesize_statements(&self.0.body.statements, environment, checking_data) - } - } - - fn type_parameters( - &self, - environment: &mut ezno_checker::Environment, - checking_data: &mut ezno_checker::CheckingData, - ) -> Option { - let type_parameters = self.0.type_parameters.as_deref(); - synthesize_type_parameters(type_parameters, environment, checking_data) - } - - fn return_type_annotation( - &self, - environment: &mut ezno_checker::Environment, - checking_data: &mut ezno_checker::CheckingData, - ) -> Option<(TypeId, ezno_checker::Span)> { - self.0.return_type.as_ref().map(|ta| { - ( - synthesize_type_annotation(&ta.type_annotation, environment, checking_data), - oxc_span_to_source_map_span(ta.span), - ) - }) - } - - fn get_set_generator_or_none(&self) -> ezno_checker::GetSetGeneratorOrNone { - if self.0.generator { - ezno_checker::GetSetGeneratorOrNone::Generator - } else { - ezno_checker::GetSetGeneratorOrNone::None - } - } - - fn id(&self) -> ezno_checker::context::FunctionId { - ezno_checker::context::FunctionId(oxc_span_to_source_map_span(self.0.span)) - } - - fn this_constraint( - &self, - _environment: &mut ezno_checker::Environment, - _checking_data: &mut ezno_checker::CheckingData, - ) -> Option { - // TODO - None - } -} diff --git a/crates/oxc_type_synthesis/src/interfaces.rs b/crates/oxc_type_synthesis/src/interfaces.rs deleted file mode 100644 index dc331d129746f..0000000000000 --- a/crates/oxc_type_synthesis/src/interfaces.rs +++ /dev/null @@ -1,167 +0,0 @@ -use ezno_checker::{CheckingData, Environment, TypeId}; -use oxc_ast::ast; - -use crate::{ - oxc_span_to_source_map_span, property_key_to_type, - statements_and_declarations::synthesize_statement, types::synthesize_type_annotation, -}; - -pub(crate) fn synthesize_interface( - interface: &ast::TSInterfaceDeclaration, - interface_id: TypeId, - environment: &mut Environment, - checking_data: &mut CheckingData, -) { - synthesize_signatures(&interface.body.body, environment, checking_data, interface_id); -} - -pub(crate) fn synthesize_signatures( - signatures: &[ast::TSSignature], - environment: &mut Environment, - checking_data: &mut CheckingData, - onto: TypeId, -) { - for declaration in signatures.iter() { - match declaration { - ast::TSSignature::TSPropertySignature(property) => { - let key_ty = property_key_to_type(&property.key, environment, checking_data); - let value_ty = synthesize_type_annotation( - &property.type_annotation.as_ref().unwrap().type_annotation, - environment, - checking_data, - ); - environment.register_property( - onto, - key_ty, - ezno_checker::Property::Value(value_ty), - ); - } - ast::TSSignature::TSIndexSignature(item) => { - checking_data.raise_unimplemented_error( - "ts index signature", - oxc_span_to_source_map_span(item.span), - ); - } - ast::TSSignature::TSCallSignatureDeclaration(item) => { - checking_data.raise_unimplemented_error( - "ts call signature", - oxc_span_to_source_map_span(item.span), - ); - } - ast::TSSignature::TSConstructSignatureDeclaration(item) => { - checking_data.raise_unimplemented_error( - "ts construct signature", - oxc_span_to_source_map_span(item.span), - ); - } - ast::TSSignature::TSMethodSignature(method) => { - // TODO reuse more functions - let key_ty = property_key_to_type(&method.key, environment, checking_data); - - let ((type_parameters, parameters, returned, constant_fn), stuff, _) = environment - .new_lexical_environment_fold_into_parent( - ezno_checker::Scope::FunctionReference {}, - checking_data, - |environment, checking_data| { - let type_parameters = crate::functions::synthesize_type_parameters( - method.type_parameters.as_deref(), - environment, - checking_data, - ); - - let parameters = crate::functions::synthesize_parameters( - &method.params, - environment, - checking_data, - ); - - let (returned, constant_fn) = - if let Some(ta) = method.return_type.as_ref() { - let mut ta = &ta.type_annotation; - let mut constant_fn = None; - - // TODO temp - if let ast::TSType::TSIntersectionType(intersection) = ta { - if let ast::TSType::TSTypeReference(type_ref) = - intersection.types.last().unwrap() - { - if let ( - ast::TSTypeName::QualifiedName(ref qual), - Some(tp), - ) = (&type_ref.type_name, &type_ref.type_parameters) - { - if let ast::TSTypeName::IdentifierReference( - ref parent_name, - ) = qual.left - { - if parent_name.name == "Ezno" { - // *remove* the right annotation - // TODO discards middle ones - ta = intersection.types.first().unwrap(); - - match qual.right.name.as_str() { - "Performs" => compute_internal_events( - tp, - environment, - checking_data, - ), - "ConstantFunction" => { - if let Some( - ast::TSType::TSLiteralType(lit), - ) = tp.params.first() - { - if let ast::TSLiteral::StringLiteral(string) = &lit.literal { - constant_fn = Some(string.value.as_str().to_owned()); - } - } - } - unknown => panic!("Ezno.{}", unknown), - } - } - } - } - } - } - - (synthesize_type_annotation(ta, environment, checking_data), constant_fn) - } else { - (TypeId::UNDEFINED_TYPE, None) - }; - (type_parameters, parameters, returned, constant_fn) - }, - ); - - let func_ty = checking_data.types.new_function_type_reference( - type_parameters, - parameters, - returned, - oxc_span_to_source_map_span(method.span), - stuff.unwrap().0, - constant_fn, - ); - - environment.register_property(onto, key_ty, ezno_checker::Property::Value(func_ty)); - } - } - } -} - -fn compute_internal_events( - tp: &ast::TSTypeParameterInstantiation, - environment: &mut Environment, - checking_data: &mut CheckingData, -) { - if let Some(ast::TSType::TSLiteralType(lit)) = tp.params.first() { - if let ast::TSLiteral::StringLiteral(string) = &lit.literal { - let source = string.value.as_str().to_owned(); - - let allocator = oxc_allocator::Allocator::default(); - let ret = oxc_parser::Parser::new(&allocator, &source, oxc_span::SourceType::default()) - .parse(); - - for statement in ret.program.body.iter() { - synthesize_statement(statement, environment, checking_data) - } - } - } -} diff --git a/crates/oxc_type_synthesis/src/lib.rs b/crates/oxc_type_synthesis/src/lib.rs deleted file mode 100644 index 836b7c6935378..0000000000000 --- a/crates/oxc_type_synthesis/src/lib.rs +++ /dev/null @@ -1,83 +0,0 @@ -#![allow(clippy::all, clippy::restriction, clippy::pedantic, clippy::nursery)] - -use ezno_checker::{ - events::Event, types::TypeStore, CheckingData, Environment, FSResolver, Root, Scope, - Span as SourceMapSpan, TypeCheckSettings, TypeId, TypeMappings, -}; -pub use ezno_checker::{ - Diagnostic, DiagnosticKind, DiagnosticsContainer, SourceId as EznoSourceId, Span as EznoSpan, -}; -use oxc_ast::ast; -use oxc_span::Span; -use statements_and_declarations::synthesize_statements; - -mod expressions; -mod functions; -mod interfaces; -mod statements_and_declarations; -mod types; - -pub fn synthesize_program( - program: &ast::Program, - resolver: T, -) -> (DiagnosticsContainer, Vec, TypeStore, TypeMappings, Root) { - let default_settings = TypeCheckSettings::default(); - let mut checking_data = CheckingData::new(default_settings, &resolver); - - let mut root = Root::new_with_primitive_references_and_ezno_magic(); - - let (_, stuff, _) = root.new_lexical_environment_fold_into_parent( - Scope::Block {}, - &mut checking_data, - |environment, checking_data| { - synthesize_statements(&program.body, environment, checking_data); - }, - ); - - ( - checking_data.diagnostics_container, - stuff.expect("block will always return events").0, - checking_data.types, - checking_data.type_mappings, - root, - ) -} - -fn oxc_span_to_source_map_span(span: Span) -> SourceMapSpan { - SourceMapSpan { - start: span.start, - end: span.end, - // TODO!! - source_id: ezno_checker::SourceId::NULL, - } -} - -fn property_key_to_type( - key: &ast::PropertyKey, - environment: &mut Environment, - checking_data: &mut CheckingData, -) -> TypeId { - match key { - ast::PropertyKey::Identifier(ident) => checking_data - .types - .new_constant_type(ezno_checker::Constant::String(ident.name.as_str().to_string())), - ast::PropertyKey::PrivateIdentifier(item) => { - checking_data.raise_unimplemented_error( - "private identifier", - oxc_span_to_source_map_span(item.span), - ); - - TypeId::ERROR_TYPE - } - ast::PropertyKey::Expression(expr) => { - // TODO make key into key - expressions::synthesize_expression(expr, environment, checking_data) - } - } -} - -// Marker type -pub enum PartiallyImplemented { - Ok(T), - NotImplemented(&'static str, EznoSpan), -} diff --git a/crates/oxc_type_synthesis/src/statements_and_declarations.rs b/crates/oxc_type_synthesis/src/statements_and_declarations.rs deleted file mode 100644 index 8cc6dec2a4860..0000000000000 --- a/crates/oxc_type_synthesis/src/statements_and_declarations.rs +++ /dev/null @@ -1,428 +0,0 @@ -use std::{borrow::Cow, collections::HashMap}; - -use ezno_checker::{ - self, context::VariableId, structures::variables::VariableMutability, CheckingData, - Environment, FSResolver, RegisterOnExisting, TypeId, -}; -use oxc_ast::{ - self, - ast::{self, Statement}, -}; -use oxc_span::GetSpan; - -use super::{oxc_span_to_source_map_span, types::synthesize_type_annotation}; -use crate::{ - expressions::{self, synthesize_expression}, - functions::OxcFunction, -}; - -/// See `checking.md`s Hoisting section in docs for details -pub(crate) fn hoist_statements( - statements: &[ast::Statement], - environment: &mut Environment, - checking_data: &mut CheckingData, -) { - // TODO temp? - let mut idx_to_types = HashMap::new(); - - // First stage - for (idx, statement) in statements.iter().enumerate() { - if let Statement::Declaration(declaration) = statement { - match declaration { - ast::Declaration::UsingDeclaration(_) => todo!(), - ast::Declaration::VariableDeclaration(_) - | ast::Declaration::FunctionDeclaration(_) => {} - ast::Declaration::ClassDeclaration(_) => {} - ast::Declaration::TSTypeAliasDeclaration(alias) => { - if alias.type_parameters.is_some() { - checking_data.raise_unimplemented_error( - "type alias with type parameters", - oxc_span_to_source_map_span(alias.span), - ); - } - - // TODO eager and so won't work with hoisting - let to = synthesize_type_annotation( - &alias.type_annotation, - environment, - checking_data, - ); - - environment.new_alias(&alias.id.name.as_str(), to, &mut checking_data.types); - } - ast::Declaration::TSInterfaceDeclaration(interface) => { - let ty = environment.new_interface( - &interface.id.name.as_str(), - oxc_span_to_source_map_span(interface.span), - &mut checking_data.types, - ); - idx_to_types.insert(idx, ty); - } - ast::Declaration::TSEnumDeclaration(_) => {} - ast::Declaration::TSModuleDeclaration(_) => {} - ast::Declaration::TSImportEqualsDeclaration(_) => {} - } - } - } - - // Second stage - for (idx, statement) in statements.iter().enumerate() { - match statement { - Statement::ModuleDeclaration(_) => {} - Statement::Declaration(declaration) => match declaration { - ast::Declaration::UsingDeclaration(_) => todo!(), - ast::Declaration::VariableDeclaration(declaration) => { - let is_declare = declaration.modifiers.contains(ast::ModifierKind::Declare); - let is_const = matches!(declaration.kind, ast::VariableDeclarationKind::Const); - - for declaration in declaration.declarations.iter() { - let ty = declaration.id.type_annotation.as_ref().map(|ta| { - synthesize_type_annotation( - &ta.type_annotation, - environment, - checking_data, - ) - }); - - // TODO save ty - let behavior = if is_declare { - ezno_checker::context::VariableRegisterBehavior::Declare { - base: ty.unwrap(), - } - } else { - ezno_checker::context::VariableRegisterBehavior::Register { - mutability: if is_const { - VariableMutability::Constant - } else { - VariableMutability::Mutable { reassignment_constraint: ty } - }, - } - }; - register_variable( - &declaration.id.kind, - &declaration.span, - environment, - checking_data, - behavior, - ); - } - } - ast::Declaration::FunctionDeclaration(func) => { - // TODO unsynthesized function? ... - let behavior = ezno_checker::context::VariableRegisterBehavior::Register { - // TODO - mutability: - ezno_checker::structures::variables::VariableMutability::Constant, - }; - // TODO catch reassignment - let _result = environment.register_variable( - func.id.as_ref().unwrap().name.as_str(), - VariableId(oxc_span_to_source_map_span(func.span)), - behavior, - &mut checking_data.types, - ); - } - ast::Declaration::ClassDeclaration(_) => {} - ast::Declaration::TSTypeAliasDeclaration(_) => {} - ast::Declaration::TSInterfaceDeclaration(interface) => { - let ty = idx_to_types.remove(&idx).unwrap(); - crate::interfaces::synthesize_interface( - interface, - ty, - environment, - checking_data, - ) - } - ast::Declaration::TSEnumDeclaration(_) => {} - ast::Declaration::TSModuleDeclaration(_) => {} - ast::Declaration::TSImportEqualsDeclaration(_) => {} - }, - _ => {} - } - } - - // Third stage - for statement in statements { - if let Statement::Declaration(declaration) = statement { - match declaration { - ast::Declaration::FunctionDeclaration(func) => environment.new_function( - checking_data, - &OxcFunction(&func, None), - RegisterOnExisting(func.id.as_ref().unwrap().name.as_str().to_owned()), - ), - _ => {} - } - } - } -} - -/// TODO different modes for parameters -/// -/// Returns the type for reasons -pub(crate) fn register_variable( - pattern: &ast::BindingPatternKind, - span: &oxc_span::Span, - environment: &mut Environment, - checking_data: &mut CheckingData, - behaviour: ezno_checker::context::VariableRegisterBehavior, -) -> TypeId { - match &pattern { - ast::BindingPatternKind::BindingIdentifier(ident) => environment - .register_variable( - ident.name.as_str(), - VariableId(oxc_span_to_source_map_span(span.clone())), - behaviour, - &mut checking_data.types, - ) - .unwrap(), - ast::BindingPatternKind::ObjectPattern(item) => { - checking_data.raise_unimplemented_error( - "yield expression", - oxc_span_to_source_map_span(item.span), - ); - TypeId::ERROR_TYPE - } - ast::BindingPatternKind::ArrayPattern(item) => { - checking_data.raise_unimplemented_error( - "yield expression", - oxc_span_to_source_map_span(item.span), - ); - TypeId::ERROR_TYPE - } - ast::BindingPatternKind::AssignmentPattern(item) => { - checking_data.raise_unimplemented_error( - "yield expression", - oxc_span_to_source_map_span(item.span), - ); - TypeId::ERROR_TYPE - } - } -} - -pub(crate) fn synthesize_statement( - statement: &ast::Statement, - environment: &mut Environment, - checking_data: &mut CheckingData, -) { - match statement { - ast::Statement::BlockStatement(block) => { - synthesize_statements(&block.body, environment, checking_data); - } - ast::Statement::BreakStatement(item) => checking_data - .raise_unimplemented_error("break statement", oxc_span_to_source_map_span(item.span)), - ast::Statement::ContinueStatement(item) => checking_data.raise_unimplemented_error( - "continue statement", - oxc_span_to_source_map_span(item.span), - ), - ast::Statement::EmptyStatement(_) => {} - ast::Statement::DebuggerStatement(_) => {} - ast::Statement::DoWhileStatement(item) => checking_data.raise_unimplemented_error( - "do while statement", - oxc_span_to_source_map_span(item.span), - ), - ast::Statement::ExpressionStatement(expr) => { - expressions::synthesize_expression(&expr.expression, environment, checking_data); - } - ast::Statement::ForInStatement(_) - | ast::Statement::ForOfStatement(_) - | ast::Statement::ForStatement(_) => { - checking_data.raise_unimplemented_error( - "for statements", - oxc_span_to_source_map_span(statement.span()), - ); - } - ast::Statement::IfStatement(if_stmt) => { - synthesize_if_statement(if_stmt, environment, checking_data) - } - ast::Statement::LabeledStatement(item) => checking_data - .raise_unimplemented_error("labeled statement", oxc_span_to_source_map_span(item.span)), - ast::Statement::ReturnStatement(ret_stmt) => { - if let Some(ref value) = ret_stmt.argument { - let returned = - expressions::synthesize_expression(value, environment, checking_data); - environment.return_value(returned) - } else { - environment.return_value(TypeId::UNDEFINED_TYPE) - } - } - ast::Statement::SwitchStatement(_) => { - checking_data.raise_unimplemented_error( - "switch statement", - oxc_span_to_source_map_span(statement.span()), - ); - } - ast::Statement::ThrowStatement(throw_stmt) => { - let thrown = expressions::synthesize_expression( - &throw_stmt.argument, - environment, - checking_data, - ); - environment.throw_value(thrown) - } - ast::Statement::TryStatement(stmt) => { - synthesize_try_statement(stmt, environment, checking_data) - } - ast::Statement::WhileStatement(_) => { - checking_data.raise_unimplemented_error( - "while statement", - oxc_span_to_source_map_span(statement.span()), - ); - } - ast::Statement::WithStatement(item) => checking_data - .raise_unimplemented_error("with statement", oxc_span_to_source_map_span(item.span)), - ast::Statement::ModuleDeclaration(item) => checking_data.raise_unimplemented_error( - "module declaration", - oxc_span_to_source_map_span(item.span()), - ), - ast::Statement::Declaration(declaration) => { - if !matches!(declaration, ast::Declaration::FunctionDeclaration(..)) { - synthesize_declaration(declaration, environment, checking_data) - } - } - } -} - -// TODO full type narrowing behavior -fn synthesize_if_statement( - if_stmt: &ast::IfStatement, - environment: &mut Environment, - checking_data: &mut CheckingData, -) { - let condition = synthesize_expression(&if_stmt.test, environment, checking_data); - - if let ezno_checker::TruthyFalsy::Decidable(value) = - environment.is_type_truthy_falsy(condition, &checking_data.types) - { - checking_data - .raise_decidable_result_error(oxc_span_to_source_map_span(if_stmt.span), value); - - if value { - synthesize_statement(&if_stmt.consequent, environment, checking_data); - return; - } - } else { - synthesize_statement(&if_stmt.consequent, environment, checking_data); - } - - if let Some(ref alternative) = if_stmt.alternate { - synthesize_statement(alternative, environment, checking_data) - } -} - -pub(crate) fn synthesize_statements( - statements: &[oxc_ast::ast::Statement], - environment: &mut Environment, - checking_data: &mut ezno_checker::CheckingData, -) { - // TODO union this into one function - hoist_statements(statements, environment, checking_data); - - for statement in statements.iter() { - synthesize_statement(statement, environment, checking_data); - } -} - -// TODO some of this logic should be moved to the checker crate -fn synthesize_try_statement( - stmt: &ast::TryStatement, - environment: &mut Environment, - checking_data: &mut CheckingData, -) { - let throw_type: TypeId = - environment.new_try_context(checking_data, |environment, checking_data| { - synthesize_statements(&stmt.block.body, environment, checking_data); - }); - - if let Some(ref handler) = stmt.handler { - // TODO catch when never - environment.new_lexical_environment_fold_into_parent( - ezno_checker::Scope::Block {}, - checking_data, - |environment, checking_data| { - if let Some(ref clause) = handler.param { - // TODO clause.type_annotation - register_variable( - &clause.kind, - // TODO clause has no span - &handler.span, - environment, - checking_data, - ezno_checker::context::VariableRegisterBehavior::CatchVariable { - ty: throw_type, - }, - ); - } - synthesize_statements(&handler.body.body, environment, checking_data); - }, - ); - } - // TODO finally -} - -pub(crate) fn synthesize_declaration( - declaration: &ast::Declaration, - environment: &mut Environment, - checking_data: &mut CheckingData, -) { - match declaration { - ast::Declaration::UsingDeclaration(_) => todo!(), - - ast::Declaration::VariableDeclaration(variable_declaration) => { - if variable_declaration.modifiers.contains(ast::ModifierKind::Declare) { - return; - } - - for declaration in variable_declaration.declarations.iter() { - // TODO get from existing!!!! - let var_ty_and_pos = declaration.id.type_annotation.as_ref().map(|ta| { - ( - synthesize_type_annotation(&ta.type_annotation, environment, checking_data), - ta.span, - ) - }); - - let value_ty = if let Some(value) = declaration.init.as_ref() { - let value_ty = - expressions::synthesize_expression(value, environment, checking_data); - - if let Some((var_ty, ta_pos)) = var_ty_and_pos { - // TODO temp - let ta_span = oxc_span_to_source_map_span(ta_pos); - let value_span = - oxc_span_to_source_map_span(oxc_span::GetSpan::span(value)); - - ezno_checker::check_variable_initialization( - (var_ty, Cow::Owned(ta_span)), - (value_ty, Cow::Owned(value_span)), - environment, - checking_data, - ); - } - value_ty - } else { - // TODO if const raise error - TypeId::UNDEFINED_TYPE - }; - - let id = VariableId(oxc_span_to_source_map_span(declaration.span)); - environment.register_initial_variable_declaration_value(id, value_ty) - } - } - ast::Declaration::FunctionDeclaration(_) => unreachable!("should be hoisted..."), - ast::Declaration::ClassDeclaration(item) => checking_data - .raise_unimplemented_error("class declaration", oxc_span_to_source_map_span(item.span)), - ast::Declaration::TSTypeAliasDeclaration(_) => {} - ast::Declaration::TSInterfaceDeclaration(_) => {} - ast::Declaration::TSEnumDeclaration(item) => checking_data - .raise_unimplemented_error("enum declaration", oxc_span_to_source_map_span(item.span)), - ast::Declaration::TSModuleDeclaration(item) => checking_data.raise_unimplemented_error( - "module declaration", - oxc_span_to_source_map_span(item.span), - ), - ast::Declaration::TSImportEqualsDeclaration(item) => checking_data - .raise_unimplemented_error( - "import equals declaration", - oxc_span_to_source_map_span(item.span), - ), - } -} diff --git a/crates/oxc_type_synthesis/src/types.rs b/crates/oxc_type_synthesis/src/types.rs deleted file mode 100644 index 30dc5c8554b39..0000000000000 --- a/crates/oxc_type_synthesis/src/types.rs +++ /dev/null @@ -1,257 +0,0 @@ -use ezno_checker::{CheckingData, Environment, FSResolver, TypeId}; -use oxc_ast::ast; - -use crate::oxc_span_to_source_map_span; - -pub(crate) fn synthesize_type_annotation( - ta: &ast::TSType, - environment: &mut Environment, - checking_data: &mut CheckingData, -) -> TypeId { - match ta { - ast::TSType::TSAnyKeyword(_) => TypeId::ANY_TYPE, - ast::TSType::TSBigIntKeyword(item) => { - checking_data.raise_unimplemented_error( - "big int keyword", - oxc_span_to_source_map_span(item.span), - ); - TypeId::ERROR_TYPE - } - ast::TSType::TSBooleanKeyword(_) => TypeId::BOOLEAN_TYPE, - ast::TSType::TSNeverKeyword(_) => TypeId::NEVER_TYPE, - ast::TSType::TSNullKeyword(_) => TypeId::NULL_TYPE, - ast::TSType::TSNumberKeyword(_) => TypeId::NUMBER_TYPE, - ast::TSType::TSObjectKeyword(_) => TypeId::OBJECT_TYPE, - ast::TSType::TSStringKeyword(_) => TypeId::STRING_TYPE, - ast::TSType::TSSymbolKeyword(item) => { - checking_data.raise_unimplemented_error( - "symbol keyword", - oxc_span_to_source_map_span(item.span), - ); - TypeId::ERROR_TYPE - } - ast::TSType::TSThisKeyword(item) => { - checking_data - .raise_unimplemented_error("this type", oxc_span_to_source_map_span(item.span)); - TypeId::ERROR_TYPE - } - // 🔥 - ast::TSType::TSVoidKeyword(_) | ast::TSType::TSUndefinedKeyword(_) => { - TypeId::UNDEFINED_TYPE - } - ast::TSType::TSUnknownKeyword(item) => { - checking_data - .raise_unimplemented_error("unknown type", oxc_span_to_source_map_span(item.span)); - TypeId::ERROR_TYPE - } - ast::TSType::TSArrayType(item) => { - checking_data - .raise_unimplemented_error("array type", oxc_span_to_source_map_span(item.span)); - TypeId::ERROR_TYPE - } - ast::TSType::TSConditionalType(condition) => { - let check_type = - synthesize_type_annotation(&condition.check_type, environment, checking_data); - let extends = - synthesize_type_annotation(&condition.extends_type, environment, checking_data); - let lhs = synthesize_type_annotation(&condition.true_type, environment, checking_data); - let rhs = synthesize_type_annotation(&condition.false_type, environment, checking_data); - - checking_data.types.new_conditional_extends_type(check_type, extends, lhs, rhs) - } - ast::TSType::TSConstructorType(item) => { - checking_data.raise_unimplemented_error( - "constructor type", - oxc_span_to_source_map_span(item.span), - ); - TypeId::ERROR_TYPE - } - ast::TSType::TSFunctionType(item) => { - checking_data - .raise_unimplemented_error("function type", oxc_span_to_source_map_span(item.span)); - TypeId::ERROR_TYPE - } - ast::TSType::TSImportType(item) => { - checking_data - .raise_unimplemented_error("import type", oxc_span_to_source_map_span(item.span)); - TypeId::ERROR_TYPE - } - ast::TSType::TSIndexedAccessType(item) => { - checking_data.raise_unimplemented_error( - "index access type", - oxc_span_to_source_map_span(item.span), - ); - TypeId::ERROR_TYPE - } - ast::TSType::TSInferType(item) => { - checking_data - .raise_unimplemented_error("infer type", oxc_span_to_source_map_span(item.span)); - TypeId::ERROR_TYPE - } - ast::TSType::TSUnionType(r#union) => { - // Borrow checker doesn't like :( - // r#union - // .types - // .iter() - // .map(|ta| synthesize_type_annotation(ta, environment, checking_data)) - // .reduce(|lhs, rhs| checking_data.types.new_or_type(lhs, rhs)) - // .unwrap(), - let mut iter = r#union.types.iter(); - let mut acc = - synthesize_type_annotation(iter.next().unwrap(), environment, checking_data); - for next in iter { - let rhs = synthesize_type_annotation(next, environment, checking_data); - acc = checking_data.types.new_or_type(acc, rhs); - } - acc - } - ast::TSType::TSIntersectionType(intersection) => { - let mut iter = intersection.types.iter(); - let mut acc = - synthesize_type_annotation(iter.next().unwrap(), environment, checking_data); - for next in iter { - let rhs = synthesize_type_annotation(next, environment, checking_data); - acc = checking_data.types.new_and_type(acc, rhs); - } - acc - } - ast::TSType::TSLiteralType(lit) => match &lit.literal { - ast::TSLiteral::NullLiteral(_) => ezno_checker::TypeId::NULL_TYPE, - ast::TSLiteral::BooleanLiteral(bool) => { - checking_data.types.new_constant_type(ezno_checker::Constant::Boolean(bool.value)) - } - ast::TSLiteral::NumberLiteral(number) => checking_data.types.new_constant_type( - number - .value - .try_into() - .map(ezno_checker::Constant::Number) - .unwrap_or(ezno_checker::Constant::NaN), - ), - ast::TSLiteral::StringLiteral(string) => checking_data.types.new_constant_type( - ezno_checker::Constant::String(string.value.as_str().to_owned()), - ), - ast::TSLiteral::BigintLiteral(item) => { - checking_data.raise_unimplemented_error( - "big int literal type", - oxc_span_to_source_map_span(item.span), - ); - TypeId::ERROR_TYPE - } - ast::TSLiteral::RegExpLiteral(item) => { - checking_data.raise_unimplemented_error( - "regexp literal type", - oxc_span_to_source_map_span(item.span), - ); - TypeId::ERROR_TYPE - } - ast::TSLiteral::TemplateLiteral(item) => { - checking_data.raise_unimplemented_error( - "template literal type", - oxc_span_to_source_map_span(item.span), - ); - TypeId::ERROR_TYPE - } - ast::TSLiteral::UnaryExpression(item) => { - checking_data.raise_unimplemented_error( - "unary expression type", - oxc_span_to_source_map_span(item.span), - ); - TypeId::ERROR_TYPE - } - }, - ast::TSType::TSMappedType(item) => { - checking_data.raise_unimplemented_error( - "ts mapped type", - oxc_span_to_source_map_span(item.span), - ); - TypeId::ERROR_TYPE - } - ast::TSType::TSQualifiedName(item) => { - checking_data.raise_unimplemented_error( - "ts qualified name", - oxc_span_to_source_map_span(item.span), - ); - TypeId::ERROR_TYPE - } - ast::TSType::TSTemplateLiteralType(item) => { - checking_data.raise_unimplemented_error( - "ts template literal type", - oxc_span_to_source_map_span(item.span), - ); - TypeId::ERROR_TYPE - } - ast::TSType::TSTupleType(item) => { - checking_data - .raise_unimplemented_error("tuple type", oxc_span_to_source_map_span(item.span)); - TypeId::ERROR_TYPE - } - ast::TSType::TSTypeLiteral(anom_interface) => { - let ty = checking_data.types.new_anonymous_interface_ty(); - crate::interfaces::synthesize_signatures( - &anom_interface.members, - environment, - checking_data, - ty, - ); - ty - } - ast::TSType::TSTypeOperatorType(item) => { - checking_data.raise_unimplemented_error( - "ts operator type", - oxc_span_to_source_map_span(item.span), - ); - TypeId::ERROR_TYPE - } - ast::TSType::TSTypePredicate(item) => { - checking_data.raise_unimplemented_error( - "ts type predicate", - oxc_span_to_source_map_span(item.span), - ); - TypeId::ERROR_TYPE - } - ast::TSType::TSTypeQuery(item) => { - checking_data - .raise_unimplemented_error("ts type query", oxc_span_to_source_map_span(item.span)); - TypeId::ERROR_TYPE - } - ast::TSType::TSTypeReference(reference) => { - if let Some(ref _args) = reference.type_parameters { - checking_data.raise_unimplemented_error( - "reference with parameters", - oxc_span_to_source_map_span(reference.span), - ); - return TypeId::ERROR_TYPE; - } - let tn = &reference.type_name; - match tn { - ast::TSTypeName::IdentifierReference(name) => environment - .get_type_by_name_handle_errors( - &name.name, - oxc_span_to_source_map_span(name.span), - checking_data, - ), - ast::TSTypeName::QualifiedName(item) => { - checking_data.raise_unimplemented_error( - "qualified name", - oxc_span_to_source_map_span(item.span), - ); - TypeId::ERROR_TYPE - } - } - } - ast::TSType::JSDocNullableType(item) => { - checking_data.raise_unimplemented_error( - "js doc nullable", - oxc_span_to_source_map_span(item.span), - ); - TypeId::ERROR_TYPE - } - ast::TSType::JSDocUnknownType(item) => { - checking_data.raise_unimplemented_error( - "js doc unknown", - oxc_span_to_source_map_span(item.span), - ); - TypeId::ERROR_TYPE - } - } -} diff --git a/crates/oxc_wasm/Cargo.toml b/crates/oxc_wasm/Cargo.toml index 4957333101859..ddb645ec0fe40 100644 --- a/crates/oxc_wasm/Cargo.toml +++ b/crates/oxc_wasm/Cargo.toml @@ -25,7 +25,6 @@ oxc = { workspace = true, features = ["serde", "semantic", "transformer", "minif oxc_linter = { workspace = true } oxc_prettier = { workspace = true } -oxc_type_synthesis = { workspace = true } serde = { workspace = true } wasm-bindgen = { version = "0.2" } diff --git a/crates/oxc_wasm/src/lib.rs b/crates/oxc_wasm/src/lib.rs index 38d3217a52c1b..a37a2f5c5dadb 100644 --- a/crates/oxc_wasm/src/lib.rs +++ b/crates/oxc_wasm/src/lib.rs @@ -14,13 +14,11 @@ use oxc::{ }; use oxc_linter::{LintContext, LintSettings, Linter}; use oxc_prettier::{Prettier, PrettierOptions}; -use oxc_type_synthesis::{synthesize_program, Diagnostic as TypeCheckDiagnostic}; use serde::Serialize; use wasm_bindgen::prelude::*; use crate::options::{ OxcCodegenOptions, OxcLinterOptions, OxcMinifierOptions, OxcParserOptions, OxcRunOptions, - OxcTypeCheckingOptions, }; #[wasm_bindgen(start)] @@ -46,8 +44,6 @@ pub struct Oxc { diagnostics: RefCell>, - type_check_diagnostics: RefCell>, - serializer: serde_wasm_bindgen::Serializer, } @@ -142,27 +138,6 @@ impl Oxc { }) .collect::>() }) - .chain(self.type_check_diagnostics.borrow().iter().filter_map(|diagnostic| { - match diagnostic { - TypeCheckDiagnostic::Global { .. } => None, - TypeCheckDiagnostic::PositionWithAdditionLabels { - reason, - position, - kind, - labels: _, - } - | TypeCheckDiagnostic::Position { reason, position, kind } => Some( - OxcDiagnostic { - start: position.start as usize, - end: position.end as usize, - severity: format!("{kind:?}"), - message: reason.to_string(), - } - .serialize(&self.serializer) - .unwrap(), - ), - } - })) .collect::>()) } @@ -176,7 +151,6 @@ impl Oxc { _linter_options: &OxcLinterOptions, _codegen_options: &OxcCodegenOptions, minifier_options: &OxcMinifierOptions, - _type_checking_options: &OxcTypeCheckingOptions, ) -> Result<(), serde_wasm_bindgen::Error> { self.diagnostics = RefCell::default(); @@ -245,11 +219,6 @@ impl Oxc { }; } - if run_options.type_check() { - let (diagnostics, ..) = synthesize_program(program, |_: &std::path::Path| None); - *self.type_check_diagnostics.borrow_mut() = diagnostics.get_diagnostics(); - } - if run_options.transform() { // FIXME: this should not be duplicated with the linter semantic, // we need to fix the API so symbols and scopes can be shared. diff --git a/website/playground/index.html b/website/playground/index.html index fb2e71da53c59..839515fce1ab9 100644 --- a/website/playground/index.html +++ b/website/playground/index.html @@ -44,7 +44,6 @@ Oxc
-
@@ -66,7 +65,6 @@
- diff --git a/website/playground/index.js b/website/playground/index.js index 78e683a3dd632..76f2e6914f840 100644 --- a/website/playground/index.js +++ b/website/playground/index.js @@ -33,7 +33,6 @@ import initWasm, { OxcLinterOptions, OxcMinifierOptions, OxcCodegenOptions, - OxcTypeCheckingOptions, } from "@oxc/wasm-web"; import { getSymbolAndReferencesSpan, renderSymbols } from "./symbols.js"; @@ -110,7 +109,6 @@ class Playground { this.codegenOptions = new OxcCodegenOptions(); this.linterOptions = new OxcLinterOptions(); this.minifierOptions = new OxcMinifierOptions(); - this.typeCheckOptions = new OxcTypeCheckingOptions(); this.runOptions.syntax = true; this.runOptions.lint = true; @@ -293,7 +291,6 @@ class Playground { this.linterOptions, this.codegenOptions, this.minifierOptions, - this.typeCheckOptions ); const elapsed = new Date() - start; document.getElementById("duration").innerText = `${elapsed}ms`; @@ -636,12 +633,6 @@ async function main() { playground.updateView(); playground.updateEditorText(playground.editor, sourceText); }; - - document.getElementById("type-check").onchange = function () { - const checked = document.getElementById("type-check-checkbox").checked; - playground.runOptions.type_check = checked; - playground.updateView(); - }; } // port from https://github.com/fkling/astexplorer/blob/541552fe45885c225fbb67d54dc4c6d6107b65b5/website/src/components/SplitPane.js#L26-L55