diff --git a/Cargo.lock b/Cargo.lock index 72b67505c2b..dec9b144de5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1022,11 +1022,12 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.115" +version = "1.0.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -1657,13 +1658,14 @@ dependencies = [ [[package]] name = "wingcli" -version = "0.74.53" +version = "0.83.2" dependencies = [ "anstyle", "camino", "clap", "home", "lazy_static", + "serde_json", "strum", "termcolor", "tracing", diff --git a/apps/wingcli-v2/Cargo.toml b/apps/wingcli-v2/Cargo.toml index f700753167b..46a0bb421d1 100644 --- a/apps/wingcli-v2/Cargo.toml +++ b/apps/wingcli-v2/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wingcli" -version = "0.74.53" +version = "0.83.2" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -16,6 +16,8 @@ clap = { version = "4.5.1", features = ["derive", "color"] } home = "0.5.9" # Lazily evaluated static variables lazy_static = "1.4.0" +# Parsing JSON +serde_json = "1.0.125" # Enum parsing strum = { version = "0.26.1", features = ["derive"] } # Colors in terminal diff --git a/apps/wingcli-v2/src/main.rs b/apps/wingcli-v2/src/main.rs index bb1b5e1e386..d1f20bd4078 100644 --- a/apps/wingcli-v2/src/main.rs +++ b/apps/wingcli-v2/src/main.rs @@ -1,6 +1,12 @@ mod cli; -use std::{error::Error, io::Write, path::PathBuf, time::Instant}; +use std::{ + error::Error, + io::Write, + path::PathBuf, + sync::{Mutex, Once}, + time::Instant, +}; use camino::{Utf8Path, Utf8PathBuf}; use clap::Parser; @@ -8,7 +14,7 @@ use cli::{print_compiled, print_compiling, print_installing}; use home::home_dir; use lazy_static::lazy_static; use strum::{Display, EnumString}; -use wingc::compile; +use wingc::{compile, diagnostic::get_diagnostics}; lazy_static! { static ref HOME_PATH: PathBuf = home_dir().expect("Could not find home directory"); @@ -80,17 +86,13 @@ fn command_build(source_file: Utf8PathBuf, target: Option) -> Result<(), )); let work_dir = target_dir.join(".wing"); - // Print that work is being done + // Print "Compiling..." print_compiling(source_file.as_str()); let sdk_root = WING_CACHE_DIR.join("node_modules").join("@winglang").join("sdk"); - // Skip installing the SDK here if we're in a unit test since tests may run in parallel - // TODO: check if the SDK is up to date - if !sdk_root.exists() && !cfg!(test) { - install_sdk()?; - } - tracing::info!("Using SDK at {}", sdk_root); + install_sdk()?; + tracing::info!("Using Wing SDK at {}", sdk_root); // Special pragma used by wingc to find the SDK types if !cfg!(test) { @@ -103,6 +105,10 @@ fn command_build(source_file: Utf8PathBuf, target: Option) -> Result<(), Ok(_) => {} Err(error) => { tracing::error!(error = ?error, "Failed"); + let diagnostics = get_diagnostics(); + for diagnostic in diagnostics { + eprintln!("{}", diagnostic); + } return Err("Compiler error".into()); } } @@ -113,7 +119,23 @@ fn command_build(source_file: Utf8PathBuf, target: Option) -> Result<(), Ok(()) } +// Create a mutex to ensure that the SDK is only installed once +lazy_static! { + static ref INSTALL_SDK_MUTEX: Mutex<()> = Mutex::new(()); +} + +static INSTALL_SDK_INIT: Once = Once::new(); + fn install_sdk() -> Result<(), Box> { + let _guard = INSTALL_SDK_MUTEX.lock().unwrap(); + let mut result = Ok(()); + INSTALL_SDK_INIT.call_once(|| { + result = install_sdk_helper(); + }); + result +} + +fn install_sdk_helper() -> Result<(), Box> { print_installing("Wing SDK"); std::fs::create_dir_all(WING_CACHE_DIR.as_str())?; @@ -173,14 +195,16 @@ fn run_javascript_node(source_file: &Utf8Path, target_dir: &Utf8Path, target: Ta } fn initialize_logger() { - let enable_logs = std::env::var("WING_LOG").is_ok_and(|x| !x.is_empty() && x != "off" && x != "0"); + let enable_logs = std::env::var("DEBUG").is_ok_and(|x| !x.is_empty() && x != "off" && x != "0"); let enable_colours = std::env::var("WING_LOG_NOCOLOR").is_err(); + let show_thread_names = cfg!(test); if enable_logs { tracing_subscriber::fmt() .with_writer(std::io::stderr) .with_target(false) .with_ansi(enable_colours) .without_time() + .with_thread_names(show_thread_names) .init(); } } @@ -216,23 +240,22 @@ mod test { static INIT: Once = Once::new(); - fn initialize() { + fn setup() { INIT.call_once(|| { initialize_logger(); - install_sdk().expect("Failed to install SDK"); }); } #[test] fn test_compile_sim() { - initialize(); + setup(); let res = command_build("../../examples/tests/valid/hello.test.w".into(), Some(Target::Sim)); res.expect("Failed to compile to sim"); } #[test] fn test_compile_tfaws() { - initialize(); + setup(); let res = command_build("../../examples/tests/valid/hello.test.w".into(), Some(Target::TfAws)); res.expect("Failed to compile to tf-aws"); } diff --git a/libs/wingc/src/lib.rs b/libs/wingc/src/lib.rs index 976b9e18f07..736b56c1150 100644 --- a/libs/wingc/src/lib.rs +++ b/libs/wingc/src/lib.rs @@ -212,9 +212,9 @@ pub unsafe extern "C" fn wingc_compile(ptr: u32, len: u32) -> u64 { let args = ptr_to_str(ptr, len); let split = args.split(";").collect::>(); - if split.len() != 3 { + if split.len() != 2 { report_diagnostic(Diagnostic { - message: format!("Expected 3 arguments to wingc_compile, got {}", split.len()), + message: format!("Expected 2 arguments to wingc_compile, got {}", split.len()), span: None, annotations: vec![], hints: vec![], @@ -387,18 +387,6 @@ pub fn compile(source_path: &Utf8Path, source_text: Option, out_dir: &Ut asts.insert(file.path.to_owned(), scope); } - // Verify that the project dir is absolute - if !is_absolute_path(&project_dir) { - report_diagnostic(Diagnostic { - message: format!("Project directory must be absolute: {}", project_dir), - span: None, - annotations: vec![], - hints: vec![], - severity: DiagnosticSeverity::Error, - }); - return Err(()); - } - let mut jsifier = JSifier::new(&mut types, &files, &file_graph, &source_path, &out_dir); // -- LIFTING PHASE -- diff --git a/tools/hangar/__snapshots__/test_corpus/valid/bring_extend_non_entry.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/bring_extend_non_entry.test.w_compile_tf-aws.md index 14e322c6b35..9ea26b0f30e 100644 --- a/tools/hangar/__snapshots__/test_corpus/valid/bring_extend_non_entry.test.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/valid/bring_extend_non_entry.test.w_compile_tf-aws.md @@ -50,7 +50,7 @@ class $Root extends $stdlib.std.Resource { let $preflightTypesMap = {}; const lib = $helpers.bringJs(`${__dirname}/preflight.extendnonentrypoint-1.cjs`, $preflightTypesMap); $helpers.nodeof(this).root.$preflightTypesMap = $preflightTypesMap; - const f = new lib.Foo(this, "Foo"); + const f = globalThis.$ClassFactory.new("rootpkg.Foo", lib.Foo, this, "Foo"); } } const $APP = $PlatformManager.createApp({ outdir: $outdir, name: "bring_extend_non_entry.test", rootConstruct: $Root, isTestEnvironment: $wing_is_test, entrypointDir: process.env['WING_SOURCE_DIR'], rootId: process.env['WING_ROOT_ID'] }); diff --git a/tools/hangar/__snapshots__/test_corpus/valid/bring_local.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/bring_local.test.w_compile_tf-aws.md index f87bc3b1c35..957cdfea1f9 100644 --- a/tools/hangar/__snapshots__/test_corpus/valid/bring_local.test.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/valid/bring_local.test.w_compile_tf-aws.md @@ -351,19 +351,19 @@ class $Root extends $stdlib.std.Resource { return ` require("${$helpers.normalPath(__dirname)}/inflight.$Closure2-3.cjs")({ $expect_Util: ${$stdlib.core.liftObject($stdlib.core.toLiftableModuleType(globalThis.$ClassFactory.resolveType("@winglang/sdk.expect.Util") ?? expect.Util, "@winglang/sdk/expect", "Util"))}, - $file2_Q: ${$stdlib.core.liftObject($stdlib.core.toLiftableModuleType(file2.Q, "", "Q"))}, + $file2_Q: ${$stdlib.core.liftObject($stdlib.core.toLiftableModuleType(globalThis.$ClassFactory.resolveType("rootpkg.subdir.Q") ?? file2.Q, "", "Q"))}, }) `; } get _liftMap() { return ({ "handle": [ - [$stdlib.core.toLiftableModuleType(file2.Q, "", "Q"), ["greet"]], [$stdlib.core.toLiftableModuleType(globalThis.$ClassFactory.resolveType("@winglang/sdk.expect.Util") ?? expect.Util, "@winglang/sdk/expect", "Util"), ["equal"]], + [$stdlib.core.toLiftableModuleType(globalThis.$ClassFactory.resolveType("rootpkg.subdir.Q") ?? file2.Q, "", "Q"), ["greet"]], ], "$inflight_init": [ - [$stdlib.core.toLiftableModuleType(file2.Q, "", "Q"), []], [$stdlib.core.toLiftableModuleType(globalThis.$ClassFactory.resolveType("@winglang/sdk.expect.Util") ?? expect.Util, "@winglang/sdk/expect", "Util"), []], + [$stdlib.core.toLiftableModuleType(globalThis.$ClassFactory.resolveType("rootpkg.subdir.Q") ?? file2.Q, "", "Q"), []], ], }); } @@ -405,8 +405,8 @@ class $Root extends $stdlib.std.Resource { }); } } - const store = new file1.Store(this, "Store"); - const q = new file2.Q(this, "Q"); + const store = globalThis.$ClassFactory.new("rootpkg.Store", file1.Store, this, "Store"); + const q = globalThis.$ClassFactory.new("rootpkg.subdir.Q", file2.Q, this, "Q"); (expect.Util.equal((file2.Q.preflightGreet("foo")), "Hello foo")); globalThis.$ClassFactory.new("@winglang/sdk.std.Test", std.Test, this, "test:add data to store", new $Closure1(this, "$Closure1")); globalThis.$ClassFactory.new("@winglang/sdk.std.Test", std.Test, this, "test:greet", new $Closure2(this, "$Closure2")); diff --git a/tools/hangar/__snapshots__/test_corpus/valid/bring_local_dir.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/bring_local_dir.test.w_compile_tf-aws.md index 40619b4963c..d5e8329578d 100644 --- a/tools/hangar/__snapshots__/test_corpus/valid/bring_local_dir.test.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/valid/bring_local_dir.test.w_compile_tf-aws.md @@ -106,13 +106,13 @@ class $Root extends $stdlib.std.Resource { const w = $helpers.bringJs(`${__dirname}/preflight.widget-1.cjs`, $preflightTypesMap); const subdir = $helpers.bringJs(`${__dirname}/preflight.subdir2-6.cjs`, $preflightTypesMap); $helpers.nodeof(this).root.$preflightTypesMap = $preflightTypesMap; - const widget1 = new w.Widget(this, "widget1"); + const widget1 = globalThis.$ClassFactory.new("rootpkg.subdir2.inner.Widget", w.Widget, this, "widget1"); $helpers.assert($helpers.eq((widget1.compute()), 42), "widget1.compute() == 42"); - const foo = new subdir.Foo(this, "Foo"); + const foo = globalThis.$ClassFactory.new("rootpkg.subdir2.Foo", subdir.Foo, this, "Foo"); $helpers.assert($helpers.eq((foo.foo()), "foo"), "foo.foo() == \"foo\""); - const bar = new subdir.Bar(this, "Bar"); + const bar = globalThis.$ClassFactory.new("rootpkg.subdir2.Bar", subdir.Bar, this, "Bar"); $helpers.assert($helpers.eq((bar.bar()), "bar"), "bar.bar() == \"bar\""); - const widget2 = new subdir.inner.Widget(this, "widget2"); + const widget2 = globalThis.$ClassFactory.new("rootpkg.subdir2.inner.Widget", subdir.inner.Widget, this, "widget2"); $helpers.assert($helpers.eq((widget2.compute()), 42), "widget2.compute() == 42"); $helpers.assert($helpers.eq((foo.checkWidget(widget2)), 1379), "foo.checkWidget(widget2) == 1379"); } diff --git a/tools/hangar/__snapshots__/test_corpus/valid/bring_wing_library.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/bring_wing_library.test.w_compile_tf-aws.md index e43a2f38324..22ddc8f6cfa 100644 --- a/tools/hangar/__snapshots__/test_corpus/valid/bring_wing_library.test.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/valid/bring_wing_library.test.w_compile_tf-aws.md @@ -156,22 +156,22 @@ class $Root extends $stdlib.std.Resource { static _toInflightType() { return ` require("${$helpers.normalPath(__dirname)}/inflight.$Closure1-3.cjs")({ - $fixture_Store: ${$stdlib.core.liftObject($stdlib.core.toLiftableModuleType(fixture.Store, "", "Store"))}, + $fixture_Store: ${$stdlib.core.liftObject($stdlib.core.toLiftableModuleType(globalThis.$ClassFactory.resolveType("@winglibs/testfixture.Store") ?? fixture.Store, "", "Store"))}, }) `; } get _liftMap() { return ({ "handle": [ - [$stdlib.core.toLiftableModuleType(fixture.Store, "", "Store"), ["makeKeyInflight"]], + [$stdlib.core.toLiftableModuleType(globalThis.$ClassFactory.resolveType("@winglibs/testfixture.Store") ?? fixture.Store, "", "Store"), ["makeKeyInflight"]], ], "$inflight_init": [ - [$stdlib.core.toLiftableModuleType(fixture.Store, "", "Store"), []], + [$stdlib.core.toLiftableModuleType(globalThis.$ClassFactory.resolveType("@winglibs/testfixture.Store") ?? fixture.Store, "", "Store"), []], ], }); } } - new fixture.Store(this, "Store"); + globalThis.$ClassFactory.new("@winglibs/testfixture.Store", fixture.Store, this, "Store"); const fave_num = fixture.FavoriteNumbers.SEVEN; const fave_num2 = testfixture.FavoriteNumbers.SEVEN; const fave_num3 = testfixture2.FavoriteNumbers.SEVEN; @@ -237,7 +237,7 @@ class Store extends $stdlib.std.Resource { static _toInflightType() { return ` require("${$helpers.normalPath(__dirname)}/inflight.Store-2.cjs")({ - $myutil_Util: ${$stdlib.core.liftObject($stdlib.core.toLiftableModuleType(myutil.Util, "", "Util"))}, + $myutil_Util: ${$stdlib.core.liftObject($stdlib.core.toLiftableModuleType(globalThis.$ClassFactory.resolveType("@winglibs/testfixture.subdir.Util") ?? myutil.Util, "", "Util"))}, }) `; } @@ -251,12 +251,12 @@ class Store extends $stdlib.std.Resource { get _liftMap() { return ({ "set": [ - [$stdlib.core.toLiftableModuleType(myutil.Util, "", "Util"), ["double"]], + [$stdlib.core.toLiftableModuleType(globalThis.$ClassFactory.resolveType("@winglibs/testfixture.subdir.Util") ?? myutil.Util, "", "Util"), ["double"]], [this.data, ["put"]], [this.handlers, []], ], "$inflight_init": [ - [$stdlib.core.toLiftableModuleType(myutil.Util, "", "Util"), []], + [$stdlib.core.toLiftableModuleType(globalThis.$ClassFactory.resolveType("@winglibs/testfixture.subdir.Util") ?? myutil.Util, "", "Util"), []], [this.data, []], [this.handlers, []], ], diff --git a/tools/hangar/__snapshots__/test_corpus/valid/inflight_class_capture_preflight_object.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/inflight_class_capture_preflight_object.test.w_compile_tf-aws.md index b4e473ef3db..439b2583e82 100644 --- a/tools/hangar/__snapshots__/test_corpus/valid/inflight_class_capture_preflight_object.test.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/valid/inflight_class_capture_preflight_object.test.w_compile_tf-aws.md @@ -447,7 +447,7 @@ class $Root extends $stdlib.std.Resource { static _toInflightType() { return ` require("${$helpers.normalPath(__dirname)}/inflight.$Closure6-5.cjs")({ - $subdir_InflightClass: ${$stdlib.core.liftObject($stdlib.core.toLiftableModuleType(subdir.InflightClass, "", "InflightClass"))}, + $subdir_InflightClass: ${$stdlib.core.liftObject($stdlib.core.toLiftableModuleType(globalThis.$ClassFactory.resolveType("rootpkg.subdir2.InflightClass") ?? subdir.InflightClass, "", "InflightClass"))}, }) `; } @@ -455,11 +455,11 @@ class $Root extends $stdlib.std.Resource { return ({ "handle": [ [$helpers.preflightClassSingleton(this, 5), ["method"]], - [$stdlib.core.toLiftableModuleType(subdir.InflightClass, "", "InflightClass"), []], + [$stdlib.core.toLiftableModuleType(globalThis.$ClassFactory.resolveType("rootpkg.subdir2.InflightClass") ?? subdir.InflightClass, "", "InflightClass"), []], ], "$inflight_init": [ [$helpers.preflightClassSingleton(this, 5), []], - [$stdlib.core.toLiftableModuleType(subdir.InflightClass, "", "InflightClass"), []], + [$stdlib.core.toLiftableModuleType(globalThis.$ClassFactory.resolveType("rootpkg.subdir2.InflightClass") ?? subdir.InflightClass, "", "InflightClass"), []], ], }); } diff --git a/tools/hangar/__snapshots__/test_corpus/valid/lift_shared_resource.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/lift_shared_resource.test.w_compile_tf-aws.md index 66aa2b794ab..309599ab482 100644 --- a/tools/hangar/__snapshots__/test_corpus/valid/lift_shared_resource.test.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/valid/lift_shared_resource.test.w_compile_tf-aws.md @@ -407,8 +407,8 @@ class $Root extends $stdlib.std.Resource { } } const bucket = globalThis.$ClassFactory.new("@winglang/sdk.cloud.Bucket", cloud.Bucket, this, "Bucket"); - const b1 = new MyBucket(this, "b1", bucket); - const b2 = new MyBucket(this, "b2", bucket); + const b1 = globalThis.$ClassFactory.new("rootpkg.MyBucket", MyBucket, this, "b1", bucket); + const b2 = globalThis.$ClassFactory.new("rootpkg.MyBucket", MyBucket, this, "b2", bucket); const api = globalThis.$ClassFactory.new("@winglang/sdk.cloud.Api", cloud.Api, this, "Api"); (api.get("/", new $Closure1(this, "$Closure1"))); globalThis.$ClassFactory.new("@winglang/sdk.std.Test", std.Test, this, "test:call endpoint", new $Closure2(this, "$Closure2")); diff --git a/tools/hangar/__snapshots__/test_corpus/valid/new_in_static.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/new_in_static.test.w_compile_tf-aws.md index f7a03b4883d..ae2ca35ab4a 100644 --- a/tools/hangar/__snapshots__/test_corpus/valid/new_in_static.test.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/valid/new_in_static.test.w_compile_tf-aws.md @@ -338,7 +338,7 @@ class LibClass extends $stdlib.std.Resource { super($scope, $id); } static createFoo($scope, id) { - return new Foo($scope, id); + return globalThis.$ClassFactory.new("rootpkg.Foo", Foo, $scope, id); } static _toInflightType() { return ` diff --git a/tools/hangar/__snapshots__/test_corpus/valid/new_in_static_lib.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/new_in_static_lib.w_compile_tf-aws.md index d06d636cfce..caf8656b25e 100644 --- a/tools/hangar/__snapshots__/test_corpus/valid/new_in_static_lib.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/valid/new_in_static_lib.w_compile_tf-aws.md @@ -57,7 +57,7 @@ class LibClass extends $stdlib.std.Resource { super($scope, $id); } static createFoo($scope, id) { - return new Foo($scope, id); + return globalThis.$ClassFactory.new("rootpkg.Foo", Foo, $scope, id); } static _toInflightType() { return ` diff --git a/tools/hangar/__snapshots__/test_corpus/valid/struct_from_json.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/struct_from_json.test.w_compile_tf-aws.md index 19360173050..b9db451237c 100644 --- a/tools/hangar/__snapshots__/test_corpus/valid/struct_from_json.test.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/valid/struct_from_json.test.w_compile_tf-aws.md @@ -485,7 +485,7 @@ class $Root extends $stdlib.std.Resource { (std.Number.fromJson("cool", { unsafe: true })); $macros.__Struct_fromJson(false, Student, ({"obviously": "not a student"}), { unsafe: true }); globalThis.$ClassFactory.new("@winglang/sdk.std.Test", std.Test, this, "test:unsafe flight", new $Closure5(this, "$Closure5")); - new otherExternalStructs.UsesStructInImportedFile(this, "UsesStructInImportedFile"); + globalThis.$ClassFactory.new("rootpkg.subdir.UsesStructInImportedFile", otherExternalStructs.UsesStructInImportedFile, this, "UsesStructInImportedFile"); } } const $APP = $PlatformManager.createApp({ outdir: $outdir, name: "struct_from_json.test", rootConstruct: $Root, isTestEnvironment: $wing_is_test, entrypointDir: process.env['WING_SOURCE_DIR'], rootId: process.env['WING_ROOT_ID'] }); diff --git a/tools/hangar/src/unsupported.test.ts b/tools/hangar/src/unsupported.test.ts index 7f9774cb5c2..1701436b894 100644 --- a/tools/hangar/src/unsupported.test.ts +++ b/tools/hangar/src/unsupported.test.ts @@ -30,7 +30,7 @@ test("unsupported resource in target", async ({ expect }) => { }, }); - expect(sanitizeOutput(result.stderr)).toMatchInlineSnapshot('"Error: A Google Cloud region must be specified through the GOOGLE_REGION environment variable."'); + expect(sanitizeOutput(result.stderr)).toMatchInlineSnapshot(`"Error: A Google Cloud region must be specified through the GOOGLE_REGION environment variable."`); }); function sanitizeOutput(inputString: string): string {