Skip to content

Commit dfa63a6

Browse files
GearsDatapackslpil
authored andcommitted
Print public type names when generating documentation
1 parent d52d084 commit dfa63a6

10 files changed

+282
-36
lines changed

compiler-core/src/analyse.rs

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,19 +1403,24 @@ impl<'a, A> ModuleAnalyzer<'a, A> {
14031403
},
14041404
)?;
14051405

1406-
environment.insert_type_alias(
1407-
name.clone(),
1408-
TypeAliasConstructor {
1409-
origin: *location,
1410-
module: self.module_name.clone(),
1411-
type_,
1412-
publicity: *publicity,
1413-
deprecation: deprecation.clone(),
1414-
documentation: documentation.as_ref().map(|(_, doc)| doc.clone()),
1415-
arity,
1416-
parameters,
1417-
},
1418-
)?;
1406+
let alias = TypeAliasConstructor {
1407+
origin: *location,
1408+
module: self.module_name.clone(),
1409+
type_,
1410+
publicity: *publicity,
1411+
deprecation: deprecation.clone(),
1412+
documentation: documentation.as_ref().map(|(_, doc)| doc.clone()),
1413+
arity,
1414+
parameters,
1415+
};
1416+
1417+
environment.names.maybe_register_reexport_alias(
1418+
&environment.current_package,
1419+
&name,
1420+
&alias,
1421+
);
1422+
1423+
environment.insert_type_alias(name.clone(), alias)?;
14191424

14201425
if let Some(name) = hydrator.unused_type_variables().next() {
14211426
return Err(Error::UnusedTypeAliasParameter {

compiler-core/src/docs/printer.rs

Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ use crate::{
1515
docvec,
1616
pretty::{Document, Documentable, break_, join, line, nil, zero_width_string},
1717
type_::{
18-
Deprecation, PRELUDE_MODULE_NAME, PRELUDE_PACKAGE_NAME, Type, TypeVar, printer::Names,
18+
Deprecation, PRELUDE_MODULE_NAME, PRELUDE_PACKAGE_NAME, Type, TypeVar,
19+
printer::{Names, PrintMode},
1920
},
2021
};
2122

@@ -279,8 +280,11 @@ impl Printer<'_> {
279280

280281
let arguments = constructor.arguments.iter().map(
281282
|RecordConstructorArg { label, type_, .. }| match label {
282-
Some((_, label)) => self.variable(label).append(": ").append(self.type_(type_)),
283-
None => self.type_(type_),
283+
Some((_, label)) => self
284+
.variable(label)
285+
.append(": ")
286+
.append(self.type_(type_, PrintMode::Normal)),
287+
None => self.type_(type_, PrintMode::Normal),
284288
},
285289
);
286290

@@ -309,7 +313,9 @@ impl Printer<'_> {
309313
self.title(name),
310314
parameters,
311315
" =",
312-
line().append(self.type_(type_)).nest(INDENT)
316+
line()
317+
.append(self.type_(type_, PrintMode::ExpandAliases))
318+
.nest(INDENT)
313319
]
314320
}
315321

@@ -320,7 +326,7 @@ impl Printer<'_> {
320326
self.keyword("pub const "),
321327
self.title(name),
322328
": ",
323-
self.type_(type_)
329+
self.type_(type_, PrintMode::Normal)
324330
]
325331
}
326332

@@ -340,7 +346,7 @@ impl Printer<'_> {
340346
} else {
341347
Self::wrap_arguments(arguments.iter().map(|argument| {
342348
let name = self.variable(self.argument_name(argument));
343-
docvec![name, ": ", self.type_(&argument.type_)].group()
349+
docvec![name, ": ", self.type_(&argument.type_, PrintMode::Normal)].group()
344350
}))
345351
};
346352

@@ -349,7 +355,7 @@ impl Printer<'_> {
349355
self.title(name),
350356
arguments,
351357
" -> ",
352-
self.type_(return_type)
358+
self.type_(return_type, PrintMode::Normal)
353359
]
354360
.group()
355361
}
@@ -387,7 +393,7 @@ impl Printer<'_> {
387393
.surround("(", ")")
388394
}
389395

390-
fn type_(&mut self, type_: &Type) -> Document<'static> {
396+
fn type_(&mut self, type_: &Type, print_mode: PrintMode) -> Document<'static> {
391397
match type_ {
392398
Type::Named {
393399
package,
@@ -397,27 +403,62 @@ impl Printer<'_> {
397403
publicity,
398404
..
399405
} => {
400-
let name = self.named_type_name(publicity, package, module, name);
406+
let name = match print_mode {
407+
// If we are printing a type for a type alias, and the alias
408+
// is reexporting an internal type, we want to show that it
409+
// is aliasing that internal type, rather than showing it as
410+
// aliasing itself.
411+
PrintMode::ExpandAliases if *package == self.package => {
412+
self.named_type_name(publicity, package, module, name)
413+
}
414+
// If we are printing a type alias which aliases an internal
415+
// type from a different package, we still want to print the
416+
// public name for that type. If we are not printing a type
417+
// alias at all, we also want to use the public name.
418+
PrintMode::ExpandAliases | PrintMode::Normal => {
419+
// If we are using a reexported internal type, we want to
420+
// print it public name, whether it is from this package
421+
// or otherwise.
422+
if let Some((module, alias)) =
423+
self.names.reexport_alias(module.clone(), name.clone())
424+
{
425+
self.named_type_name(&Publicity::Public, package, module, alias)
426+
} else {
427+
self.named_type_name(publicity, package, module, name)
428+
}
429+
}
430+
};
431+
401432
if arguments.is_empty() {
402433
name
403434
} else {
404435
name.append(Self::type_arguments(
405-
arguments.iter().map(|argument| self.type_(argument)),
436+
arguments
437+
.iter()
438+
.map(|argument| self.type_(argument, PrintMode::Normal)),
406439
))
407440
}
408441
}
409442
Type::Fn { arguments, return_ } => docvec![
410443
self.keyword("fn"),
411-
Self::type_arguments(arguments.iter().map(|argument| self.type_(argument))),
444+
Self::type_arguments(
445+
arguments
446+
.iter()
447+
.map(|argument| self.type_(argument, PrintMode::Normal))
448+
),
412449
" -> ",
413-
self.type_(return_)
450+
self.type_(return_, PrintMode::Normal)
414451
],
415452
Type::Tuple { elements } => docvec![
416453
"#",
417-
Self::type_arguments(elements.iter().map(|element| self.type_(element))),
454+
Self::type_arguments(
455+
elements
456+
.iter()
457+
.map(|element| self.type_(element, PrintMode::Normal))
458+
),
418459
],
419460
Type::Var { type_ } => match type_.as_ref().borrow().deref() {
420-
TypeVar::Link { type_ } => self.type_(type_),
461+
TypeVar::Link { type_ } => self.type_(type_, PrintMode::Normal),
421462

422463
TypeVar::Unbound { id } | TypeVar::Generic { id } => {
423464
let name = self.type_variable(*id);
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
source: compiler-core/src/docs/tests.rs
3+
expression: output
4+
---
5+
---- SOURCE CODE
6+
-- thepackage/internal.gleam
7+
pub type Internal
8+
9+
-- main.gleam
10+
11+
import thepackage/internal
12+
13+
pub type External = internal.Internal
14+
15+
pub fn do_thing(value: internal.Internal) -> External {
16+
value
17+
}
18+
19+
20+
---- TYPES
21+
22+
--- External
23+
<pre><code>pub type External =
24+
@internal Internal</code></pre>
25+
26+
---- VALUES
27+
28+
--- do_thing
29+
<pre><code>pub fn do_thing(value: <a href="#External">External</a>) -> <a href="#External">External</a></code></pre>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
source: compiler-core/src/docs/tests.rs
3+
expression: output
4+
---
5+
---- SOURCE CODE
6+
-- thepackage/internal.gleam
7+
pub type Internal
8+
9+
-- thepackage/something.gleam
10+
11+
import thepackage/internal
12+
13+
pub type External = internal.Internal
14+
15+
16+
-- main.gleam
17+
18+
import thepackage/something
19+
20+
pub fn do_thing(value: something.External) {
21+
value
22+
}
23+
24+
25+
---- VALUES
26+
27+
--- do_thing
28+
<pre><code>pub fn do_thing(value: <a href="thepackage/something.html#External" title="thepackage/something.{type External}">something.External</a>) -> <a href="thepackage/something.html#External" title="thepackage/something.{type External}">something.External</a></code></pre>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
source: compiler-core/src/docs/tests.rs
3+
expression: output
4+
---
5+
---- SOURCE CODE
6+
-- some_package/internal.gleam
7+
pub type Internal
8+
9+
-- some_package/api.gleam
10+
11+
import some_package/internal
12+
pub type External = internal.Internal
13+
14+
15+
-- main.gleam
16+
17+
import some_package/api
18+
19+
pub fn do_thing(value: api.External) {
20+
value
21+
}
22+
23+
24+
---- VALUES
25+
26+
--- do_thing
27+
<pre><code>pub fn do_thing(value: <a href="https://hexdocs.pm/some_package/1.0.0/some_package/api.html#External" title="some_package/api.{type External}">api.External</a>) -> <a href="https://hexdocs.pm/some_package/1.0.0/some_package/api.html#External" title="some_package/api.{type External}">api.External</a></code></pre>

compiler-core/src/docs/tests.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,69 @@ pub type External =
11231123
);
11241124
}
11251125

1126+
#[test]
1127+
fn use_reexport_from_other_package() {
1128+
assert_documentation!(
1129+
("some_package", "some_package/internal", "pub type Internal"),
1130+
(
1131+
"some_package",
1132+
"some_package/api",
1133+
"
1134+
import some_package/internal
1135+
pub type External = internal.Internal
1136+
"
1137+
),
1138+
"
1139+
import some_package/api
1140+
1141+
pub fn do_thing(value: api.External) {
1142+
value
1143+
}
1144+
",
1145+
ONLY_LINKS
1146+
);
1147+
}
1148+
1149+
#[test]
1150+
fn function_uses_reexport_of_internal_type() {
1151+
assert_documentation!(
1152+
("thepackage/internal", "pub type Internal"),
1153+
"
1154+
import thepackage/internal
1155+
1156+
pub type External = internal.Internal
1157+
1158+
pub fn do_thing(value: internal.Internal) -> External {
1159+
value
1160+
}
1161+
",
1162+
ONLY_LINKS
1163+
);
1164+
}
1165+
1166+
#[test]
1167+
fn function_uses_reexport_of_internal_type_in_other_module() {
1168+
assert_documentation!(
1169+
("thepackage/internal", "pub type Internal"),
1170+
(
1171+
"thepackage/something",
1172+
"
1173+
import thepackage/internal
1174+
1175+
pub type External = internal.Internal
1176+
"
1177+
),
1178+
"
1179+
import thepackage/something
1180+
1181+
pub fn do_thing(value: something.External) {
1182+
value
1183+
}
1184+
",
1185+
ONLY_LINKS
1186+
);
1187+
}
1188+
11261189
#[test]
11271190
fn constructor_with_long_types_and_many_fields() {
11281191
assert_documentation!(

compiler-core/src/language_server/tests/action.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9894,3 +9894,34 @@ pub fn make_wibble(x) {
98949894
find_position_of("main").to_selection(),
98959895
);
98969896
}
9897+
9898+
#[test]
9899+
fn add_type_annotations_uses_internal_name_for_same_package() {
9900+
let src = "
9901+
import thepackage/internal
9902+
9903+
pub fn main() {
9904+
internal.Constructor
9905+
}
9906+
";
9907+
9908+
assert_code_action!(
9909+
ADD_ANNOTATION,
9910+
TestProject::for_source(src)
9911+
.add_module(
9912+
"thepackage/internal",
9913+
"
9914+
pub type Internal { Constructor }
9915+
"
9916+
)
9917+
.add_module(
9918+
"thepackage/external",
9919+
"
9920+
import thepackage/internal
9921+
9922+
pub type External = internal.Internal
9923+
"
9924+
),
9925+
find_position_of("main").to_selection(),
9926+
);
9927+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
source: compiler-core/src/language_server/tests/action.rs
3+
expression: "\nimport thepackage/internal\n\npub fn main() {\n internal.Constructor\n}\n"
4+
---
5+
----- BEFORE ACTION
6+
7+
import thepackage/internal
8+
9+
pub fn main() {
10+
11+
internal.Constructor
12+
}
13+
14+
15+
----- AFTER ACTION
16+
17+
import thepackage/internal
18+
19+
pub fn main() -> internal.Internal {
20+
internal.Constructor
21+
}

0 commit comments

Comments
 (0)