Skip to content

Commit

Permalink
Correctly print prelude types when shadowed by an alias of a non-name…
Browse files Browse the repository at this point in the history
…d type
  • Loading branch information
GearsDatapacks committed Sep 10, 2024
1 parent 53aba14 commit 2faacfc
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 3 deletions.
7 changes: 7 additions & 0 deletions compiler-core/src/analyse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1129,7 +1129,14 @@ impl<'a, A> ModuleAnalyzer<'a, A> {
type_name.clone(),
name.clone(),
);
} else {
// We need to make sure we register the type as existing, even if we don't define
// the underlying type for printing, because these types do still affect printing,
// for shadowing prelude types, even if they aren't printed at all.
environment.names.type_exists_in_scope(name);
}
} else {
environment.names.type_exists_in_scope(name);
}

// Insert the alias so that it can be used by other code.
Expand Down
2 changes: 2 additions & 0 deletions compiler-core/src/analyse/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ impl<'context, 'problems> Importer<'context, 'problems> {
name.clone(),
imported_name.clone(),
);
} else {
self.environment.names.type_exists_in_scope(imported_name);
}

if let Err(e) = self
Expand Down
26 changes: 26 additions & 0 deletions compiler-core/src/language_server/tests/hover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1168,3 +1168,29 @@ fn do_thing() -> LocalResult {
find_position_of("do_thing").under_char('d')
);
}

#[test]
fn hover_print_qualified_prelude_type_when_shadowed_by_alias() {
let code = "
type Result = #(Bool, String)
const ok = Ok(10)
";

assert_hover!(
TestProject::for_source(code),
find_position_of("ok").under_char('k')
);
}

#[test]
fn hover_print_qualified_prelude_type_when_shadowed_by_imported_alias() {
let code = "
import alias.{type Bool}
const value = True
";

assert_hover!(
TestProject::for_source(code).add_hex_module("alias", "pub type Bool = #(Int, Int)"),
find_position_of("value").under_char('v')
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
source: compiler-core/src/language_server/tests/hover.rs
expression: "\ntype Result = #(Bool, String)\nconst ok = Ok(10)\n"
---
type Result = #(Bool, String)
const ok = Ok(10)
▔▔▔▔▔▔▔↑


----- Hover content -----
Scalar(
String(
"```gleam\ngleam.Result(Int, a)\n```\n",
),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
source: compiler-core/src/language_server/tests/hover.rs
expression: "\nimport alias.{type Bool}\nconst value = True\n"
---
import alias.{type Bool}
const value = True
▔▔▔▔▔▔↑▔▔▔▔


----- Hover content -----
Scalar(
String(
"```gleam\ngleam.Bool\n```\n",
),
)
16 changes: 13 additions & 3 deletions compiler-core/src/type_/printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,14 +165,24 @@ impl Names {
type_name: EcoString,
local_alias: EcoString,
) {
// If this is a type in the prelude, it is now shadowed.
_ = self.unshadowed_prelude_types.remove(&local_alias);

self.type_exists_in_scope(&local_alias);
_ = self
.local_types
.insert((module_name, type_name), local_alias);
}

/// Record a type existing in the current module. This is for types
/// which define a name in the current scope, but do not represent a
/// named type (aliases). This exists so we can correctly print
/// prelude types, even if they are shadowed by an alias like:
/// ```gleam
/// type Pair = #(String, Int)
/// ```
pub fn type_exists_in_scope(&mut self, name: &EcoString) {
// If this is a type in the prelude, it is now shadowed.
_ = self.unshadowed_prelude_types.remove(name);
}

pub fn prelude_type(&mut self, name: EcoString) {
_ = self.unshadowed_prelude_types.insert(name);
}
Expand Down

0 comments on commit 2faacfc

Please sign in to comment.