Add option for emitting absolute paths to rojo sourcemap (#1092)

Co-authored-by: Micah <micah@uplift.games>
This commit is contained in:
ffrostfall
2025-08-04 14:33:35 -04:00
committed by GitHub
parent a4eb65ca3f
commit 2ddb21ec5f
4 changed files with 46 additions and 12 deletions

View File

@@ -1,7 +1,8 @@
use std::{
borrow::Cow,
io::{BufWriter, Write},
mem::forget,
path::{Path, PathBuf},
path::{self, Path, PathBuf},
};
use clap::Parser;
@@ -20,6 +21,7 @@ use crate::{
use super::resolve_path;
const PATH_STRIP_FAILED_ERR: &str = "Failed to create relative paths for project file!";
const ABSOLUTE_PATH_FAILED_ERR: &str = "Failed to turn relative path into absolute path!";
/// Representation of a node in the generated sourcemap tree.
#[derive(Serialize)]
@@ -32,7 +34,7 @@ struct SourcemapNode<'a> {
skip_serializing_if = "Vec::is_empty",
serialize_with = "crate::path_serializer::serialize_vec_absolute"
)]
file_paths: Vec<PathBuf>,
file_paths: Vec<Cow<'a, Path>>,
#[serde(skip_serializing_if = "Vec::is_empty")]
children: Vec<SourcemapNode<'a>>,
@@ -60,6 +62,10 @@ pub struct SourcemapCommand {
/// Whether to automatically recreate a snapshot when any input files change.
#[clap(long)]
pub watch: bool,
/// Whether the sourcemap should use absolute paths instead of relative paths.
#[clap(long)]
pub absolute: bool,
}
impl SourcemapCommand {
@@ -86,7 +92,7 @@ impl SourcemapCommand {
.build_global()
.unwrap();
write_sourcemap(&session, self.output.as_deref(), filter)?;
write_sourcemap(&session, self.output.as_deref(), filter, self.absolute)?;
if self.watch {
let rt = Runtime::new().unwrap();
@@ -97,7 +103,7 @@ impl SourcemapCommand {
cursor = new_cursor;
if patch_set_affects_sourcemap(&session, &patch_set, filter) {
write_sourcemap(&session, self.output.as_deref(), filter)?;
write_sourcemap(&session, self.output.as_deref(), filter, self.absolute)?;
}
}
}
@@ -163,13 +169,16 @@ fn recurse_create_node<'a>(
referent: Ref,
project_dir: &Path,
filter: fn(&InstanceWithMeta) -> bool,
use_absolute_paths: bool,
) -> Option<SourcemapNode<'a>> {
let instance = tree.get_instance(referent).expect("instance did not exist");
let children: Vec<_> = instance
.children()
.par_iter()
.filter_map(|&child_id| recurse_create_node(tree, child_id, project_dir, filter))
.filter_map(|&child_id| {
recurse_create_node(tree, child_id, project_dir, filter, use_absolute_paths)
})
.collect();
// If this object has no children and doesn't pass the filter, it doesn't
@@ -184,14 +193,30 @@ fn recurse_create_node<'a>(
.iter()
// Not all paths listed as relevant are guaranteed to exist.
.filter(|path| path.is_file())
.map(|path| path.strip_prefix(project_dir).expect(PATH_STRIP_FAILED_ERR))
.map(|path| path.to_path_buf())
.collect();
.map(|path| path.as_path());
let mut output_file_paths: Vec<Cow<'a, Path>> =
Vec::with_capacity(instance.metadata().relevant_paths.len());
if use_absolute_paths {
// It's somewhat important to note here that `path::absolute` takes in a Path and returns a PathBuf
for val in file_paths {
output_file_paths.push(Cow::Owned(
path::absolute(val).expect(ABSOLUTE_PATH_FAILED_ERR),
));
}
} else {
for val in file_paths {
output_file_paths.push(Cow::from(
val.strip_prefix(project_dir).expect(PATH_STRIP_FAILED_ERR),
));
}
};
Some(SourcemapNode {
name: instance.name(),
class_name: instance.class_name(),
file_paths,
file_paths: output_file_paths,
children,
})
}
@@ -200,10 +225,17 @@ fn write_sourcemap(
session: &ServeSession,
output: Option<&Path>,
filter: fn(&InstanceWithMeta) -> bool,
use_absolute_paths: bool,
) -> anyhow::Result<()> {
let tree = session.tree();
let root_node = recurse_create_node(&tree, tree.get_root_id(), session.root_dir(), filter);
let root_node = recurse_create_node(
&tree,
tree.get_root_id(),
session.root_dir(),
filter,
use_absolute_paths,
);
if let Some(output_path) = output {
let mut file = BufWriter::new(File::create(output_path)?);