alpha
Login
or
Join now
nandi.uk
/
gleam
Star
2
Fork
0
Atom
Configure Feed
Issues
Pull Requests
Commits
Tags
Feed URL
Select the types of activity you want to include in your feed.
Fork of daniellemaywood.uk/gleam — Wasm codegen work
Star
2
Fork
0
Atom
Configure Feed
Issues
Pull Requests
Commits
Tags
Feed URL
Select the types of activity you want to include in your feed.
Overview
Issues
Pulls
Pipelines
Fix links for external dependencies
author
GearsDatapacks
committer
Louis Pilfold
date
1 year ago
(May 12, 2025, 10:29 AM +0100)
commit
5e202f96
5e202f96077529d3f63afa042ac747f5583fadd8
parent
a7e2d4c8
a7e2d4c873d05ef605492e82e16bd27bbeef4f40
+276
-25
8 changed files
Expand all
Collapse all
Unified
Split
compiler-cli
src
docs.rs
publish.rs
compiler-core
src
docs
printer.rs
snapshots
gleam_core__docs__tests__link_to_type_in_different_package.snap
gleam_core__docs__tests__no_link_to_type_in_git_dependency.snap
gleam_core__docs__tests__no_link_to_type_in_path_dependency.snap
tests.rs
docs.rs
+51
-4
compiler-cli/src/docs.rs
View file
Reviewed
···
1
1
-
use std::time::{Instant, SystemTime};
1
1
+
use std::{
2
2
+
collections::HashMap,
3
3
+
time::{Instant, SystemTime},
4
4
+
};
2
5
3
6
use camino::{Utf8Path, Utf8PathBuf};
4
7
use ecow::EcoString;
···
9
12
analyse::TargetSupport,
10
13
build::{Codegen, Compile, Mode, Options, Package, Target},
11
14
config::{DocsPage, PackageConfig},
12
12
-
docs::DocContext,
15
15
+
docs::{Dependency, DependencyKind, DocContext},
13
16
error::Error,
14
17
hex,
15
18
io::HttpClient as _,
19
19
+
manifest::ManifestPackageSource,
16
20
paths::ProjectPaths,
17
21
type_,
18
22
};
···
49
53
crate::fs::delete_directory(&paths.build_directory_for_target(Mode::Prod, config.target))?;
50
54
51
55
let out = paths.build_documentation_directory(&config.name);
56
56
+
57
57
+
let manifest = crate::build::download_dependencies(paths, cli::Reporter::new())?;
58
58
+
let dependencies = manifest
59
59
+
.packages
60
60
+
.iter()
61
61
+
.map(|package| {
62
62
+
(
63
63
+
package.name.clone(),
64
64
+
Dependency {
65
65
+
version: package.version.clone(),
66
66
+
kind: match &package.source {
67
67
+
ManifestPackageSource::Hex { .. } => DependencyKind::Hex,
68
68
+
ManifestPackageSource::Git { .. } => DependencyKind::Git,
69
69
+
ManifestPackageSource::Local { .. } => DependencyKind::Path,
70
70
+
},
71
71
+
},
72
72
+
)
73
73
+
})
74
74
+
.collect();
75
75
+
52
76
let mut built = crate::build::main(
53
77
paths,
54
78
Options {
···
60
84
root_target_support: TargetSupport::Enforced,
61
85
no_print_progress: false,
62
86
},
63
63
-
crate::build::download_dependencies(paths, cli::Reporter::new())?,
87
87
+
manifest,
64
88
)?;
65
89
let outputs = build_documentation(
66
90
paths,
67
91
&config,
92
92
+
dependencies,
68
93
&mut built.root_package,
69
94
DocContext::Build,
70
95
&built.module_interfaces,
···
106
131
pub(crate) fn build_documentation(
107
132
paths: &ProjectPaths,
108
133
config: &PackageConfig,
134
134
+
dependencies: HashMap<EcoString, Dependency>,
109
135
compiled: &mut Package,
110
136
is_hex_publish: DocContext,
111
137
cached_modules: &im::HashMap<EcoString, type_::ModuleInterface>,
···
121
147
let mut outputs = gleam_core::docs::generate_html(
122
148
paths,
123
149
config,
150
150
+
dependencies,
124
151
compiled.modules.as_slice(),
125
152
&pages,
126
153
ProjectIO::new(),
···
147
174
// Reset the build directory so we know the state of the project
148
175
crate::fs::delete_directory(&paths.build_directory_for_target(Mode::Prod, config.target))?;
149
176
177
177
+
let manifest = crate::build::download_dependencies(paths, cli::Reporter::new())?;
178
178
+
let dependencies = manifest
179
179
+
.packages
180
180
+
.iter()
181
181
+
.map(|package| {
182
182
+
(
183
183
+
package.name.clone(),
184
184
+
Dependency {
185
185
+
version: package.version.clone(),
186
186
+
kind: match &package.source {
187
187
+
ManifestPackageSource::Hex { .. } => DependencyKind::Hex,
188
188
+
ManifestPackageSource::Git { .. } => DependencyKind::Git,
189
189
+
ManifestPackageSource::Local { .. } => DependencyKind::Path,
190
190
+
},
191
191
+
},
192
192
+
)
193
193
+
})
194
194
+
.collect();
195
195
+
150
196
let mut built = crate::build::main(
151
197
paths,
152
198
Options {
···
158
204
target: None,
159
205
no_print_progress: false,
160
206
},
161
161
-
crate::build::download_dependencies(paths, cli::Reporter::new())?,
207
207
+
manifest,
162
208
)?;
163
209
let outputs = build_documentation(
164
210
paths,
165
211
&config,
212
212
+
dependencies,
166
213
&mut built.root_package,
167
214
DocContext::HexPublish,
168
215
&built.module_interfaces,
+27
-3
compiler-cli/src/publish.rs
View file
Reviewed
···
6
6
analyse::TargetSupport,
7
7
build::{Codegen, Compile, Mode, Options, Package, Target},
8
8
config::{GleamVersion, PackageConfig, SpdxLicense},
9
9
-
docs::DocContext,
9
9
+
docs::{Dependency, DependencyKind, DocContext},
10
10
error::{SmallVersion, wrap},
11
11
hex,
12
12
+
manifest::ManifestPackageSource,
12
13
paths::{self, ProjectPaths},
13
14
requirement::Requirement,
14
15
type_,
···
16
17
use hexpm::version::{Range, Version};
17
18
use itertools::Itertools;
18
19
use sha2::Digest;
19
19
-
use std::{io::Write, path::PathBuf, time::Instant};
20
20
+
use std::{collections::HashMap, io::Write, path::PathBuf, time::Instant};
20
21
21
22
use crate::{build, cli, docs, fs, http::HttpClient};
22
23
···
38
39
data: package_tarball,
39
40
src_files_added,
40
41
generated_files_added,
42
42
+
dependencies,
41
43
} = do_build_hex_tarball(paths, &mut config)?;
42
44
43
45
check_for_name_squatting(&compile_result)?;
···
47
49
let docs_tarball = fs::create_tar_archive(docs::build_documentation(
48
50
paths,
49
51
&config,
52
52
+
dependencies,
50
53
&mut compile_result,
51
54
DocContext::HexPublish,
52
55
&cached_modules,
···
271
274
data: Vec<u8>,
272
275
src_files_added: Vec<Utf8PathBuf>,
273
276
generated_files_added: Vec<(Utf8PathBuf, String)>,
277
277
+
dependencies: HashMap<EcoString, Dependency>,
274
278
}
275
279
276
280
pub fn build_hex_tarball(paths: &ProjectPaths, config: &mut PackageConfig) -> Result<Vec<u8>> {
···
285
289
// Reset the build directory so we know the state of the project
286
290
fs::delete_directory(&paths.build_directory_for_target(Mode::Prod, target))?;
287
291
292
292
+
let manifest = build::download_dependencies(paths, cli::Reporter::new())?;
293
293
+
let dependencies = manifest
294
294
+
.packages
295
295
+
.iter()
296
296
+
.map(|package| {
297
297
+
(
298
298
+
package.name.clone(),
299
299
+
Dependency {
300
300
+
version: package.version.clone(),
301
301
+
kind: match &package.source {
302
302
+
ManifestPackageSource::Hex { .. } => DependencyKind::Hex,
303
303
+
ManifestPackageSource::Git { .. } => DependencyKind::Git,
304
304
+
ManifestPackageSource::Local { .. } => DependencyKind::Path,
305
305
+
},
306
306
+
},
307
307
+
)
308
308
+
})
309
309
+
.collect();
310
310
+
288
311
// Build the project to check that it is valid
289
312
let built = build::main(
290
313
paths,
···
297
320
compile: Compile::All,
298
321
no_print_progress: false,
299
322
},
300
300
-
build::download_dependencies(paths, cli::Reporter::new())?,
323
323
+
manifest,
301
324
)?;
302
325
303
326
let minimum_required_version = built.minimum_required_version();
···
399
422
data: tarball,
400
423
src_files_added: src_files,
401
424
generated_files_added: generated_files,
425
425
+
dependencies,
402
426
})
403
427
}
404
428
+19
-1
compiler-core/src/docs.rs
View file
Reviewed
···
3
3
#[cfg(test)]
4
4
mod tests;
5
5
6
6
-
use std::time::SystemTime;
6
6
+
use std::{collections::HashMap, time::SystemTime};
7
7
8
8
use camino::Utf8PathBuf;
9
9
+
use hexpm::version::Version;
9
10
use printer::Printer;
10
11
11
12
use crate::{
···
36
37
package_config: PackageConfig,
37
38
}
38
39
40
40
+
/// Like `ManifestPackage`, but lighter and cheaper to clone as it is all that
41
41
+
/// we need for printing documentation.
42
42
+
#[derive(Debug, Clone)]
43
43
+
pub struct Dependency {
44
44
+
pub version: Version,
45
45
+
pub kind: DependencyKind,
46
46
+
}
47
47
+
48
48
+
#[derive(Debug, Clone, Copy)]
49
49
+
pub enum DependencyKind {
50
50
+
Hex,
51
51
+
Path,
52
52
+
Git,
53
53
+
}
54
54
+
39
55
pub fn generate_html<IO: FileSystemReader>(
40
56
paths: &ProjectPaths,
41
57
config: &PackageConfig,
58
58
+
dependencies: HashMap<EcoString, Dependency>,
42
59
analysed: &[Module],
43
60
docs_pages: &[DocsPage],
44
61
fs: IO,
···
174
191
module.ast.type_info.package.clone(),
175
192
module.name.clone(),
176
193
&module.ast.names,
194
194
+
&dependencies,
177
195
);
178
196
179
197
let types: Vec<TypeDefinition<'_>> = module
+35
-8
compiler-core/src/docs/printer.rs
View file
Reviewed
···
20
20
};
21
21
22
22
use super::{
23
23
-
DocsValues, TypeConstructor, TypeConstructorArg, TypeDefinition, markdown_documentation,
24
24
-
source_links::SourceLinker, text_documentation,
23
23
+
Dependency, DependencyKind, DocsValues, TypeConstructor, TypeConstructorArg, TypeDefinition,
24
24
+
markdown_documentation, source_links::SourceLinker, text_documentation,
25
25
};
26
26
27
27
#[derive(Clone, Copy)]
···
55
55
/// An incrementing number used to generate the next type variable name.
56
56
/// `0` becomes `a`, `1` becomes `b`, etc.
57
57
next_type_variable_id: u64,
58
58
+
59
59
+
dependencies: &'a HashMap<EcoString, Dependency>,
58
60
}
59
61
60
62
impl Printer<'_> {
61
61
-
pub fn new(package: EcoString, module: EcoString, names: &Names) -> Printer<'_> {
63
63
+
pub fn new<'a>(
64
64
+
package: EcoString,
65
65
+
module: EcoString,
66
66
+
names: &'a Names,
67
67
+
dependencies: &'a HashMap<EcoString, Dependency>,
68
68
+
) -> Printer<'a> {
62
69
Printer {
63
70
options: PrintOptions::all(),
64
71
names,
···
67
74
printed_type_variables: HashMap::new(),
68
75
printed_type_variable_names: HashSet::new(),
69
76
next_type_variable_id: 0,
77
77
+
dependencies,
70
78
}
71
79
}
72
80
···
521
529
];
522
530
let title = eco_format!("{module}.{{type {name}}}");
523
531
524
524
-
self.link(
525
525
-
eco_format!("https://hexdocs.pm/{package}/{module}.html#{name}"),
526
526
-
qualified_name,
527
527
-
Some(title),
528
528
-
)
532
532
+
// We can't reliably link to documentation if the type is from a path
533
533
+
// or git dependency
534
534
+
match self.dependencies.get(package) {
535
535
+
Some(Dependency {
536
536
+
kind: DependencyKind::Hex,
537
537
+
version,
538
538
+
}) => self.link(
539
539
+
eco_format!("https://hexdocs.pm/{package}/{version}/{module}.html#{name}"),
540
540
+
qualified_name,
541
541
+
Some(title),
542
542
+
),
543
543
+
Some(_) | None => self.span_with_title(qualified_name, title),
544
544
+
}
529
545
}
530
546
}
531
547
···
624
640
name.to_doc().surround(
625
641
zero_width_string(opening_tag),
626
642
zero_width_string("</a>".into()),
643
643
+
)
644
644
+
}
645
645
+
646
646
+
fn span_with_title<'a>(&self, name: impl Documentable<'a>, title: EcoString) -> Document<'a> {
647
647
+
if !self.options.print_links {
648
648
+
return name.to_doc();
649
649
+
}
650
650
+
651
651
+
name.to_doc().surround(
652
652
+
zero_width_string(eco_format!(r#"<span title="{title}">"#)),
653
653
+
zero_width_string("</span>".into()),
627
654
)
628
655
}
629
656
}
+1
-1
compiler-core/src/docs/snapshots/gleam_core__docs__tests__link_to_type_in_different_package.snap
View file
Reviewed
···
16
16
---- VALUES
17
17
18
18
--- make_dict
19
19
-
<pre><code>pub fn make_dict() -> <a href="https://hexdocs.pm/gleam_stdlib/gleam/dict.html#Dict" title="gleam/dict.{type Dict}">dict.Dict</a>(a, b)</code></pre>
19
19
+
<pre><code>pub fn make_dict() -> <a href="https://hexdocs.pm/gleam_stdlib/1.0.0/gleam/dict.html#Dict" title="gleam/dict.{type Dict}">dict.Dict</a>(a, b)</code></pre>
+19
compiler-core/src/docs/snapshots/gleam_core__docs__tests__no_link_to_type_in_git_dependency.snap
View file
Reviewed
···
1
1
+
---
2
2
+
source: compiler-core/src/docs/tests.rs
3
3
+
expression: output
4
4
+
---
5
5
+
---- SOURCE CODE
6
6
+
-- gleam/dict.gleam
7
7
+
pub type Dict(a, b)
8
8
+
9
9
+
-- main.gleam
10
10
+
11
11
+
import gleam/dict
12
12
+
13
13
+
pub fn make_dict() -> dict.Dict(a, b) { todo }
14
14
+
15
15
+
16
16
+
---- VALUES
17
17
+
18
18
+
--- make_dict
19
19
+
<pre><code>pub fn make_dict() -> <span title="gleam/dict.{type Dict}">dict.Dict</span>(a, b)</code></pre>
+19
compiler-core/src/docs/snapshots/gleam_core__docs__tests__no_link_to_type_in_path_dependency.snap
View file
Reviewed
···
1
1
+
---
2
2
+
source: compiler-core/src/docs/tests.rs
3
3
+
expression: output
4
4
+
---
5
5
+
---- SOURCE CODE
6
6
+
-- gleam/dict.gleam
7
7
+
pub type Dict(a, b)
8
8
+
9
9
+
-- main.gleam
10
10
+
11
11
+
import gleam/dict
12
12
+
13
13
+
pub fn make_dict() -> dict.Dict(a, b) { todo }
14
14
+
15
15
+
16
16
+
---- VALUES
17
17
+
18
18
+
--- make_dict
19
19
+
<pre><code>pub fn make_dict() -> <span title="gleam/dict.{type Dict}">dict.Dict</span>(a, b)</code></pre>
+105
-8
compiler-core/src/docs/tests.rs
View file
Reviewed
···
1
1
-
use std::{collections::HashSet, time::SystemTime};
1
1
+
use std::{
2
2
+
collections::{HashMap, HashSet},
3
3
+
time::SystemTime,
4
4
+
};
2
5
3
6
use super::{
4
4
-
SearchData, SearchItem, SearchItemType, SearchProgrammingLanguage,
7
7
+
Dependency, DependencyKind, SearchData, SearchItem, SearchItemType, SearchProgrammingLanguage,
5
8
printer::{PrintOptions, Printer},
6
9
source_links::SourceLinker,
7
10
};
···
21
24
};
22
25
use camino::Utf8PathBuf;
23
26
use ecow::EcoString;
27
27
+
use hexpm::version::Version;
24
28
use itertools::Itertools;
25
29
use serde_json::to_string as serde_to_string;
26
30
···
96
100
super::generate_html(
97
101
&paths,
98
102
&config,
103
103
+
HashMap::new(),
99
104
&modules,
100
105
&docs_pages,
101
106
pages_fs,
···
136
141
module_name: &str,
137
142
module_src: &str,
138
143
modules: Vec<(&str, &str, &str)>,
144
144
+
dependency_kind: DependencyKind,
139
145
options: PrintOptions,
140
146
) -> EcoString {
141
147
let module = type_::tests::compile_module(module_name, module_src, None, modules.clone())
···
158
164
let source_links = SourceLinker::new(&paths, &config, &build_module);
159
165
160
166
let module = build_module.ast;
167
167
+
let dependencies = modules
168
168
+
.iter()
169
169
+
.map(|(package, _, _)| {
170
170
+
(
171
171
+
EcoString::from(*package),
172
172
+
Dependency {
173
173
+
version: Version::new(1, 0, 0),
174
174
+
kind: dependency_kind,
175
175
+
},
176
176
+
)
177
177
+
})
178
178
+
.collect();
161
179
162
180
let mut printer = Printer::new(
163
181
module.type_info.package.clone(),
164
182
module.name.clone(),
165
183
&module.names,
184
184
+
&dependencies,
166
185
);
167
186
printer.set_options(options);
168
187
···
251
270
};
252
271
253
272
($src:literal, $options:expr $(,)?) => {
254
254
-
let output = compile_documentation("main", $src, Vec::new(), $options);
273
273
+
let output = compile_documentation("main", $src, Vec::new(), DependencyKind::Hex, $options);
255
274
insta::assert_snapshot!(output);
256
275
};
257
276
258
277
($(($name:expr, $module_src:literal)),+, $src:literal $(,)?) => {
259
259
-
let output = compile_documentation("main", $src, vec![$(("thepackage", $name, $module_src)),*], PrintOptions::all());
278
278
+
let output = compile_documentation(
279
279
+
"main",
280
280
+
$src,
281
281
+
vec![$(("thepackage", $name, $module_src)),*],
282
282
+
DependencyKind::Hex,
283
283
+
PrintOptions::all(),
284
284
+
);
260
285
insta::assert_snapshot!(output);
261
286
};
262
287
263
288
($(($name:expr, $module_src:literal)),+, $src:literal, $options:expr $(,)?) => {
264
264
-
let output = compile_documentation("main", $src, vec![$(("thepackage", $name, $module_src)),*], $options);
289
289
+
let output = compile_documentation(
290
290
+
"main",
291
291
+
$src,
292
292
+
vec![$(("thepackage", $name, $module_src)),*],
293
293
+
DependencyKind::Hex,
294
294
+
$options,
295
295
+
);
265
296
insta::assert_snapshot!(output);
266
297
};
267
298
268
299
($(($name:expr, $module_src:literal)),+, $main_module:literal, $src:literal, $options:expr $(,)?) => {
269
269
-
let output = compile_documentation($main_module, $src, vec![$(("thepackage", $name, $module_src)),*], $options);
300
300
+
let output = compile_documentation(
301
301
+
$main_module,
302
302
+
$src,
303
303
+
vec![$(("thepackage", $name, $module_src)),*],
304
304
+
DependencyKind::Hex,
305
305
+
$options,
306
306
+
);
270
307
insta::assert_snapshot!(output);
271
308
};
272
309
273
310
($(($package:expr, $name:expr, $module_src:literal)),+, $src:literal $(,)?) => {
274
274
-
let output = compile_documentation("main", $src, vec![$(($package, $name, $module_src)),*], PrintOptions::all());
311
311
+
let output = compile_documentation(
312
312
+
"main",
313
313
+
$src,
314
314
+
vec![$(($package, $name, $module_src)),*],
315
315
+
DependencyKind::Hex,
316
316
+
PrintOptions::all(),
317
317
+
);
275
318
insta::assert_snapshot!(output);
276
319
};
277
320
278
321
($(($package:expr, $name:expr, $module_src:literal)),+, $src:literal, $options:expr $(,)?) => {
279
279
-
let output = compile_documentation("main", $src, vec![$(($package, $name, $module_src)),*], $options);
322
322
+
let output = compile_documentation(
323
323
+
"main",
324
324
+
$src,
325
325
+
vec![$(($package, $name, $module_src)),*],
326
326
+
DependencyKind::Hex,
327
327
+
$options,
328
328
+
);
329
329
+
insta::assert_snapshot!(output);
330
330
+
};
331
331
+
332
332
+
(git: $(($package:expr, $name:expr, $module_src:literal)),+, $src:literal, $options:expr $(,)?) => {
333
333
+
let output = compile_documentation(
334
334
+
"main",
335
335
+
$src,
336
336
+
vec![$(($package, $name, $module_src)),*],
337
337
+
DependencyKind::Git,
338
338
+
$options,
339
339
+
);
340
340
+
insta::assert_snapshot!(output);
341
341
+
};
342
342
+
343
343
+
(path: $(($package:expr, $name:expr, $module_src:literal)),+, $src:literal, $options:expr $(,)?) => {
344
344
+
let output = compile_documentation(
345
345
+
"main",
346
346
+
$src,
347
347
+
vec![$(($package, $name, $module_src)),*],
348
348
+
DependencyKind::Path,
349
349
+
$options,
350
350
+
);
280
351
insta::assert_snapshot!(output);
281
352
};
282
353
}
···
882
953
fn link_to_type_in_different_package() {
883
954
assert_documentation!(
884
955
("gleam_stdlib", "gleam/dict", "pub type Dict(a, b)"),
956
956
+
"
957
957
+
import gleam/dict
958
958
+
959
959
+
pub fn make_dict() -> dict.Dict(a, b) { todo }
960
960
+
",
961
961
+
ONLY_LINKS
962
962
+
);
963
963
+
}
964
964
+
965
965
+
#[test]
966
966
+
fn no_link_to_type_in_git_dependency() {
967
967
+
assert_documentation!(
968
968
+
git: ("gleam_stdlib", "gleam/dict", "pub type Dict(a, b)"),
969
969
+
"
970
970
+
import gleam/dict
971
971
+
972
972
+
pub fn make_dict() -> dict.Dict(a, b) { todo }
973
973
+
",
974
974
+
ONLY_LINKS
975
975
+
);
976
976
+
}
977
977
+
978
978
+
#[test]
979
979
+
fn no_link_to_type_in_path_dependency() {
980
980
+
assert_documentation!(
981
981
+
path: ("gleam_stdlib", "gleam/dict", "pub type Dict(a, b)"),
885
982
"
886
983
import gleam/dict
887
984