···1111 stable_graph::{NodeIndex, StableGraph},
1212};
13131414-#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
1414+/// Describes one of a number of situations where references can be generated.
1515+/// See each variant for an explanation.
1616+#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
1517pub enum ReferenceKind {
1616- Qualified,
1818+ /// A type or value which is referenced using the qualified syntax, along with
1919+ /// some information about the qualifier which is used for tracking module name
2020+ /// references. For example:
2121+ /// ```gleam
2222+ /// import gleam/option.{Some}
2323+ ///
2424+ /// pub fn main() -> option.Option(Int) {
2525+ /// // ^^^^^^ `module_location` covers this
2626+ /// Some(1)
2727+ /// }
2828+ /// ```
2929+ ///
3030+ /// Here, `module_alias` is `option`, as that's what's being used as a
3131+ /// qualifier.
3232+ ///
3333+ ///
3434+ /// ```gleam
3535+ /// import gleam/int as integer
3636+ ///
3737+ /// pub fn main() {
3838+ /// integer.add(1, 2)
3939+ /// //^^^^^^^ `module_location` covers this
4040+ /// }
4141+ /// ```
4242+ ///
4343+ /// In this case, `module_alias` is `integer`, due to the aliased import.
4444+ ///
4545+ Qualified {
4646+ module_alias: EcoString,
4747+ module_location: SrcSpan,
4848+ },
4949+ /// A type or value is being referenced using unqualified syntax. This may
5050+ /// be due to being imported unqualified, or because it's from the same
5151+ /// module. For example:
5252+ ///
5353+ /// ```gleam
5454+ /// import gleam/option.{None}
5555+ ///
5656+ /// pub fn main() {
5757+ /// none()
5858+ /// //^^^^ Unqualified
5959+ /// }
6060+ ///
6161+ /// fn none() {
6262+ /// None
6363+ /// //^^^^ Unqualified
6464+ /// }
6565+ /// ```
6666+ ///
1767 Unqualified,
6868+ /// A value or type is being referenced inside an unqualified import. For
6969+ /// example:
7070+ /// ```gleam
7171+ /// import gleam/option.{None}
7272+ /// // ^^^^ Import
7373+ /// import gleam/dynamic/decode.{type Dynamic}
7474+ /// // ^^^^^^^ Import
7575+ /// ```
1876 Import,
7777+ /// The original definition location of a type or value. This also counts as
7878+ /// a reference for renaming and "find references" purposes. For example:
7979+ ///
8080+ /// ```gleam
8181+ /// pub type Wibble {
8282+ /// // ^^^^^^ Definition
8383+ /// Wibble(Int)
8484+ /// //^^^^^^ Definition
8585+ /// }
8686+ ///
8787+ /// pub fn extract(w: Wibble) {
8888+ /// // ^^^^^^^ Definition
8989+ /// let Wibble(x) = w
9090+ /// x
9191+ /// }
9292+ /// ```
1993 Definition,
9494+ /// A value or type is being referenced using unqualified syntax, with a
9595+ /// name other than its original definition. This can be due to importing it
9696+ /// using an alias, or due to referencing it through a type alias. For example:
9797+ ///
9898+ /// ```gleam
9999+ /// import gleam/option.{None as Nothing, type Option as Maybe}
100100+ ///
101101+ /// pub fn nothing() -> Maybe(_) {
102102+ /// // ^^^^^ Alias
103103+ /// Nothing
104104+ /// //^^^^^^^ Alias
105105+ /// }
106106+ /// ```
107107+ ///
20108 Alias,
21109}
221102323-#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
111111+#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
24112pub struct Reference {
25113 pub location: SrcSpan,
26114 pub kind: ReferenceKind,
27115}
28116117117+/// A reference to a module name. This is similar to a `Reference`, which covers
118118+/// types and values, but it is separate because we care about slightly different
119119+/// pieces of information when, for example, renaming modules vs. renaming types
120120+/// or values.
121121+///
122122+#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
123123+pub enum ModuleNameReference {
124124+ /// The location of a module name in a `ModuleSelect`, when the module name
125125+ /// is not aliased. For example:
126126+ /// ```gleam
127127+ /// import gleam/option
128128+ ///
129129+ /// pub fn main() -> option.Option(_) {
130130+ /// // ^^^^^^ ModuleSelect
131131+ /// option.None
132132+ /// //^^^^^^ ModuleSelect
133133+ /// }
134134+ /// ```
135135+ ///
136136+ ModuleSelect(SrcSpan),
137137+ /// The location of a module name in a `ModuleSelect`, when the module name
138138+ /// *is* aliased. For example:
139139+ /// ```gleam
140140+ /// import gleam/option as maybe
141141+ ///
142142+ /// pub fn main() -> maybe.Option(_) {
143143+ /// // ^^^^^ AliasedModuleSelect
144144+ /// maybe.None
145145+ /// //^^^^^ AliasedModuleSelect
146146+ /// }
147147+ /// ```
148148+ ///
149149+ AliasedModuleSelect(SrcSpan),
150150+ /// The location of a module name in an `import` statement, when the module
151151+ /// name is not aliased. For example:
152152+ /// ```gleam
153153+ /// import gleam/option.{None, Some}
154154+ /// // ^^^^^^^^^^^^ Import ^ `import_end`
155155+ /// ```
156156+ ///
157157+ Import {
158158+ module_location: SrcSpan,
159159+ import_end: u32,
160160+ },
161161+ /// The location of a module name in an `import` statement, when the module
162162+ /// name *is* aliased. Also stores the location of the alias (including the
163163+ /// `as` keyword), and what the alias is. For example:
164164+ /// ```gleam
165165+ /// import gleam/option.{None, Some} as maybe
166166+ /// // ^^^^^^^^^^^^ `module_location`
167167+ /// // ^^^^^^^^ `alias_location`
168168+ /// ```
169169+ /// In this example, `alias` would be `maybe`.
170170+ ///
171171+ AliasedImport {
172172+ module_location: SrcSpan,
173173+ alias_location: SrcSpan,
174174+ alias: EcoString,
175175+ },
176176+}
177177+29178pub type ReferenceMap = HashMap<(EcoString, EcoString), Vec<Reference>>;
3017931180#[derive(Debug, Clone)]
···96245 /// The locations of the references to each type in this module, used for
97246 /// renaming and go-to reference.
98247 pub type_references: ReferenceMap,
248248+ /// The locations of the references to each imported module, used for
249249+ /// renaming and go-to reference.
250250+ pub module_references: HashMap<EcoString, Vec<ModuleNameReference>>,
99251100252 /// This map is used to access the nodes of modules that were not
101253 /// aliased, given their name.
···280432 module_name: EcoString,
281433 alias_location: SrcSpan,
282434 import_location: SrcSpan,
435435+ module_location: SrcSpan,
283436 ) {
284284- // We first record a node for the module being aliased. We use its entire
285285- // name to identify it in this case and keep track of the node it's
286286- // associated with.
287287- self.register_module(module_name.clone(), module_name.clone(), import_location);
437437+ // We first record a node for the module being aliased.
438438+ self.register_module(
439439+ used_name.clone(),
440440+ module_name.clone(),
441441+ import_location,
442442+ module_location,
443443+ Some(alias_location),
444444+ );
288445289446 // Then we create a node for the alias, as the alias itself might be
290447 // unused!
···315472 used_name: EcoString,
316473 module_name: EcoString,
317474 location: SrcSpan,
475475+ module_location: SrcSpan,
476476+ alias_location: Option<SrcSpan>,
318477 ) {
319478 self.current_node = self.create_node(used_name.clone(), EntityLayer::Module);
320479 let _ = self
321480 .module_name_to_node
322481 .insert(module_name.clone(), self.current_node);
323482483483+ let reference = if let Some(alias_location) = alias_location {
484484+ ModuleNameReference::AliasedImport {
485485+ module_location,
486486+ alias_location,
487487+ alias: used_name.clone(),
488488+ }
489489+ } else {
490490+ ModuleNameReference::Import {
491491+ module_location,
492492+ import_end: location.end,
493493+ }
494494+ };
495495+496496+ self.register_module_name_reference(module_name.clone(), reference);
497497+324498 let entity = Entity {
325499 name: used_name,
326500 layer: EntityLayer::Module,
···360534 location: SrcSpan,
361535 kind: ReferenceKind,
362536 ) {
363363- match kind {
364364- ReferenceKind::Qualified | ReferenceKind::Import | ReferenceKind::Definition => {}
537537+ match &kind {
538538+ ReferenceKind::Qualified {
539539+ module_alias,
540540+ module_location,
541541+ } => {
542542+ let last_module_segment = module.split('/').next_back().unwrap_or(&module);
543543+ let reference = if last_module_segment == module_alias {
544544+ ModuleNameReference::ModuleSelect(*module_location)
545545+ } else {
546546+ ModuleNameReference::AliasedModuleSelect(*module_location)
547547+ };
548548+ self.register_module_name_reference(module.clone(), reference);
549549+ }
550550+ ReferenceKind::Import | ReferenceKind::Definition => {}
365551 ReferenceKind::Alias | ReferenceKind::Unqualified => {
366552 let target = self.get_or_create_node(referenced_name.clone(), EntityLayer::Value);
367553 _ = self.graph.add_edge(self.current_node, target, ());
···382568 location: SrcSpan,
383569 kind: ReferenceKind,
384570 ) {
385385- match kind {
386386- ReferenceKind::Qualified | ReferenceKind::Import | ReferenceKind::Definition => {}
571571+ match &kind {
572572+ ReferenceKind::Qualified {
573573+ module_alias,
574574+ module_location,
575575+ } => {
576576+ let last_module_segment = module.split('/').next_back().unwrap_or(&module);
577577+ let reference = if last_module_segment == module_alias {
578578+ ModuleNameReference::ModuleSelect(*module_location)
579579+ } else {
580580+ ModuleNameReference::AliasedModuleSelect(*module_location)
581581+ };
582582+ self.register_module_name_reference(module.clone(), reference);
583583+ }
584584+ ReferenceKind::Import | ReferenceKind::Definition => {}
387585 ReferenceKind::Alias | ReferenceKind::Unqualified => {
388586 self.register_type_reference_in_call_graph(referenced_name.clone())
389587 }
···393591 .entry((module, name))
394592 .or_default()
395593 .push(Reference { location, kind });
594594+ }
595595+596596+ /// Register a reference to a module in the code. This is separate to
597597+ /// `register_module_reference`, as references to modules can be created
598598+ /// implicitly, for example when using unqualified imports. This only register
599599+ /// explicit references in the source code, when the module name or local
600600+ /// alias is written.
601601+ pub fn register_module_name_reference(
602602+ &mut self,
603603+ module: EcoString,
604604+ reference: ModuleNameReference,
605605+ ) {
606606+ self.module_references
607607+ .entry(module)
608608+ .or_default()
609609+ .push(reference);
396610 }
397611398612 /// Like `register_type_reference`, but doesn't modify `self.type_references`.
···14551455 // We only register the reference here, if we know that this is a module access.
14561456 // Otherwise we would register module access even if we are actually accessing
14571457 // the field on a record
14581458+ let module_location =
14591459+ SrcSpan::new(location.start, location.start + module_alias.len() as u32);
14581460 self.environment.references.register_value_reference(
14591461 module_name.clone(),
14601462 label.clone(),
14611463 &label,
14621464 SrcSpan::new(field_start, location.end),
14631463- ReferenceKind::Qualified,
14651465+ ReferenceKind::Qualified {
14661466+ module_alias: module_alias.clone(),
14671467+ module_location,
14681468+ },
14641469 );
14651470 TypedExpr::ModuleSelect {
14661471 location,
···25772582 match self.infer_clause_guard_variable(name.clone(), location) {
25782583 // If the variable itself cannot be inferred as one, then
25792584 // it could really be a module select. We try that one
25802580- // as an elternative.
25852585+ // as an alternative.
25812586 Err(error) => self.infer_guard_module_access(
25822587 name,
25832588 label,
···25942599 }
25952600 } else {
25962601 // If it doesn't this has to be a regular record access and
25972597- // we try and inferr it as such.
26022602+ // we try and infer it as such.
25982603 let inferred_container = self.infer_clause_guard(*container.clone());
25992604 self.infer_guard_record_access(
26002605 inferred_container,
···28542859 label.clone(),
28552860 &label,
28562861 label_location,
28572857- ReferenceKind::Qualified,
28622862+ ReferenceKind::Qualified {
28632863+ module_alias: module_alias.clone(),
28642864+ module_location,
28652865+ },
28582866 );
2859286728602868 Ok(ClauseGuard::ModuleSelect {
···37173725 ReferenceRegistration::DoNotRegister => (),
3718372637193727 ReferenceRegistration::Register | ReferenceRegistration::VariableArgument { .. } => {
37203720- self.register_value_constructor_reference(
37213721- name,
37223722- &variant,
37233723- *location,
37243724- if module.is_some() {
37253725- ReferenceKind::Qualified
37263726- } else {
37273727- ReferenceKind::Unqualified
37283728- },
37293729- );
37283728+ let kind = if let Some((module_alias, module_location)) = module {
37293729+ ReferenceKind::Qualified {
37303730+ module_alias: module_alias.clone(),
37313731+ module_location: *module_location,
37323732+ }
37333733+ } else {
37343734+ ReferenceKind::Unqualified
37353735+ };
37363736+ self.register_value_constructor_reference(name, &variant, *location, kind);
37303737 }
37313738 }
37323739
···809809810810 executor(&mut engine, params, code.into())
811811 }
812812+813813+ /// Run a test in a project without a specific position (for workspace-wide
814814+ /// actions).
815815+ pub fn run<T>(
816816+ &self,
817817+ executor: impl FnOnce(
818818+ &mut LanguageServerEngine<LanguageServerTestIO, LanguageServerTestIO>,
819819+ ) -> T,
820820+ ) -> T {
821821+ // Use a throwaway position and ignore it
822822+ let (mut engine, _) = self.positioned_with_io(Position::default());
823823+824824+ executor(&mut engine)
825825+ }
812826}
813827814828#[derive(Clone)]
···11+---
22+source: language-server/src/tests/rename.rs
33+expression: "\nimport wibble\n\npub const one = wibble.Wibble\n\npub const two = wibble.wibble\n\npub fn main() -> wibble.Wibble {\n case wibble.Wobble {\n x if x == wibble.Wibble -> x\n x if x == wibble.wibble -> x\n wibble.Wobble -> wibble.wibble\n }\n}\n"
44+---
55+----- BEFORE RENAME
66+-- wibble.gleam
77+88+pub type Wibble {
99+ Wibble
1010+ Wobble
1111+}
1212+1313+pub const wibble = Wibble
1414+1515+1616+-- app.gleam
1717+1818+import wibble
1919+2020+pub const one = wibble.Wibble
2121+2222+pub const two = wibble.wibble
2323+2424+pub fn main() -> wibble.Wibble {
2525+ case wibble.Wobble {
2626+ x if x == wibble.Wibble -> x
2727+ x if x == wibble.wibble -> x
2828+ wibble.Wobble -> wibble.wibble
2929+ }
3030+}
3131+3232+3333+----- AFTER RENAME
3434+-- wobble.gleam
3535+3636+pub type Wibble {
3737+ Wibble
3838+ Wobble
3939+}
4040+4141+pub const wibble = Wibble
4242+4343+4444+-- app.gleam
4545+4646+import wobble
4747+4848+pub const one = wobble.Wibble
4949+5050+pub const two = wobble.wibble
5151+5252+pub fn main() -> wobble.Wibble {
5353+ case wobble.Wobble {
5454+ x if x == wobble.Wibble -> x
5555+ x if x == wobble.wibble -> x
5656+ wobble.Wobble -> wobble.wibble
5757+ }
5858+}