Skip to content
Merged
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
7 changes: 4 additions & 3 deletions crates/doc/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ impl DocBuilder {
.collect::<Vec<_>>();

let out_dir = self.out_dir()?;
let out_target_dir = out_dir.clone();
let documents = compiler.enter_mut(|compiler| -> eyre::Result<Vec<Vec<Document>>> {
let gcx = compiler.gcx();
let documents = combined_sources
Expand Down Expand Up @@ -197,7 +198,7 @@ impl DocBuilder {
path.clone(),
target_path,
from_library,
self.config.out.clone(),
out_target_dir.clone(),
)
.with_content(DocumentContent::Single(item), ident))
})
Expand Down Expand Up @@ -231,7 +232,7 @@ impl DocBuilder {
path.clone(),
target_path,
from_library,
self.config.out.clone(),
out_target_dir.clone(),
)
.with_content(DocumentContent::Constants(consts), identity),
)
Expand All @@ -250,7 +251,7 @@ impl DocBuilder {
path.clone(),
target_path,
from_library,
self.config.out.clone(),
out_target_dir.clone(),
)
.with_content(
DocumentContent::OverloadedFunctions(funcs),
Expand Down
2 changes: 1 addition & 1 deletion crates/doc/src/preprocessor/contract_inheritance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl ContractInheritance {
&& let ParseSource::Contract(ref contract) = item.source
&& base == contract.name.safe_unwrap().name
{
return Some(candidate.target_path.clone());
return Some(candidate.relative_output_path().to_path_buf());
}
}
None
Expand Down
20 changes: 6 additions & 14 deletions crates/doc/src/writer/as_doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
};
use itertools::Itertools;
use solang_parser::pt::{Base, FunctionDefinition};
use std::path::{Path, PathBuf};
use std::path::Path;

/// The result of [`AsDoc::as_doc`].
pub type AsDocResult = Result<String, std::fmt::Error>;
Expand Down Expand Up @@ -141,9 +141,6 @@ impl AsDoc for Document {
if !contract.base.is_empty() {
writer.write_bold("Inherits:")?;

// we need this to find the _relative_ paths
let src_target_dir = self.target_src_dir();

let mut bases = vec![];
let linked =
read_context!(self, CONTRACT_INHERITANCE_ID, ContractInheritance);
Expand All @@ -155,11 +152,11 @@ impl AsDoc for Document {
.as_ref()
.and_then(|link| {
link.get(base_ident).map(|path| {
let path = Path::new("/").join(
path.strip_prefix(&src_target_dir)
.ok()
.unwrap_or(path),
);
let path = if cfg!(windows) {
Path::new("\\").join(path)
} else {
Path::new("/").join(path)
};
Markdown::Link(&base_doc, &path.display().to_string())
.as_doc()
})
Expand Down Expand Up @@ -287,11 +284,6 @@ impl AsDoc for Document {
}

impl Document {
/// Where all the source files are written to
fn target_src_dir(&self) -> PathBuf {
self.out_target_dir.join("src")
}

/// Writes a function to the buffer.
fn write_function(
&self,
Expand Down
43 changes: 43 additions & 0 deletions crates/forge/tests/cli/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,46 @@ contract Example is IExample {
assert!(content.contains("Process multiple addresses"));
assert!(content.contains("Process an address with a value"));
});

// Test that hyperlinks use relative paths, not absolute paths
// fixes <https://github.com/foundry-rs/foundry/issues/12361>
forgetest_init!(hyperlinks_use_relative_paths, |prj, cmd| {
prj.add_source(
"IBase.sol",
r#"
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IBase {
function baseFunction() external;
}
"#,
);

prj.add_source(
"Derived.sol",
r#"
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./IBase.sol";

/// @dev Inherits: {IBase}
contract Derived is IBase {
function baseFunction() external override {}
}
"#,
);

cmd.args(["doc", "--build"]).assert_success();

let doc_path = prj.root().join("docs/src/src/Derived.sol/contract.Derived.md");
let content = std::fs::read_to_string(&doc_path).unwrap();

assert!(
content.contains("[IBase](/src/IBase.sol/interface.IBase.md")
|| content.contains("[IBase](\\src\\IBase.sol\\interface.IBase.md"),
"Hyperlink should use relative path but found: {:?}",
content.lines().find(|line| line.contains("[IBase]")).unwrap_or("not found")
);
});
Loading