Skip to content

Commit

Permalink
chore(compiler): store FQN information for types (#7047)
Browse files Browse the repository at this point in the history
  • Loading branch information
Chriscbr authored Aug 26, 2024
1 parent d11a8a0 commit b06b407
Show file tree
Hide file tree
Showing 25 changed files with 325 additions and 119 deletions.
7 changes: 4 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apps/wingcli-v2/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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
Expand Down
53 changes: 38 additions & 15 deletions apps/wingcli-v2/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
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;
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");
Expand Down Expand Up @@ -80,29 +86,29 @@ fn command_build(source_file: Utf8PathBuf, target: Option<Target>) -> 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) {
std::env::set_var("WINGSDK_MANIFEST_ROOT", &sdk_root);
}

let result = compile(&project_dir, &source_file, None, &work_dir);
let result = compile(&source_file, None, &work_dir);

match result {
Ok(_) => {}
Err(error) => {
tracing::error!(error = ?error, "Failed");
let diagnostics = get_diagnostics();
for diagnostic in diagnostics {
eprintln!("{}", diagnostic);
}
return Err("Compiler error".into());
}
}
Expand All @@ -113,7 +119,23 @@ fn command_build(source_file: Utf8PathBuf, target: Option<Target>) -> 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<dyn Error>> {
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<dyn Error>> {
print_installing("Wing SDK");

std::fs::create_dir_all(WING_CACHE_DIR.as_str())?;
Expand Down Expand Up @@ -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();
}
}
Expand Down Expand Up @@ -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");
}
Expand Down
2 changes: 1 addition & 1 deletion libs/wingc/examples/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub fn main() {
let source_path = Utf8Path::new(&args[1]).canonicalize_utf8().unwrap();
let target_dir: Utf8PathBuf = env::current_dir().unwrap().join("target").try_into().unwrap();

let _ = compile(source_path.parent().unwrap(), &source_path, None, &target_dir);
let _ = compile(&source_path, None, &target_dir);
let mut diags = get_diagnostics();
if !diags.is_empty() {
// Sort error messages by line number (ascending)
Expand Down
4 changes: 2 additions & 2 deletions libs/wingc/src/dtsify/extern_dtsify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,8 @@ impl<'a> ExternDTSifier<'a> {
fn resolve_named_type(&mut self, type_: TypeRef, is_inflight: bool) -> String {
let fqn = match &*type_ {
Type::Class(c) => c.fqn.as_ref().unwrap_or(&c.name.span.file_id),
Type::Interface(i) => i.fqn.as_ref().unwrap_or(&i.name.span.file_id),
Type::Struct(s) => s.fqn.as_ref().unwrap_or(&s.name.span.file_id),
Type::Interface(i) => &i.fqn,
Type::Struct(s) => &s.fqn,
Type::Enum(e) => &e.name.span.file_id,
_ => panic!("Not a named type"),
};
Expand Down
2 changes: 1 addition & 1 deletion libs/wingc/src/dtsify/snapshots/declarations.snap
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ class ParentClass extends $stdlib.std.Resource {
});
}
}
class Child extends ParentClass {
class Child extends (globalThis.$ClassFactory.resolveType("rootpkg.ParentClass") ?? ParentClass) {
constructor($scope, $id, ) {
super($scope, $id);
}
Expand Down
74 changes: 44 additions & 30 deletions libs/wingc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<Vec<&str>>();
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![],
Expand All @@ -224,10 +224,6 @@ pub unsafe extern "C" fn wingc_compile(ptr: u32, len: u32) -> u64 {
}
let source_path = Utf8Path::new(split[0]);
let output_dir = split.get(1).map(|s| Utf8Path::new(s)).expect("output dir not provided");
let project_dir = split
.get(2)
.map(|s| Utf8Path::new(s))
.expect("project dir not provided");

if !source_path.exists() {
report_diagnostic(Diagnostic {
Expand All @@ -240,7 +236,7 @@ pub unsafe extern "C" fn wingc_compile(ptr: u32, len: u32) -> u64 {
return WASM_RETURN_ERROR;
}

let results = compile(project_dir, source_path, None, output_dir);
let results = compile(source_path, None, output_dir);

if let Ok(results) = results {
string_to_combined_ptr(serde_json::to_string(&results).unwrap())
Expand All @@ -254,6 +250,7 @@ pub fn type_check(
types: &mut Types,
file: &File,
file_graph: &FileGraph,
library_roots: &mut IndexMap<String, Utf8PathBuf>,
jsii_types: &mut TypeSystem,
jsii_imports: &mut Vec<JsiiImportSpec>,
) {
Expand All @@ -267,7 +264,7 @@ pub fn type_check(

types.set_scope_env(scope, env);

let mut tc = TypeChecker::new(types, file, file_graph, jsii_types, jsii_imports);
let mut tc = TypeChecker::new(types, file, file_graph, library_roots, jsii_types, jsii_imports);
tc.add_jsii_module_to_env(
&mut env,
WINGSDK_ASSEMBLY_NAME.to_string(),
Expand All @@ -283,18 +280,45 @@ pub fn type_check(
tc.add_this(&mut env);
}

tc.type_check_file_or_dir(file, scope);
tc.type_check_file_or_dir(scope);
}

pub fn compile(
project_dir: &Utf8Path,
source_path: &Utf8Path,
source_text: Option<String>,
out_dir: &Utf8Path,
) -> Result<CompilerOutput, ()> {
let source_package = as_wing_library(project_dir).unwrap_or_else(|| DEFAULT_PACKAGE_NAME.to_string());
/// Infer the root directory of the current Wing application or library.
///
/// Check the current file's directory for a wing.toml file or package.json file,
/// and continue searching up the directory tree until we find one.
/// If we run out of parent directories, fall back to the first directory we found.
pub fn find_nearest_wing_project_dir(source_path: &Utf8Path) -> Utf8PathBuf {
let initial_dir: Utf8PathBuf = if source_path.is_dir() {
source_path.to_owned()
} else {
source_path.parent().unwrap_or_else(|| Utf8Path::new("/")).to_owned()
};
let mut current_dir = initial_dir.as_path();
loop {
if current_dir.join("wing.toml").exists() {
return current_dir.to_owned();
}
if current_dir.join("package.json").exists() {
return current_dir.to_owned();
}
if current_dir == "/" {
break;
}
current_dir = current_dir.parent().unwrap_or_else(|| Utf8Path::new("/"));
}
return initial_dir;
}

pub fn compile(source_path: &Utf8Path, source_text: Option<String>, out_dir: &Utf8Path) -> Result<CompilerOutput, ()> {
let project_dir = find_nearest_wing_project_dir(source_path);
let source_package = as_wing_library(&project_dir).unwrap_or_else(|| DEFAULT_PACKAGE_NAME.to_string());
let source_path = normalize_path(source_path, None);
let source_file = File::new(&source_path, source_package);
let source_file = File::new(&source_path, source_package.clone());

// A map from package names to their root directories
let mut library_roots: IndexMap<String, Utf8PathBuf> = IndexMap::new();
library_roots.insert(source_package, project_dir.to_owned());

// -- PARSING PHASE --
let mut files = Files::new();
Expand All @@ -306,6 +330,7 @@ pub fn compile(
source_text,
&mut files,
&mut file_graph,
&mut library_roots,
&mut tree_sitter_trees,
&mut asts,
);
Expand Down Expand Up @@ -342,6 +367,7 @@ pub fn compile(
&mut types,
&file,
&file_graph,
&mut library_roots,
&mut jsii_types,
&mut jsii_imports,
);
Expand All @@ -361,18 +387,6 @@ pub fn compile(
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 --
Expand Down Expand Up @@ -505,7 +519,7 @@ mod sanity {
fs::remove_dir_all(&out_dir).expect("remove out dir");
}

let result = compile(&test_dir, &test_file, None, &out_dir);
let result = compile(&test_file, None, &out_dir);

if result.is_err() {
assert!(
Expand Down
2 changes: 1 addition & 1 deletion libs/wingc/src/lifting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ impl<'a> LiftVisitor<'a> {
let fqn = if let Some(class) = type_.as_ref().and_then(|t| t.as_class()) {
class.fqn.clone()
} else if let Some(iface) = type_.as_ref().and_then(|t| t.as_interface()) {
iface.fqn.clone()
Some(iface.fqn.clone())
} else {
None
};
Expand Down
Loading

0 comments on commit b06b407

Please sign in to comment.