Fork of daniellemaywood.uk/gleam — Wasm codegen work
2

Configure Feed

Select the types of activity you want to include in your feed.

Generate relative links for same-package documentation

+146 -12
+52
compiler-core/src/docs/printer.rs
··· 460 460 self.title(name) 461 461 } else if package == self.package && module == self.module { 462 462 self.link(eco_format!("#{name}"), self.title(name), None) 463 + } else if package == self.package { 464 + // If we are linking to the current package, we might be viewing the 465 + // documentation locally and so we need to generate a relative link. 466 + 467 + let mut module_path = module.split('/').peekable(); 468 + let mut current_module = self.module.split('/'); 469 + 470 + // The documentation page for the final segment of the module is just 471 + // an html file by itself, so it doesn't form part of the path and doesn't 472 + // need to be backtracked using `..`. 473 + let module_name = module_path.next_back().unwrap_or(module); 474 + _ = current_module.next_back(); 475 + 476 + // The two modules might have some sharer part of the path, which we 477 + // don't need to traverse back through. However, if the two modules are 478 + // something like `gleam/a/wibble/wobble` and `gleam/b/wibble/wobble`, 479 + // the `wibble` folders are two different folders despite being at the 480 + // same position with the same name. 481 + let mut encountered_different_path = false; 482 + let mut path = Vec::new(); 483 + 484 + // Calculate how far backwards in the directory tree we need to walk 485 + for segment in current_module { 486 + // If this is still part of the shared path, we can just skip it: 487 + // no need to go back and forth through the same directory in the 488 + // path! 489 + if !encountered_different_path && module_path.peek() == Some(&segment) { 490 + _ = module_path.next(); 491 + } else { 492 + encountered_different_path = true; 493 + path.push(".."); 494 + } 495 + } 496 + 497 + // Once we have walked backwards, we walk forwards again to the correct 498 + // page. 499 + path.extend(module_path); 500 + path.push(module_name); 501 + 502 + let qualified_name = docvec![ 503 + self.variable(EcoString::from(module_name)), 504 + ".", 505 + self.title(name) 506 + ]; 507 + 508 + let title = eco_format!("{module}.{{type {name}}}"); 509 + 510 + self.link( 511 + eco_format!("{path}.html#{name}", path = path.join("/")), 512 + qualified_name, 513 + Some(title), 514 + ) 463 515 } else { 464 516 let module_name = module.split('/').next_back().unwrap_or(module); 465 517 let qualified_name = docvec![
+54 -11
compiler-core/src/docs/tests.rs
··· 133 133 } 134 134 135 135 fn compile_documentation( 136 - main_module: &str, 136 + module_name: &str, 137 + module_src: &str, 137 138 modules: Vec<(&str, &str, &str)>, 138 139 options: PrintOptions, 139 140 ) -> EcoString { 140 - let module = type_::tests::compile_module("main", main_module, None, modules.clone()) 141 + let module = type_::tests::compile_module(module_name, module_src, None, modules.clone()) 141 142 .expect("Module should compile successfully"); 142 143 143 144 let mut config = PackageConfig::default(); ··· 145 146 let paths = ProjectPaths::new("/".into()); 146 147 let build_module = build::Module { 147 148 name: "main".into(), 148 - code: main_module.into(), 149 + code: module_src.into(), 149 150 mtime: SystemTime::now(), 150 151 input_path: "/".into(), 151 152 origin: Origin::Src, ··· 168 169 let types = module 169 170 .definitions 170 171 .iter() 171 - .filter_map(|statement| printer.type_definition(&source_links, statement)) 172 + .filter_map( 173 + |statement: &crate::ast::Definition< 174 + std::sync::Arc<type_::Type>, 175 + crate::ast::TypedExpr, 176 + EcoString, 177 + EcoString, 178 + >| printer.type_definition(&source_links, statement), 179 + ) 172 180 .sorted() 173 181 .collect_vec(); 174 182 ··· 185 193 for (_package, name, src) in modules { 186 194 output.push_str(&format!("-- {name}.gleam\n{src}\n\n")); 187 195 } 188 - output.push_str("-- main.gleam\n"); 189 - output.push_str(main_module); 196 + output.push_str("-- "); 197 + output.push_str(module_name); 198 + output.push_str(".gleam\n"); 199 + output.push_str(module_src); 190 200 191 201 if !types.is_empty() { 192 202 output.push_str("\n\n---- TYPES"); ··· 241 251 }; 242 252 243 253 ($src:literal, $options:expr $(,)?) => { 244 - let output = compile_documentation($src, Vec::new(), $options); 254 + let output = compile_documentation("main", $src, Vec::new(), $options); 245 255 insta::assert_snapshot!(output); 246 256 }; 247 257 248 258 ($(($name:expr, $module_src:literal)),+, $src:literal $(,)?) => { 249 - let output = compile_documentation($src, vec![$(("thepackage", $name, $module_src)),*], PrintOptions::all()); 259 + let output = compile_documentation("main", $src, vec![$(("thepackage", $name, $module_src)),*], PrintOptions::all()); 250 260 insta::assert_snapshot!(output); 251 261 }; 252 262 253 263 ($(($name:expr, $module_src:literal)),+, $src:literal, $options:expr $(,)?) => { 254 - let output = compile_documentation($src, vec![$(("thepackage", $name, $module_src)),*], $options); 264 + let output = compile_documentation("main", $src, vec![$(("thepackage", $name, $module_src)),*], $options); 265 + insta::assert_snapshot!(output); 266 + }; 267 + 268 + ($(($name:expr, $module_src:literal)),+, $main_module:literal, $src:literal, $options:expr $(,)?) => { 269 + let output = compile_documentation($main_module, $src, vec![$(("thepackage", $name, $module_src)),*], $options); 255 270 insta::assert_snapshot!(output); 256 271 }; 257 272 258 273 ($(($package:expr, $name:expr, $module_src:literal)),+, $src:literal $(,)?) => { 259 - let output = compile_documentation($src, vec![$(($package, $name, $module_src)),*], PrintOptions::all()); 274 + let output = compile_documentation("main", $src, vec![$(($package, $name, $module_src)),*], PrintOptions::all()); 260 275 insta::assert_snapshot!(output); 261 276 }; 262 277 263 278 ($(($package:expr, $name:expr, $module_src:literal)),+, $src:literal, $options:expr $(,)?) => { 264 - let output = compile_documentation($src, vec![$(($package, $name, $module_src)),*], $options); 279 + let output = compile_documentation("main", $src, vec![$(($package, $name, $module_src)),*], $options); 265 280 insta::assert_snapshot!(output); 266 281 }; 267 282 } ··· 829 844 import gleam/dict 830 845 831 846 pub fn make_dict() -> dict.Dict(a, b) { todo } 847 + ", 848 + ONLY_LINKS 849 + ); 850 + } 851 + 852 + #[test] 853 + fn link_to_type_in_different_module_from_nested_module() { 854 + assert_documentation!( 855 + ("gleam/dict", "pub type Dict(a, b)"), 856 + "gleam/dynamic/decode", 857 + " 858 + import gleam/dict 859 + 860 + pub fn decode_dict() -> dict.Dict(a, b) { todo } 861 + ", 862 + ONLY_LINKS 863 + ); 864 + } 865 + 866 + #[test] 867 + fn link_to_type_in_different_module_from_nested_module_with_shared_path() { 868 + assert_documentation!( 869 + ("gleam/dynamic", "pub type Dynamic"), 870 + "gleam/dynamic/decode", 871 + " 872 + import gleam/dynamic 873 + 874 + pub type Dynamic = dynamic.Dynamic 832 875 ", 833 876 ONLY_LINKS 834 877 );