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

Configure Feed

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

gleam / language-server / src / reference.rs
36 kB 1055 lines
1use std::collections::{HashMap, HashSet}; 2 3use ecow::EcoString; 4use lsp_types::Location; 5 6use gleam_core::{ 7 analyse, 8 ast::{ 9 self, ArgNames, AssignName, BitArraySize, ClauseGuard, CustomType, Function, 10 ModuleConstant, Pattern, RecordConstructor, SrcSpan, TypeAstConstructorName, TypedExpr, 11 TypedModule, visit::Visit, 12 }, 13 build::Located, 14 type_::{ 15 ModuleInterface, ModuleValueConstructor, Type, ValueConstructor, ValueConstructorVariant, 16 error::{Named, VariableOrigin}, 17 }, 18}; 19 20use super::{ 21 compiler::ModuleSourceInformation, rename::RenameTarget, src_span_to_lsp_range, url_from_path, 22}; 23 24#[derive(Debug)] 25pub enum Referenced { 26 LocalVariable { 27 definition_location: SrcSpan, 28 location: SrcSpan, 29 origin: Option<VariableOrigin>, 30 name: EcoString, 31 }, 32 ModuleName { 33 module_name: EcoString, 34 module_alias: EcoString, 35 location: SrcSpan, 36 }, 37 ModuleValue { 38 module: EcoString, 39 name: EcoString, 40 location: SrcSpan, 41 name_kind: Named, 42 target_kind: RenameTarget, 43 }, 44 ModuleType { 45 module: EcoString, 46 name: EcoString, 47 location: SrcSpan, 48 target_kind: RenameTarget, 49 }, 50} 51 52pub fn reference_for_ast_node( 53 found: Located<'_>, 54 current_module: &EcoString, 55) -> Option<Referenced> { 56 match found { 57 Located::Expression { 58 expression: 59 TypedExpr::Var { 60 constructor: 61 ValueConstructor { 62 variant: 63 ValueConstructorVariant::LocalVariable { 64 location: definition_location, 65 origin, 66 }, 67 .. 68 }, 69 location, 70 name, 71 }, 72 .. 73 } => Some(Referenced::LocalVariable { 74 definition_location: *definition_location, 75 location: *location, 76 origin: Some(origin.clone()), 77 name: name.clone(), 78 }), 79 Located::Pattern(Pattern::Variable { 80 location, 81 origin, 82 name, 83 .. 84 }) => Some(Referenced::LocalVariable { 85 definition_location: *location, 86 location: *location, 87 origin: Some(origin.clone()), 88 name: name.clone(), 89 }), 90 Located::Pattern(Pattern::BitArraySize(BitArraySize::Variable { 91 constructor, 92 location, 93 name, 94 .. 95 })) => constructor 96 .as_ref() 97 .and_then(|constructor| match &constructor.variant { 98 ValueConstructorVariant::LocalVariable { 99 location: definition_location, 100 origin, 101 } => Some(Referenced::LocalVariable { 102 definition_location: *definition_location, 103 location: *location, 104 origin: Some(origin.clone()), 105 name: name.clone(), 106 }), 107 ValueConstructorVariant::ModuleConstant { .. } 108 | ValueConstructorVariant::ModuleFn { .. } 109 | ValueConstructorVariant::Record { .. } => None, 110 }), 111 Located::Pattern(Pattern::Assign { location, name, .. }) => { 112 Some(Referenced::LocalVariable { 113 definition_location: *location, 114 location: *location, 115 origin: None, 116 name: name.clone(), 117 }) 118 } 119 Located::Arg(arg) => match &arg.names { 120 ArgNames::Named { location, name } 121 | ArgNames::NamedLabelled { 122 name_location: location, 123 name, 124 .. 125 } => Some(Referenced::LocalVariable { 126 definition_location: *location, 127 location: *location, 128 origin: None, 129 name: name.clone(), 130 }), 131 ArgNames::Discard { .. } | ArgNames::LabelledDiscard { .. } => None, 132 }, 133 Located::Expression { 134 expression: 135 TypedExpr::Var { 136 constructor: 137 ValueConstructor { 138 variant: 139 ValueConstructorVariant::ModuleConstant { module, name, .. } 140 | ValueConstructorVariant::ModuleFn { module, name, .. }, 141 .. 142 }, 143 location, 144 .. 145 }, 146 .. 147 } => Some(Referenced::ModuleValue { 148 module: module.clone(), 149 name: name.clone(), 150 location: *location, 151 name_kind: Named::Function, 152 target_kind: RenameTarget::Unqualified, 153 }), 154 155 Located::Expression { 156 expression: 157 TypedExpr::ModuleSelect { 158 module_name, 159 label, 160 constructor: 161 ModuleValueConstructor::Fn { .. } | ModuleValueConstructor::Constant { .. }, 162 location, 163 field_start, 164 .. 165 }, 166 .. 167 } => Some(Referenced::ModuleValue { 168 module: module_name.clone(), 169 name: label.clone(), 170 location: SrcSpan::new(*field_start, location.end), 171 name_kind: Named::Function, 172 target_kind: RenameTarget::Qualified, 173 }), 174 175 Located::ModuleFunction(Function { 176 name: Some((location, name)), 177 .. 178 }) 179 | Located::ModuleConstant(ModuleConstant { 180 name, 181 name_location: location, 182 .. 183 }) => Some(Referenced::ModuleValue { 184 module: current_module.clone(), 185 name: name.clone(), 186 location: *location, 187 name_kind: Named::Function, 188 target_kind: RenameTarget::Definition, 189 }), 190 Located::Expression { 191 expression: 192 TypedExpr::Var { 193 constructor: 194 ValueConstructor { 195 variant: ValueConstructorVariant::Record { module, name, .. }, 196 .. 197 }, 198 location, 199 .. 200 }, 201 .. 202 } => Some(Referenced::ModuleValue { 203 module: module.clone(), 204 name: name.clone(), 205 location: *location, 206 name_kind: Named::CustomTypeVariant, 207 target_kind: RenameTarget::Unqualified, 208 }), 209 Located::Expression { 210 expression: 211 TypedExpr::ModuleSelect { 212 module_name, 213 label, 214 constructor: ModuleValueConstructor::Record { .. }, 215 location, 216 field_start, 217 .. 218 }, 219 .. 220 } => Some(Referenced::ModuleValue { 221 module: module_name.clone(), 222 name: label.clone(), 223 location: SrcSpan::new(*field_start, location.end), 224 name_kind: Named::CustomTypeVariant, 225 target_kind: RenameTarget::Qualified, 226 }), 227 Located::VariantConstructorDefinition(RecordConstructor { 228 name, 229 name_location, 230 .. 231 }) => Some(Referenced::ModuleValue { 232 module: current_module.clone(), 233 name: name.clone(), 234 location: *name_location, 235 name_kind: Named::CustomTypeVariant, 236 target_kind: RenameTarget::Definition, 237 }), 238 Located::Pattern(Pattern::Constructor { 239 constructor: analyse::Inferred::Known(constructor), 240 module: module_select, 241 name_location: location, 242 .. 243 }) => Some(Referenced::ModuleValue { 244 module: constructor.module.clone(), 245 name: constructor.name.clone(), 246 location: *location, 247 name_kind: Named::CustomTypeVariant, 248 target_kind: if module_select.is_some() { 249 RenameTarget::Qualified 250 } else { 251 RenameTarget::Unqualified 252 }, 253 }), 254 Located::StringPrefixPatternVariable { location, name, .. } => { 255 Some(Referenced::LocalVariable { 256 definition_location: location, 257 location, 258 origin: None, 259 name: name.clone(), 260 }) 261 } 262 Located::Annotation { ast, type_ } => match type_.named_type_name() { 263 Some((module, name)) => { 264 let (target_kind, location) = match ast { 265 ast::TypeAst::Constructor(constructor) => { 266 let kind = if constructor.name.is_qualified() { 267 RenameTarget::Qualified 268 } else { 269 RenameTarget::Unqualified 270 }; 271 let name_location = constructor.name.name_location()?; 272 (kind, name_location) 273 } 274 ast::TypeAst::Fn(_) 275 | ast::TypeAst::Var(_) 276 | ast::TypeAst::Tuple(_) 277 | ast::TypeAst::Hole(_) => (RenameTarget::Unqualified, ast.location()), 278 }; 279 Some(Referenced::ModuleType { 280 module, 281 name, 282 location, 283 target_kind, 284 }) 285 } 286 None => None, 287 }, 288 Located::ModuleCustomType(CustomType { 289 name, 290 name_location, 291 .. 292 }) => Some(Referenced::ModuleType { 293 module: current_module.clone(), 294 name: name.clone(), 295 location: *name_location, 296 target_kind: RenameTarget::Definition, 297 }), 298 Located::ModuleName { 299 location, 300 module_name, 301 module_alias, 302 .. 303 } => Some(Referenced::ModuleName { 304 module_name, 305 module_alias, 306 location, 307 }), 308 Located::ModuleImport(import) => { 309 let module_name = match &import.as_name { 310 Some(( 311 AssignName::Variable(module_alias) | AssignName::Discard(module_alias), 312 alias_location, 313 )) => Referenced::ModuleName { 314 module_name: import.module.clone(), 315 module_alias: module_alias.clone(), 316 location: SrcSpan { 317 start: alias_location.end - (module_alias.len() as u32), 318 end: alias_location.end, 319 }, 320 }, 321 None => Referenced::ModuleName { 322 module_name: import.module.clone(), 323 module_alias: import 324 .module 325 .split('/') 326 .next_back() 327 .map(EcoString::from) 328 .unwrap_or_else(|| import.module.clone()), 329 location: import.module_location, 330 }, 331 }; 332 333 Some(module_name) 334 } 335 336 Located::ClauseGuard(ClauseGuard::Var { 337 location, 338 type_: _, 339 name, 340 definition_location, 341 origin, 342 }) => Some(Referenced::LocalVariable { 343 definition_location: *definition_location, 344 location: *location, 345 origin: Some(origin.clone()), 346 name: name.clone(), 347 }), 348 349 Located::ClauseGuard(ClauseGuard::ModuleSelect { 350 location, 351 field_start, 352 label, 353 module_name, 354 .. 355 }) => Some(Referenced::ModuleValue { 356 module: module_name.clone(), 357 name: label.clone(), 358 location: SrcSpan::new(*field_start, location.end), 359 name_kind: Named::Function, 360 target_kind: RenameTarget::Qualified, 361 }), 362 363 Located::Pattern(_) 364 | Located::ClauseGuard(_) 365 | Located::PatternSpread { .. } 366 | Located::Statement(_) 367 | Located::Expression { .. } 368 | Located::FunctionBody(_) 369 | Located::UnqualifiedImport(_) 370 | Located::Label(..) 371 | Located::Constant(_) 372 | Located::ModuleFunction(_) 373 | Located::ModuleTypeAlias(_) => None, 374 } 375} 376 377pub fn find_module_references( 378 module_name: EcoString, 379 name: EcoString, 380 modules: &im::HashMap<EcoString, ModuleInterface>, 381 sources: &HashMap<EcoString, ModuleSourceInformation>, 382 layer: ast::Layer, 383) -> Vec<Location> { 384 let mut reference_locations = Vec::new(); 385 386 for module in modules.values() { 387 if module.name == module_name || module.references.imported_modules.contains(&module_name) { 388 let Some(source_information) = sources.get(&module.name) else { 389 continue; 390 }; 391 392 find_references_in_module( 393 &module_name, 394 &name, 395 module, 396 source_information, 397 &mut reference_locations, 398 layer, 399 ); 400 } 401 } 402 403 reference_locations 404} 405 406fn find_references_in_module( 407 module_name: &EcoString, 408 name: &EcoString, 409 module: &ModuleInterface, 410 source_information: &ModuleSourceInformation, 411 reference_locations: &mut Vec<Location>, 412 layer: ast::Layer, 413) { 414 let reference_map = match layer { 415 ast::Layer::Value => &module.references.value_references, 416 ast::Layer::Type => &module.references.type_references, 417 }; 418 419 let Some(references) = reference_map.get(&(module_name.clone(), name.clone())) else { 420 return; 421 }; 422 423 let Some(uri) = url_from_path(source_information.path.as_str()) else { 424 return; 425 }; 426 427 for reference in references { 428 reference_locations.push(Location { 429 uri: uri.clone(), 430 range: src_span_to_lsp_range(reference.location, &source_information.line_numbers), 431 }); 432 } 433} 434 435#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 436pub struct VariableReference { 437 pub location: SrcSpan, 438 pub kind: VariableReferenceKind, 439} 440 441#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 442pub enum VariableReferenceKind { 443 Variable, 444 LabelShorthand, 445} 446 447/// How to treat variables defined in alternative patterns 448enum AlternativeVariable { 449 Track, 450 Ignore, 451} 452 453pub struct FindVariableReferences { 454 // Due to the structure of some AST nodes (for example, record updates), 455 // when we traverse the AST it is possible to accidentally duplicate references. 456 // To avoid this, we use a `HashSet` instead of a `Vec` here. 457 // See: https://github.com/gleam-lang/gleam/issues/4859 and the linked PR. 458 references: HashSet<VariableReference>, 459 definition_location: DefinitionLocation, 460 alternative_variable: AlternativeVariable, 461 name: EcoString, 462} 463 464/// Where the variable we're finding references for is defined. 465/// 466enum DefinitionLocation { 467 /// This is the location where the variable is defined, nothing special is 468 /// going on here. For example: 469 /// 470 /// ```gleam 471 /// let wibble = 1 472 /// // ^^^^^^ Definition location for `wibble` 473 /// wibble + 1 474 /// ^^^^^^ 475 /// // `wibble` used here, defined earlier 476 /// ``` 477 /// 478 Regular { location: SrcSpan }, 479 480 /// When dealing with alternative patterns and aliases we need special care: 481 /// each usage wil always reference the first alternative where a variable 482 /// is defined and not the following ones. For example: 483 /// 484 /// ```gleam 485 /// case wibble { 486 /// [] as var | [_] as var -> var 487 /// // ^^^ ^^^ If we look where `var` thinks it's defined 488 /// // It will say it's defined here! 489 /// } 490 /// ``` 491 /// 492 /// This poses a problem if we start the renaming from the second 493 /// alternative pattern: 494 /// 495 /// ```gleam 496 /// case wibble { 497 /// [] as var | [_] as var -> var 498 /// // ^^^ Since `var` uses the first alternative as its 499 /// // definition location, this would not be considered 500 /// // a reference to that same var. 501 /// } 502 /// ``` 503 /// 504 /// So we keep track of the location of this definition, but we also need 505 /// to store the location of the first definition in the alternative case 506 /// (that's `first_alternative_location`), so that when we look for 507 /// references we can check against this one that is canonically used by 508 /// expressions in the AST 509 /// 510 Alternative { 511 location: SrcSpan, 512 first_alternative_location: SrcSpan, 513 }, 514} 515 516impl FindVariableReferences { 517 pub fn new(variable_definition_location: SrcSpan, variable_name: EcoString) -> Self { 518 Self { 519 references: HashSet::new(), 520 definition_location: DefinitionLocation::Regular { 521 location: variable_definition_location, 522 }, 523 alternative_variable: AlternativeVariable::Ignore, 524 name: variable_name, 525 } 526 } 527 528 /// Where the definition for which we're accumulating references is 529 /// originally defined. In case of alternative patterns this will point to 530 /// the first occurrence of that name! Look at the docs for 531 /// `DefinitionLocation` to learn more on why this is needed. 532 /// 533 fn definition_origin_location(&self) -> SrcSpan { 534 match self.definition_location { 535 DefinitionLocation::Regular { location } 536 | DefinitionLocation::Alternative { 537 first_alternative_location: location, 538 .. 539 } => location, 540 } 541 } 542 543 /// This is the location of the definition for which we're accumulating 544 /// references. In most cases you'll want to use `definition_origin_location`. 545 /// The difference between the two is explained in greater detail in the docs 546 /// for `DefinitionLocation`. 547 /// 548 fn definition_location(&self) -> SrcSpan { 549 match self.definition_location { 550 DefinitionLocation::Regular { location } 551 | DefinitionLocation::Alternative { location, .. } => location, 552 } 553 } 554 555 fn update_alternative_origin(&mut self, alternative_location: SrcSpan) { 556 match self.definition_location { 557 // We've found the location of the origin of an alternative pattern. 558 DefinitionLocation::Regular { location } if alternative_location < location => { 559 self.definition_location = DefinitionLocation::Alternative { 560 location, 561 first_alternative_location: alternative_location, 562 }; 563 } 564 565 // Since the new alternative location we've found is smaller, that 566 // is the actual first one for the alternative pattern! 567 DefinitionLocation::Alternative { 568 location, 569 first_alternative_location, 570 } if alternative_location < first_alternative_location => { 571 self.definition_location = DefinitionLocation::Alternative { 572 location, 573 first_alternative_location: alternative_location, 574 }; 575 } 576 577 DefinitionLocation::Regular { .. } | DefinitionLocation::Alternative { .. } => (), 578 }; 579 } 580 581 pub fn find_in_module(mut self, module: &TypedModule) -> HashSet<VariableReference> { 582 self.visit_typed_module(module); 583 self.references 584 } 585 586 pub fn find(mut self, expression: &TypedExpr) -> HashSet<VariableReference> { 587 self.visit_typed_expr(expression); 588 self.references 589 } 590 591 fn register_alternative_definition(&mut self, name: &EcoString, location: &SrcSpan) { 592 match self.alternative_variable { 593 // If we are inside the same alternative pattern as the target 594 // variable and the name is the same, this is an alternative definition 595 // of the same variable. We don't register the reference if this is 596 // the exact variable though, as that would result in a duplicated 597 // reference. 598 AlternativeVariable::Track 599 if *name == self.name && *location != self.definition_location() => 600 { 601 self.update_alternative_origin(*location); 602 603 _ = self.references.insert(VariableReference { 604 location: *location, 605 kind: VariableReferenceKind::Variable, 606 }); 607 } 608 AlternativeVariable::Track | AlternativeVariable::Ignore => {} 609 } 610 } 611} 612 613impl<'ast> Visit<'ast> for FindVariableReferences { 614 fn visit_typed_function(&mut self, fun: &'ast ast::TypedFunction) { 615 if fun 616 .full_location() 617 .contains(self.definition_origin_location().start) 618 { 619 ast::visit::visit_typed_function(self, fun); 620 } 621 } 622 623 fn visit_typed_expr_var( 624 &mut self, 625 location: &'ast SrcSpan, 626 constructor: &'ast ValueConstructor, 627 _name: &'ast EcoString, 628 ) { 629 match constructor.variant { 630 ValueConstructorVariant::LocalVariable { 631 location: definition_location, 632 .. 633 } if definition_location == self.definition_origin_location() => { 634 _ = self.references.insert(VariableReference { 635 location: *location, 636 kind: VariableReferenceKind::Variable, 637 }); 638 } 639 ValueConstructorVariant::LocalVariable { .. } 640 | ValueConstructorVariant::ModuleConstant { .. } 641 | ValueConstructorVariant::ModuleFn { .. } 642 | ValueConstructorVariant::Record { .. } => {} 643 } 644 } 645 646 fn visit_typed_clause_guard_var( 647 &mut self, 648 location: &'ast SrcSpan, 649 _name: &'ast EcoString, 650 _type_: &'ast std::sync::Arc<Type>, 651 definition_location: &'ast SrcSpan, 652 _origin: &'ast VariableOrigin, 653 ) { 654 if *definition_location == self.definition_origin_location() { 655 _ = self.references.insert(VariableReference { 656 location: *location, 657 kind: VariableReferenceKind::Variable, 658 }); 659 } 660 } 661 662 fn visit_typed_clause(&mut self, clause: &'ast ast::TypedClause) { 663 // If this alternative pattern contains the variable we are finding 664 // references for, we track that so we can find alternative definitions 665 // of the target variable. 666 if clause 667 .pattern_location() 668 .contains(self.definition_origin_location().start) 669 { 670 self.alternative_variable = AlternativeVariable::Track; 671 } 672 673 for pattern in clause.pattern.iter() { 674 self.visit_typed_pattern(pattern); 675 } 676 for patterns in clause.alternative_patterns.iter() { 677 for pattern in patterns { 678 self.visit_typed_pattern(pattern); 679 } 680 } 681 682 self.alternative_variable = AlternativeVariable::Ignore; 683 684 if let Some(guard) = &clause.guard { 685 self.visit_typed_clause_guard(guard); 686 } 687 self.visit_typed_expr(&clause.then); 688 } 689 690 fn visit_typed_pattern_variable( 691 &mut self, 692 location: &'ast SrcSpan, 693 name: &'ast EcoString, 694 _type_: &'ast std::sync::Arc<Type>, 695 _origin: &'ast VariableOrigin, 696 ) { 697 self.register_alternative_definition(name, location); 698 } 699 700 fn visit_typed_pattern_assign( 701 &mut self, 702 location: &'ast SrcSpan, 703 name: &'ast EcoString, 704 pattern: &'ast ast::TypedPattern, 705 ) { 706 self.register_alternative_definition(name, location); 707 708 ast::visit::visit_typed_pattern_assign(self, location, name, pattern); 709 } 710 711 fn visit_typed_bit_array_size_variable( 712 &mut self, 713 location: &'ast SrcSpan, 714 _name: &'ast EcoString, 715 constructor: &'ast Option<Box<ValueConstructor>>, 716 _type_: &'ast std::sync::Arc<Type>, 717 ) { 718 let variant = match constructor { 719 Some(constructor) => &constructor.variant, 720 None => return, 721 }; 722 match variant { 723 ValueConstructorVariant::LocalVariable { 724 location: definition_location, 725 .. 726 } if *definition_location == self.definition_origin_location() => { 727 _ = self.references.insert(VariableReference { 728 location: *location, 729 kind: VariableReferenceKind::Variable, 730 }); 731 } 732 ValueConstructorVariant::LocalVariable { .. } 733 | ValueConstructorVariant::ModuleConstant { .. } 734 | ValueConstructorVariant::ModuleFn { .. } 735 | ValueConstructorVariant::Record { .. } => {} 736 } 737 } 738 739 fn visit_typed_call_arg(&mut self, arg: &'ast gleam_core::type_::TypedCallArg) { 740 if let TypedExpr::Var { 741 location, 742 constructor, 743 .. 744 } = &arg.value 745 { 746 match &constructor.variant { 747 ValueConstructorVariant::LocalVariable { 748 location: definition_location, 749 .. 750 } if arg.uses_label_shorthand() 751 && *definition_location == self.definition_origin_location() => 752 { 753 _ = self.references.insert(VariableReference { 754 location: *location, 755 kind: VariableReferenceKind::LabelShorthand, 756 }); 757 return; 758 } 759 ValueConstructorVariant::LocalVariable { .. } 760 | ValueConstructorVariant::ModuleConstant { .. } 761 | ValueConstructorVariant::ModuleFn { .. } 762 | ValueConstructorVariant::Record { .. } => {} 763 } 764 } 765 766 ast::visit::visit_typed_call_arg(self, arg); 767 } 768 769 fn visit_typed_pattern_string_prefix( 770 &mut self, 771 location: &'ast SrcSpan, 772 left_location: &'ast SrcSpan, 773 left_side_assignment: &'ast Option<(EcoString, SrcSpan)>, 774 right_location: &'ast SrcSpan, 775 left_side_string: &'ast EcoString, 776 right_side_assignment: &'ast AssignName, 777 ) { 778 // Handle the prefix alias in alternative pattern: "prefix" as name | "other_prefix" as name 779 if let Some((name, left_side_assignment_location)) = left_side_assignment { 780 self.register_alternative_definition(name, left_side_assignment_location); 781 } 782 783 // Handle the suffix in alternative pattern: "prefix" <> name | "other_prefix" <> name 784 match right_side_assignment { 785 AssignName::Variable(name) => { 786 self.register_alternative_definition(name, right_location) 787 } 788 AssignName::Discard(_) => {} 789 } 790 791 ast::visit::visit_typed_pattern_string_prefix( 792 self, 793 location, 794 left_location, 795 left_side_assignment, 796 right_location, 797 left_side_string, 798 right_side_assignment, 799 ); 800 } 801} 802 803pub struct ModuleNameReference { 804 pub location: SrcSpan, 805 pub kind: ModuleNameReferenceKind, 806} 807 808pub enum ModuleNameReferenceKind { 809 Import, 810 AliasedImport, 811 ModuleSelect, 812} 813 814pub struct FindModuleNameReferences<'a> { 815 pub references: Vec<ModuleNameReference>, 816 pub module_name: &'a EcoString, 817 pub module_alias: &'a EcoString, 818} 819 820impl<'ast> Visit<'ast> for FindModuleNameReferences<'_> { 821 fn visit_typed_module(&mut self, module: &'ast TypedModule) { 822 ast::visit::visit_typed_module(self, module); 823 } 824 825 fn visit_typed_clause_guard(&mut self, guard: &'ast ast::TypedClauseGuard) { 826 ast::visit::visit_typed_clause_guard(self, guard); 827 } 828 829 fn visit_typed_import(&mut self, import: &'ast ast::TypedImport) { 830 match import.as_name.as_ref() { 831 None => { 832 if import.module == *self.module_name { 833 self.references.push(ModuleNameReference { 834 location: import.location, 835 kind: ModuleNameReferenceKind::Import, 836 }) 837 } 838 } 839 Some((AssignName::Variable(alias) | AssignName::Discard(alias), alias_location)) => { 840 if alias == self.module_alias { 841 self.references.push(ModuleNameReference { 842 location: *alias_location, 843 kind: ModuleNameReferenceKind::AliasedImport, 844 }) 845 } 846 } 847 } 848 849 ast::visit::visit_typed_import(self, import); 850 } 851 852 fn visit_typed_clause_guard_module_select( 853 &mut self, 854 location: &'ast SrcSpan, 855 field_start: &'ast u32, 856 definition_location: &'ast SrcSpan, 857 type_: &'ast std::sync::Arc<Type>, 858 label: &'ast EcoString, 859 module_name: &'ast EcoString, 860 module_alias: &'ast EcoString, 861 literal: &'ast ast::TypedConstant, 862 ) { 863 if module_alias == self.module_alias { 864 self.references.push(ModuleNameReference { 865 location: SrcSpan::new( 866 location.start, 867 location.start + (module_alias.len() as u32), 868 ), 869 kind: ModuleNameReferenceKind::ModuleSelect, 870 }); 871 } 872 873 ast::visit::visit_typed_clause_guard_module_select( 874 self, 875 location, 876 field_start, 877 definition_location, 878 type_, 879 label, 880 module_name, 881 module_alias, 882 literal, 883 ); 884 } 885 886 fn visit_typed_expr_module_select( 887 &mut self, 888 location: &'ast SrcSpan, 889 field_start: &'ast u32, 890 type_: &'ast std::sync::Arc<Type>, 891 label: &'ast EcoString, 892 module_name: &'ast EcoString, 893 module_alias: &'ast EcoString, 894 constructor: &'ast ModuleValueConstructor, 895 ) { 896 if module_alias == self.module_alias { 897 self.references.push(ModuleNameReference { 898 location: SrcSpan::new( 899 location.start, 900 location.start + (module_alias.len() as u32), 901 ), 902 kind: ModuleNameReferenceKind::ModuleSelect, 903 }); 904 } 905 906 ast::visit::visit_typed_expr_module_select( 907 self, 908 location, 909 field_start, 910 type_, 911 label, 912 module_name, 913 module_alias, 914 constructor, 915 ); 916 } 917 918 fn visit_type_ast_constructor( 919 &mut self, 920 location: &'ast SrcSpan, 921 name: &'ast TypeAstConstructorName, 922 arguments: &'ast [ast::TypeAst], 923 arguments_types: Option<Vec<std::sync::Arc<Type>>>, 924 ) { 925 if let TypeAstConstructorName::Qualified { 926 module: module_alias, 927 module_location, 928 .. 929 } = name 930 && module_alias == self.module_alias 931 { 932 self.references.push(ModuleNameReference { 933 location: *module_location, 934 kind: ModuleNameReferenceKind::ModuleSelect, 935 }) 936 } 937 938 ast::visit::visit_type_ast_constructor(self, location, name, arguments, arguments_types); 939 } 940 941 fn visit_typed_constant_record( 942 &mut self, 943 location: &'ast SrcSpan, 944 module: &'ast Option<(EcoString, SrcSpan)>, 945 name: &'ast EcoString, 946 arguments: &'ast Vec<ast::CallArg<ast::TypedConstant>>, 947 type_: &'ast std::sync::Arc<Type>, 948 field_map: &'ast analyse::Inferred<gleam_core::type_::FieldMap>, 949 record_constructor: &'ast Option<Box<ValueConstructor>>, 950 ) { 951 if let Some((module_alias, module_location)) = module 952 && module_alias == self.module_alias 953 { 954 self.references.push(ModuleNameReference { 955 location: *module_location, 956 kind: ModuleNameReferenceKind::ModuleSelect, 957 }) 958 } 959 960 ast::visit::visit_typed_constant_record( 961 self, 962 location, 963 module, 964 name, 965 arguments, 966 type_, 967 field_map, 968 record_constructor, 969 ); 970 } 971 972 fn visit_typed_constant_record_update( 973 &mut self, 974 location: &'ast SrcSpan, 975 constructor_location: &'ast SrcSpan, 976 module: &'ast Option<(EcoString, SrcSpan)>, 977 name: &'ast EcoString, 978 record: &'ast ast::RecordBeingUpdated<ast::TypedConstant>, 979 arguments: &'ast [ast::RecordUpdateArg<ast::TypedConstant>], 980 type_: &'ast std::sync::Arc<Type>, 981 field_map: &'ast analyse::Inferred<gleam_core::type_::FieldMap>, 982 ) { 983 if let Some((module_alias, module_location)) = module 984 && module_alias == self.module_alias 985 { 986 self.references.push(ModuleNameReference { 987 location: *module_location, 988 kind: ModuleNameReferenceKind::ModuleSelect, 989 }) 990 } 991 992 ast::visit::visit_typed_constant_record_update( 993 self, 994 location, 995 constructor_location, 996 module, 997 name, 998 record, 999 arguments, 1000 type_, 1001 field_map, 1002 ) 1003 } 1004 1005 fn visit_typed_constant_var( 1006 &mut self, 1007 _location: &'ast SrcSpan, 1008 module: &'ast Option<(EcoString, SrcSpan)>, 1009 _name: &'ast EcoString, 1010 _constructor: &'ast Option<Box<ValueConstructor>>, 1011 _type_: &'ast std::sync::Arc<Type>, 1012 ) { 1013 if let Some((module_alias, module_location)) = module 1014 && module_alias == self.module_alias 1015 { 1016 self.references.push(ModuleNameReference { 1017 location: *module_location, 1018 kind: ModuleNameReferenceKind::ModuleSelect, 1019 }) 1020 } 1021 } 1022 1023 fn visit_typed_pattern_constructor( 1024 &mut self, 1025 location: &'ast SrcSpan, 1026 name_location: &'ast SrcSpan, 1027 name: &'ast EcoString, 1028 arguments: &'ast Vec<ast::CallArg<ast::TypedPattern>>, 1029 module: &'ast Option<(EcoString, SrcSpan)>, 1030 constructor: &'ast analyse::Inferred<gleam_core::type_::PatternConstructor>, 1031 spread: &'ast Option<SrcSpan>, 1032 type_: &'ast std::sync::Arc<Type>, 1033 ) { 1034 if let Some((module_alias, module_location)) = module 1035 && module_alias == self.module_alias 1036 { 1037 self.references.push(ModuleNameReference { 1038 location: *module_location, 1039 kind: ModuleNameReferenceKind::ModuleSelect, 1040 }); 1041 } 1042 1043 ast::visit::visit_typed_pattern_constructor( 1044 self, 1045 location, 1046 name_location, 1047 name, 1048 arguments, 1049 module, 1050 constructor, 1051 spread, 1052 type_, 1053 ); 1054 } 1055}