浏览代码

fix hot reloading in a workspace

Evan Almloff 2 年之前
父节点
当前提交
55787c2e7d
共有 2 个文件被更改,包括 36 次插入1 次删除
  1. 1 0
      packages/rsx/Cargo.toml
  2. 35 1
      packages/rsx/src/hot_reload/hot_reloading_file_map.rs

+ 1 - 0
packages/rsx/Cargo.toml

@@ -18,3 +18,4 @@ syn = { version = "1.0", features = ["full", "extra-traits"] }
 quote = { version = "1.0" }
 quote = { version = "1.0" }
 serde = { version = "1.0", features = ["derive"] }
 serde = { version = "1.0", features = ["derive"] }
 internment = "0.7.0"
 internment = "0.7.0"
+krates = "0.12.6"

+ 35 - 1
packages/rsx/src/hot_reload/hot_reloading_file_map.rs

@@ -1,5 +1,7 @@
 use crate::{CallBody, HotReloadingContext};
 use crate::{CallBody, HotReloadingContext};
 use dioxus_core::Template;
 use dioxus_core::Template;
+use krates::cm::MetadataCommand;
+use krates::Cmd;
 pub use proc_macro2::TokenStream;
 pub use proc_macro2::TokenStream;
 pub use std::collections::HashMap;
 pub use std::collections::HashMap;
 use std::path::PathBuf;
 use std::path::PathBuf;
@@ -27,6 +29,7 @@ pub struct FileMapBuildResult<Ctx: HotReloadingContext> {
 
 
 pub struct FileMap<Ctx: HotReloadingContext> {
 pub struct FileMap<Ctx: HotReloadingContext> {
     pub map: HashMap<PathBuf, (String, Option<Template<'static>>)>,
     pub map: HashMap<PathBuf, (String, Option<Template<'static>>)>,
+    in_workspace: HashMap<PathBuf, bool>,
     phantom: std::marker::PhantomData<Ctx>,
     phantom: std::marker::PhantomData<Ctx>,
 }
 }
 
 
@@ -76,6 +79,7 @@ impl<Ctx: HotReloadingContext> FileMap<Ctx> {
         let FileMapSearchResult { map, errors } = find_rs_files(path, &mut filter)?;
         let FileMapSearchResult { map, errors } = find_rs_files(path, &mut filter)?;
         let result = Self {
         let result = Self {
             map,
             map,
+            in_workspace: HashMap::new(),
             phantom: std::marker::PhantomData,
             phantom: std::marker::PhantomData,
         };
         };
         Ok(FileMapBuildResult {
         Ok(FileMapBuildResult {
@@ -90,6 +94,7 @@ impl<Ctx: HotReloadingContext> FileMap<Ctx> {
         let mut src = String::new();
         let mut src = String::new();
         file.read_to_string(&mut src)?;
         file.read_to_string(&mut src)?;
         if let Ok(syntax) = syn::parse_file(&src) {
         if let Ok(syntax) = syn::parse_file(&src) {
+            let in_workspace = self.child_in_workspace(crate_dir)?;
             if let Some((old_src, template_slot)) = self.map.get_mut(file_path) {
             if let Some((old_src, template_slot)) = self.map.get_mut(file_path) {
                 if let Ok(old) = syn::parse_file(old_src) {
                 if let Ok(old) = syn::parse_file(old_src) {
                     match find_rsx(&syntax, &old) {
                     match find_rsx(&syntax, &old) {
@@ -105,7 +110,17 @@ impl<Ctx: HotReloadingContext> FileMap<Ctx> {
                                     syn::parse2::<CallBody>(old.tokens),
                                     syn::parse2::<CallBody>(old.tokens),
                                     syn::parse2::<CallBody>(new),
                                     syn::parse2::<CallBody>(new),
                                 ) {
                                 ) {
-                                    if let Ok(file) = file_path.strip_prefix(crate_dir) {
+                                    // if the file!() macro is invoked in a workspace, the path is relative to the workspace root, otherwise it's relative to the crate root
+                                    // we need to check if the file is in a workspace or not and strip the prefix accordingly
+                                    let prefix = if in_workspace {
+                                        crate_dir.parent().ok_or(io::Error::new(
+                                            io::ErrorKind::Other,
+                                            "Could not load workspace",
+                                        ))?
+                                    } else {
+                                        crate_dir
+                                    };
+                                    if let Ok(file) = file_path.strip_prefix(prefix) {
                                         let line = old_start.line;
                                         let line = old_start.line;
                                         let column = old_start.column + 1;
                                         let column = old_start.column + 1;
                                         let location = file.display().to_string()
                                         let location = file.display().to_string()
@@ -157,4 +172,23 @@ impl<Ctx: HotReloadingContext> FileMap<Ctx> {
         }
         }
         Ok(UpdateResult::NeedsRebuild)
         Ok(UpdateResult::NeedsRebuild)
     }
     }
+
+    fn child_in_workspace(&mut self, crate_dir: &Path) -> io::Result<bool> {
+        if let Some(in_workspace) = self.in_workspace.get(crate_dir) {
+            Ok(*in_workspace)
+        } else {
+            let mut cmd = Cmd::new();
+            let manafest_path = crate_dir.join("Cargo.toml");
+            cmd.manifest_path(&manafest_path);
+            let cmd: MetadataCommand = cmd.into();
+            let metadata = cmd
+                .exec()
+                .map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;
+
+            let in_workspace = metadata.workspace_root != crate_dir;
+            self.in_workspace
+                .insert(crate_dir.to_path_buf(), in_workspace);
+            Ok(in_workspace)
+        }
+    }
 }
 }