Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Path bug proposed fix #248

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 24 additions & 95 deletions ts-rs/src/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ use std::{
sync::{Mutex, OnceLock},
};

use path::absolute::PathAbsolute;
use thiserror::Error;
use ExportError::*;

use crate::TS;

mod path;

const NOTE: &str = "// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.\n";

/// An error which may occur when exporting a type
Expand Down Expand Up @@ -107,8 +109,8 @@ pub(crate) fn export_type_to<T: TS + ?Sized + 'static, P: AsRef<Path>>(
use dprint_plugin_typescript::{configuration::ConfigurationBuilder, format_text};

let fmt_cfg = ConfigurationBuilder::new().deno().build();
if let Some(formatted) =
format_text(path.as_ref(), &buffer, &fmt_cfg).map_err(|e| Formatting(e.to_string()))?
if let Some(formatted) = format_text(path.as_ref(), &buffer, &fmt_cfg)
.map_err(|e| ExportError::Formatting(e.to_string()))?
{
buffer = formatted;
}
Expand Down Expand Up @@ -158,11 +160,12 @@ pub(crate) fn export_type_to_string<T: TS + ?Sized + 'static>() -> Result<String

/// Compute the output path to where `T` should be exported.
fn output_path<T: TS + ?Sized>() -> Result<PathBuf, ExportError> {
let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").map_err(|_| ManifestDirNotSet)?;
let manifest_dir = Path::new(&manifest_dir);
let path =
PathBuf::from(T::get_export_to().ok_or(CannotBeExported(std::any::type_name::<T>()))?);
Ok(manifest_dir.join(path))
Ok(Path::new(
&T::get_export_to()
.ok_or_else(|| std::any::type_name::<T>())
.map_err(ExportError::CannotBeExported)?,
)
.absolute()?)
}

/// Push the declaration of `T`
Expand All @@ -180,7 +183,8 @@ fn generate_decl<T: TS + ?Sized>(out: &mut String) {

/// Push an import statement for all dependencies of `T`
fn generate_imports<T: TS + ?Sized + 'static>(out: &mut String) -> Result<(), ExportError> {
let export_to = T::get_export_to().ok_or(CannotBeExported(std::any::type_name::<T>()))?;
let export_to =
T::get_export_to().ok_or(ExportError::CannotBeExported(std::any::type_name::<T>()))?;
let path = Path::new(&export_to);

let deps = T::dependencies();
Expand Down Expand Up @@ -221,10 +225,6 @@ fn import_path(from: &Path, import: &Path) -> String {
}
}

fn to_absolute_path(path: &Path) -> Result<PathBuf, ExportError> {
Ok(std::env::current_dir()?.join(path).clean())
}

// Construct a relative path from a provided base directory path to the provided path.
//
// Copyright 2012-2015 The Rust Project Developers.
Expand All @@ -242,31 +242,33 @@ where
P: AsRef<Path>,
B: AsRef<Path>,
{
let path = to_absolute_path(path.as_ref())?;
let base = to_absolute_path(base.as_ref())?;
use Component as C;
let path = path.as_ref().absolute()?;
let base = base.as_ref().absolute()?;

let mut ita = path.components();
let mut itb = base.components();
let mut comps: Vec<Component> = vec![];

loop {
match (ita.next(), itb.next()) {
(Some(Component::ParentDir), _) | (_, Some(Component::ParentDir)) => {
unreachable!("The paths have been cleaned, no parent dir components are present")
},
(Some(C::CurDir | C::ParentDir), _) | (_, Some(C::CurDir | C::ParentDir)) => {
unreachable!(
"The paths are absolute and have been cleaned, no parent or current dir components are present"
)
}
(None, None) => break,
(Some(a), None) => {
comps.push(a);
comps.extend(ita.by_ref());
break;
}
(None, _) => comps.push(Component::ParentDir),
(None, _) => comps.push(C::ParentDir),
(Some(a), Some(b)) if comps.is_empty() && a == b => (),
(Some(a), Some(Component::CurDir)) => comps.push(a),
(Some(a), Some(_)) => {
comps.push(Component::ParentDir);
comps.push(C::ParentDir);
for _ in itb {
comps.push(Component::ParentDir);
comps.push(C::ParentDir);
}
comps.push(a);
comps.extend(ita.by_ref());
Expand All @@ -277,76 +279,3 @@ where

Ok(comps.iter().map(|c| c.as_os_str()).collect())
}

// Copyright 2018 Dan Reeves
// Adapted from the `path-clean` crate
// https://github.com/danreeves/path-clean
trait PathClean: AsRef<Path> {
fn clean(&self) -> PathBuf {
clean(self)
}
}

// Copyright 2018 Dan Reeves
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
// Adapted from the `path-clean` crate
// https://github.com/danreeves/path-clean
impl PathClean for PathBuf {}

// Copyright 2018 Dan Reeves
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
// Adapted from the `path-clean` crate
// https://github.com/danreeves/path-clean
impl PathClean for Path {}

// Copyright 2018 Dan Reeves
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
// Copied verbatim from the `path-clean` crate
// https://github.com/danreeves/path-clean
pub fn clean<P>(path: P) -> PathBuf
where
P: AsRef<Path>,
{
let mut out = Vec::new();

for comp in path.as_ref().components() {
match comp {
Component::CurDir => (),
Component::ParentDir => match out.last() {
Some(Component::RootDir) => (),
Some(Component::Normal(_)) => {
out.pop();
}
None
| Some(Component::CurDir)
| Some(Component::ParentDir)
| Some(Component::Prefix(_)) => out.push(comp),
},
comp => out.push(comp),
}
}

if !out.is_empty() {
out.iter().collect()
} else {
PathBuf::from(".")
}
}
2 changes: 2 additions & 0 deletions ts-rs/src/export/path.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod absolute;
pub mod clean;
18 changes: 18 additions & 0 deletions ts-rs/src/export/path/absolute.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use std::{
env,
io::Result,
path::{Path, PathBuf},
};

use super::clean::PathClean;

/// This trait is responsible for converting a relative path
/// into an absolute path
pub trait PathAbsolute: AsRef<Path> + PathClean {
/// Converts a relative path into an absolute path.
fn absolute(&self) -> Result<PathBuf> {
Ok(Path::new(&env::current_dir()?).join(self).clean())
}
}

impl<T: AsRef<Path> + PathClean> PathAbsolute for T {}
32 changes: 32 additions & 0 deletions ts-rs/src/export/path/clean.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use std::path::{Component, Path, PathBuf};

pub trait PathClean: AsRef<Path> {
fn clean(&self) -> PathBuf {
let mut out = Vec::new();

for comp in self.as_ref().components() {
match comp {
Component::CurDir => (),
Component::ParentDir => match out.last() {
Some(Component::RootDir) => (),
Some(Component::Normal(_)) => {
out.pop();
}
None
| Some(Component::CurDir)
| Some(Component::ParentDir)
| Some(Component::Prefix(_)) => out.push(comp),
},
comp => out.push(comp),
}
}

if !out.is_empty() {
out.iter().collect()
} else {
PathBuf::from(".")
}
}
}

impl<T: AsRef<Path>> PathClean for T {}
10 changes: 2 additions & 8 deletions ts-rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -562,10 +562,7 @@ impl<T: TS, E: TS> TS for Result<T, E> {
where
Self: 'static,
{
T::generics()
.push::<T>()
.extend(E::generics())
.push::<E>()
T::generics().push::<T>().extend(E::generics()).push::<E>()
}
}

Expand Down Expand Up @@ -658,10 +655,7 @@ impl<K: TS, V: TS, H> TS for HashMap<K, V, H> {
where
Self: 'static,
{
K::generics()
.push::<K>()
.extend(V::generics())
.push::<V>()
K::generics().push::<K>().extend(V::generics()).push::<V>()
}
}

Expand Down
4 changes: 2 additions & 2 deletions ts-rs/tests/path_bug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ use ts_rs::TS;
#[derive(TS)]
#[ts(export, export_to = "../ts-rs/tests-out/path_bug/")]
struct Foo {
bar: Bar
bar: Bar,
}

#[derive(TS)]
#[ts(export_to = "tests-out/path_bug/aaa/")]
struct Bar {
i: i32
i: i32,
}
1 change: 0 additions & 1 deletion ts-rs/tests/struct_tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,3 @@ fn test() {
"{ type: \"TaggedType\", a: number, b: number, }"
)
}

Loading