From 058daff7c5ff12d3125b3bbd844c0c814389703c Mon Sep 17 00:00:00 2001 From: GearsDatapacks Date: Mon, 24 Feb 2025 13:40:29 +0000 Subject: [PATCH 01/27] Find in-module references to constants and functions --- compiler-core/src/analyse.rs | 7 +-- compiler-core/src/ast.rs | 2 + compiler-core/src/call_graph.rs | 50 +++++++++++++------ .../call_graph/into_dependency_order_tests.rs | 3 +- compiler-core/src/parse.rs | 1 + ...re__parse__tests__const_string_concat.snap | 1 + ...deprecation_attribute_on_type_variant.snap | 1 + ...gleam_core__parse__tests__import_type.snap | 1 + ..._parse__tests__record_access_no_label.snap | 1 + compiler-core/src/type_/tests.rs | 1 + 10 files changed, 49 insertions(+), 19 deletions(-) diff --git a/compiler-core/src/analyse.rs b/compiler-core/src/analyse.rs index a064018ef17..8bee6710c05 100644 --- a/compiler-core/src/analyse.rs +++ b/compiler-core/src/analyse.rs @@ -15,7 +15,7 @@ use crate::{ UntypedModule, UntypedModuleConstant, UntypedStatement, UntypedTypeAlias, }, build::{Origin, Outcome, Target}, - call_graph::{CallGraphNode, into_dependency_order}, + call_graph::{CallGraphNode, call_graph_info}, config::PackageConfig, dep_tree, line_numbers::LineNumbers, @@ -254,8 +254,8 @@ impl<'a, A> ModuleAnalyzer<'a, A> { // Sort functions and constants into dependency order for inference. Definitions that do // not depend on other definitions are inferred first, then ones that depend // on those, etc. - let definition_groups = - match into_dependency_order(statements.functions, statements.constants) { + let (definition_groups, references) = + match call_graph_info(statements.functions, statements.constants) { Ok(it) => it, Err(error) => return self.all_errors(error), }; @@ -342,6 +342,7 @@ impl<'a, A> ModuleAnalyzer<'a, A> { contains_echo: echo_found, }, names: type_names, + references, }; match Vec1::try_from_vec(self.problems.take_errors()) { diff --git a/compiler-core/src/ast.rs b/compiler-core/src/ast.rs index 56b0bf09cd6..8a02329c0d2 100644 --- a/compiler-core/src/ast.rs +++ b/compiler-core/src/ast.rs @@ -20,6 +20,7 @@ use crate::type_::printer::Names; use crate::type_::{ self, Deprecation, ModuleValueConstructor, PatternConstructor, Type, ValueConstructor, }; +use std::collections::HashMap; use std::sync::Arc; use ecow::EcoString; @@ -50,6 +51,7 @@ pub struct Module { pub type_info: Info, pub definitions: Vec, pub names: Names, + pub references: HashMap>, } impl TypedModule { diff --git a/compiler-core/src/call_graph.rs b/compiler-core/src/call_graph.rs index 22e2f8037fc..2dcdbbe6a3d 100644 --- a/compiler-core/src/call_graph.rs +++ b/compiler-core/src/call_graph.rs @@ -4,6 +4,8 @@ #[cfg(test)] mod into_dependency_order_tests; +use std::collections::HashMap; + use crate::{ Result, ast::{ @@ -13,6 +15,7 @@ use crate::{ }, type_::Error, }; +use ecow::EcoString; use itertools::Itertools; use petgraph::stable_graph::NodeIndex; use petgraph::{Directed, stable_graph::StableGraph}; @@ -22,6 +25,7 @@ struct CallGraphBuilder<'a> { names: im::HashMap<&'a str, Option<(NodeIndex, SrcSpan)>>, graph: StableGraph<(), (), Directed>, current_function: NodeIndex, + references: HashMap>, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -32,8 +36,13 @@ pub enum CallGraphNode { } impl<'a> CallGraphBuilder<'a> { - fn into_graph(self) -> StableGraph<(), (), Directed> { - self.graph + fn into_info( + self, + ) -> ( + StableGraph<(), (), Directed>, + HashMap>, + ) { + (self.graph, self.references) } /// Add each function to the graph, storing the index of the node under the @@ -119,7 +128,7 @@ impl<'a> CallGraphBuilder<'a> { self.names = names; } - fn referenced(&mut self, name: &str) { + fn referenced(&mut self, name: &str, location: SrcSpan) { // If we don't know what the target is then it's either a programmer // error to be detected later, or it's not a module function and as such // is not a value we are tracking. @@ -132,6 +141,10 @@ impl<'a> CallGraphBuilder<'a> { let Some((target, _)) = target else { return }; _ = self.graph.add_edge(self.current_function, *target, ()); + self.references + .entry(name.into()) + .or_default() + .push(location); } fn statements(&mut self, statements: &'a [UntypedStatement]) { @@ -189,8 +202,8 @@ impl<'a> CallGraphBuilder<'a> { } // Aha! A variable is being referenced. - UntypedExpr::Var { name, .. } => { - self.referenced(name); + UntypedExpr::Var { name, location, .. } => { + self.referenced(name, *location); } UntypedExpr::Call { fun, arguments, .. } => { @@ -339,8 +352,8 @@ impl<'a> CallGraphBuilder<'a> { } } - Pattern::VarUsage { name, .. } => { - self.referenced(name); + Pattern::VarUsage { name, location, .. } => { + self.referenced(name, *location); } Pattern::Assign { name, pattern, .. } => { @@ -427,13 +440,17 @@ impl<'a> CallGraphBuilder<'a> { ClauseGuard::Not { expression, .. } => self.guard(expression), - ClauseGuard::Var { name, .. } => self.referenced(name), + ClauseGuard::Var { name, location, .. } => self.referenced(name, *location), ClauseGuard::TupleIndex { tuple, .. } => self.guard(tuple), ClauseGuard::FieldAccess { container, .. } => self.guard(container), - ClauseGuard::ModuleSelect { module_name, .. } => self.referenced(module_name), + ClauseGuard::ModuleSelect { + module_name, + location, + .. + } => self.referenced(module_name, *location), ClauseGuard::Constant(constant) => self.constant(constant), } @@ -462,8 +479,11 @@ impl<'a> CallGraphBuilder<'a> { } Constant::Var { - module: None, name, .. - } => self.referenced(name), + module: None, + name, + location, + .. + } => self.referenced(name, *location), Constant::BitArray { segments, .. } => { for segment in segments { @@ -485,10 +505,10 @@ impl<'a> CallGraphBuilder<'a> { /// Determine the order in which functions and constants should be compiled and if any /// mutually recursive functions need to be compiled together. /// -pub fn into_dependency_order( +pub fn call_graph_info( functions: Vec, constants: Vec, -) -> Result>, Error> { +) -> Result<(Vec>, HashMap>), Error> { let mut grapher = CallGraphBuilder::default(); for function in &functions { @@ -509,7 +529,7 @@ pub fn into_dependency_order( } // Consume the grapher to get the graph - let graph = grapher.into_graph(); + let (graph, references) = grapher.into_info(); // Determine the order in which the functions should be compiled by looking // at which other functions they depend on. @@ -541,5 +561,5 @@ pub fn into_dependency_order( }) .collect_vec(); - Ok(ordered) + Ok((ordered, references)) } diff --git a/compiler-core/src/call_graph/into_dependency_order_tests.rs b/compiler-core/src/call_graph/into_dependency_order_tests.rs index e3f6bb48306..87fb5dd6751 100644 --- a/compiler-core/src/call_graph/into_dependency_order_tests.rs +++ b/compiler-core/src/call_graph/into_dependency_order_tests.rs @@ -72,7 +72,8 @@ fn parse_and_order( }) .collect_vec(); - Ok(into_dependency_order(functions, constants)? + Ok(call_graph_info(functions, constants)? + .0 .into_iter() .map(|level| { level diff --git a/compiler-core/src/parse.rs b/compiler-core/src/parse.rs index 455cb24fb4e..78a0be3748a 100644 --- a/compiler-core/src/parse.rs +++ b/compiler-core/src/parse.rs @@ -243,6 +243,7 @@ where type_info: (), definitions, names: Default::default(), + references: Default::default(), }; Ok(Parsed { module, diff --git a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__const_string_concat.snap b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__const_string_concat.snap index 6b7d2acca51..4adf196b592 100644 --- a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__const_string_concat.snap +++ b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__const_string_concat.snap @@ -101,6 +101,7 @@ Parsed { type_variables: {}, local_value_constructors: {}, }, + references: {}, }, extra: ModuleExtra { module_comments: [], diff --git a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__deprecation_attribute_on_type_variant.snap b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__deprecation_attribute_on_type_variant.snap index 46bf2af06c0..7e22b65d1fe 100644 --- a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__deprecation_attribute_on_type_variant.snap +++ b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__deprecation_attribute_on_type_variant.snap @@ -70,6 +70,7 @@ Parsed { type_variables: {}, local_value_constructors: {}, }, + references: {}, }, extra: ModuleExtra { module_comments: [], diff --git a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__import_type.snap b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__import_type.snap index 0cab85203f6..0fd832e7634 100644 --- a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__import_type.snap +++ b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__import_type.snap @@ -58,6 +58,7 @@ Parsed { type_variables: {}, local_value_constructors: {}, }, + references: {}, }, extra: ModuleExtra { module_comments: [], diff --git a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__record_access_no_label.snap b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__record_access_no_label.snap index ad0330040fa..1a349f7480b 100644 --- a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__record_access_no_label.snap +++ b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__record_access_no_label.snap @@ -164,6 +164,7 @@ Parsed { type_variables: {}, local_value_constructors: {}, }, + references: {}, }, extra: ModuleExtra { module_comments: [], diff --git a/compiler-core/src/type_/tests.rs b/compiler-core/src/type_/tests.rs index 33e9b0a5ead..dcd572ac894 100644 --- a/compiler-core/src/type_/tests.rs +++ b/compiler-core/src/type_/tests.rs @@ -786,6 +786,7 @@ fn infer_module_type_retention_test() { definitions: vec![], type_info: (), names: Default::default(), + references: Default::default(), }; let direct_dependencies = HashMap::from_iter(vec![]); let ids = UniqueIdGenerator::new(); From e43157be47bdb330d53b4d341cd2365b5437187e Mon Sep 17 00:00:00 2001 From: GearsDatapacks Date: Mon, 24 Feb 2025 14:11:23 +0000 Subject: [PATCH 02/27] Implement renaming for local constants and functions --- compiler-core/src/ast.rs | 3 +- compiler-core/src/call_graph.rs | 46 +++++++++++++++++---- compiler-core/src/language_server/engine.rs | 23 ++++++++++- compiler-core/src/language_server/rename.rs | 34 +++++++++++++++ 4 files changed, 96 insertions(+), 10 deletions(-) diff --git a/compiler-core/src/ast.rs b/compiler-core/src/ast.rs index 8a02329c0d2..7a389023f26 100644 --- a/compiler-core/src/ast.rs +++ b/compiler-core/src/ast.rs @@ -13,6 +13,7 @@ pub use self::constant::{Constant, TypedConstant, UntypedConstant}; use crate::analyse::Inferred; use crate::build::{Located, Target}; +use crate::call_graph::ReferenceInformation; use crate::parse::SpannedString; use crate::type_::error::VariableOrigin; use crate::type_::expression::Implementations; @@ -51,7 +52,7 @@ pub struct Module { pub type_info: Info, pub definitions: Vec, pub names: Names, - pub references: HashMap>, + pub references: HashMap, } impl TypedModule { diff --git a/compiler-core/src/call_graph.rs b/compiler-core/src/call_graph.rs index 2dcdbbe6a3d..b942be7dda7 100644 --- a/compiler-core/src/call_graph.rs +++ b/compiler-core/src/call_graph.rs @@ -25,7 +25,13 @@ struct CallGraphBuilder<'a> { names: im::HashMap<&'a str, Option<(NodeIndex, SrcSpan)>>, graph: StableGraph<(), (), Directed>, current_function: NodeIndex, - references: HashMap>, + references: HashMap, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ReferenceInformation { + pub definition_location: SrcSpan, + pub references: Vec, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -40,7 +46,7 @@ impl<'a> CallGraphBuilder<'a> { self, ) -> ( StableGraph<(), (), Directed>, - HashMap>, + HashMap, ) { (self.graph, self.references) } @@ -51,7 +57,7 @@ impl<'a> CallGraphBuilder<'a> { &mut self, function: &'a UntypedFunction, ) -> Result<(), Error> { - let (_, name) = function + let (name_location, name) = function .name .as_ref() .expect("A module's function must be named"); @@ -67,6 +73,15 @@ impl<'a> CallGraphBuilder<'a> { name: name.clone(), }); } + + _ = self.references.insert( + name.clone(), + ReferenceInformation { + definition_location: *name_location, + references: Vec::new(), + }, + ); + Ok(()) } @@ -89,6 +104,15 @@ impl<'a> CallGraphBuilder<'a> { name: name.clone(), }); } + + _ = self.references.insert( + name.clone(), + ReferenceInformation { + definition_location: constant.name_location, + references: Vec::new(), + }, + ); + Ok(()) } @@ -141,10 +165,10 @@ impl<'a> CallGraphBuilder<'a> { let Some((target, _)) = target else { return }; _ = self.graph.add_edge(self.current_function, *target, ()); - self.references - .entry(name.into()) - .or_default() - .push(location); + _ = self + .references + .get_mut(name) + .map(|information| information.references.push(location)); } fn statements(&mut self, statements: &'a [UntypedStatement]) { @@ -508,7 +532,13 @@ impl<'a> CallGraphBuilder<'a> { pub fn call_graph_info( functions: Vec, constants: Vec, -) -> Result<(Vec>, HashMap>), Error> { +) -> Result< + ( + Vec>, + HashMap, + ), + Error, +> { let mut grapher = CallGraphBuilder::default(); for function in &functions { diff --git a/compiler-core/src/language_server/engine.rs b/compiler-core/src/language_server/engine.rs index 277089ede64..2784f05f3fb 100644 --- a/compiler-core/src/language_server/engine.rs +++ b/compiler-core/src/language_server/engine.rs @@ -42,7 +42,7 @@ use super::{ code_action_inexhaustive_let_to_case, }, completer::Completer, - rename::{VariableRenameKind, rename_local_variable}, + rename::{VariableRenameKind, rename_local_variable, rename_module_value}, signature_help, src_span_to_lsp_range, }; @@ -600,6 +600,16 @@ where } => success_response(*location), ArgNames::Discard { .. } | ArgNames::LabelledDiscard { .. } => None, }, + Located::Expression(TypedExpr::Var { + constructor: + ValueConstructor { + variant: + ValueConstructorVariant::ModuleConstant { location, .. } + | ValueConstructorVariant::ModuleFn { location, .. }, + .. + }, + .. + }) => success_response(*location), _ => None, }) }) @@ -694,6 +704,17 @@ where ), ArgNames::Discard { .. } | ArgNames::LabelledDiscard { .. } => None, }, + Located::Expression(TypedExpr::Var { + constructor: + ValueConstructor { + variant: + ValueConstructorVariant::ModuleConstant { .. } + | ValueConstructorVariant::ModuleFn { .. }, + .. + }, + name, + .. + }) => rename_module_value(module, &lines, ¶ms, name), _ => None, }) }) diff --git a/compiler-core/src/language_server/rename.rs b/compiler-core/src/language_server/rename.rs index 17f5d3537df..17ff4f79bce 100644 --- a/compiler-core/src/language_server/rename.rs +++ b/compiler-core/src/language_server/rename.rs @@ -65,6 +65,40 @@ pub fn rename_local_variable( Some(workspace_edit(uri, edits.edits)) } +pub fn rename_module_value( + module: &Module, + line_numbers: &LineNumbers, + params: &RenameParams, + name: &EcoString, +) -> Option { + if name::check_name_case( + Default::default(), + ¶ms.new_name.as_str().into(), + Named::Function, + ) + .is_err() + { + return None; + } + + let uri = params.text_document_position.text_document.uri.clone(); + let mut edits = TextEdits::new(line_numbers); + + let reference_information = module.ast.references.get(name)?; + + edits.replace( + reference_information.definition_location, + params.new_name.clone(), + ); + + reference_information + .references + .iter() + .for_each(|location| edits.replace(*location, params.new_name.clone())); + + Some(workspace_edit(uri, edits.edits)) +} + pub fn find_variable_references( module: &TypedModule, definition_location: SrcSpan, From c2edde6203ed9ce6c1a3bfe3806e4185be9282f1 Mon Sep 17 00:00:00 2001 From: GearsDatapacks Date: Mon, 24 Feb 2025 14:21:43 +0000 Subject: [PATCH 03/27] Fix rename location --- compiler-core/src/language_server/engine.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler-core/src/language_server/engine.rs b/compiler-core/src/language_server/engine.rs index 2784f05f3fb..9b2a8534575 100644 --- a/compiler-core/src/language_server/engine.rs +++ b/compiler-core/src/language_server/engine.rs @@ -604,10 +604,11 @@ where constructor: ValueConstructor { variant: - ValueConstructorVariant::ModuleConstant { location, .. } - | ValueConstructorVariant::ModuleFn { location, .. }, + ValueConstructorVariant::ModuleConstant { .. } + | ValueConstructorVariant::ModuleFn { .. }, .. }, + location, .. }) => success_response(*location), _ => None, From 9cabeefac0bfa8da5cd7a09226067ae9a678d3b8 Mon Sep 17 00:00:00 2001 From: GearsDatapacks Date: Tue, 25 Feb 2025 10:10:51 +0000 Subject: [PATCH 04/27] Implement cross-module renaming in language server --- compiler-core/src/analyse.rs | 17 ++++-- compiler-core/src/ast.rs | 10 +++- compiler-core/src/language_server/engine.rs | 2 +- compiler-core/src/language_server/rename.rs | 60 ++++++++++++++++++--- 4 files changed, 73 insertions(+), 16 deletions(-) diff --git a/compiler-core/src/analyse.rs b/compiler-core/src/analyse.rs index 8bee6710c05..44b019ee791 100644 --- a/compiler-core/src/analyse.rs +++ b/compiler-core/src/analyse.rs @@ -9,10 +9,10 @@ use crate::{ ast::{ self, Arg, BitArrayOption, CustomType, Definition, DefinitionLocation, Function, GroupedStatements, Import, ModuleConstant, Publicity, RecordConstructor, - RecordConstructorArg, SrcSpan, Statement, TypeAlias, TypeAst, TypeAstConstructor, - TypeAstFn, TypeAstHole, TypeAstTuple, TypeAstVar, TypedDefinition, TypedExpr, - TypedFunction, TypedModule, UntypedArg, UntypedCustomType, UntypedFunction, UntypedImport, - UntypedModule, UntypedModuleConstant, UntypedStatement, UntypedTypeAlias, + RecordConstructorArg, References, SrcSpan, Statement, TypeAlias, TypeAst, + TypeAstConstructor, TypeAstFn, TypeAstHole, TypeAstTuple, TypeAstVar, TypedDefinition, + TypedExpr, TypedFunction, TypedModule, UntypedArg, UntypedCustomType, UntypedFunction, + UntypedImport, UntypedModule, UntypedModuleConstant, UntypedStatement, UntypedTypeAlias, }, build::{Origin, Outcome, Target}, call_graph::{CallGraphNode, call_graph_info}, @@ -342,7 +342,14 @@ impl<'a, A> ModuleAnalyzer<'a, A> { contains_echo: echo_found, }, names: type_names, - references, + references: References { + imported_modules: env + .imported_modules + .into_iter() + .map(|(name, _)| name) + .collect(), + value_references: references, + }, }; match Vec1::try_from_vec(self.problems.take_errors()) { diff --git a/compiler-core/src/ast.rs b/compiler-core/src/ast.rs index 7a389023f26..6e27a8ada8f 100644 --- a/compiler-core/src/ast.rs +++ b/compiler-core/src/ast.rs @@ -21,7 +21,7 @@ use crate::type_::printer::Names; use crate::type_::{ self, Deprecation, ModuleValueConstructor, PatternConstructor, Type, ValueConstructor, }; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::sync::Arc; use ecow::EcoString; @@ -52,7 +52,7 @@ pub struct Module { pub type_info: Info, pub definitions: Vec, pub names: Names, - pub references: HashMap, + pub references: References, } impl TypedModule { @@ -69,6 +69,12 @@ impl TypedModule { } } +#[derive(Debug, Clone, PartialEq, Eq, Default)] +pub struct References { + pub imported_modules: HashSet, + pub value_references: HashMap, +} + /// The `@target(erlang)` and `@target(javascript)` attributes can be used to /// mark a definition as only being for a specific target. /// diff --git a/compiler-core/src/language_server/engine.rs b/compiler-core/src/language_server/engine.rs index 9b2a8534575..1830424620f 100644 --- a/compiler-core/src/language_server/engine.rs +++ b/compiler-core/src/language_server/engine.rs @@ -715,7 +715,7 @@ where }, name, .. - }) => rename_module_value(module, &lines, ¶ms, name), + }) => rename_module_value(module, &lines, ¶ms, name, &this.compiler.modules), _ => None, }) }) diff --git a/compiler-core/src/language_server/rename.rs b/compiler-core/src/language_server/rename.rs index 17ff4f79bce..b1a81e24698 100644 --- a/compiler-core/src/language_server/rename.rs +++ b/compiler-core/src/language_server/rename.rs @@ -66,10 +66,11 @@ pub fn rename_local_variable( } pub fn rename_module_value( - module: &Module, + main_module: &Module, line_numbers: &LineNumbers, params: &RenameParams, name: &EcoString, + modules: &HashMap, ) -> Option { if name::check_name_case( Default::default(), @@ -81,22 +82,65 @@ pub fn rename_module_value( return None; } - let uri = params.text_document_position.text_document.uri.clone(); let mut edits = TextEdits::new(line_numbers); + let mut workspace_edit = WorkspaceEdit { + changes: Some(HashMap::new()), + document_changes: None, + change_annotations: None, + }; - let reference_information = module.ast.references.get(name)?; - - edits.replace( - reference_information.definition_location, + rename_references_in_module( + main_module, + &mut edits, + &mut workspace_edit, + name, params.new_name.clone(), ); + for (_, module) in modules { + if module + .ast + .references + .imported_modules + .contains(&main_module.name) + { + rename_references_in_module( + module, + &mut edits, + &mut workspace_edit, + name, + params.new_name.clone(), + ); + } + } + + Some(workspace_edit) +} + +fn rename_references_in_module( + module: &Module, + edits: &mut TextEdits<'_>, + workspace_edit: &mut WorkspaceEdit, + name: &EcoString, + new_name: String, +) { + let Some(reference_information) = module.ast.references.value_references.get(name) else { + return; + }; reference_information .references .iter() - .for_each(|location| edits.replace(*location, params.new_name.clone())); + .for_each(|location| edits.replace(*location, new_name.clone())); + edits.replace(reference_information.definition_location, new_name); - Some(workspace_edit(uri, edits.edits)) + let Ok(uri) = Url::from_file_path(&module.input_path) else { + return; + }; + + _ = workspace_edit + .changes + .as_mut() + .map(|changes| changes.insert(uri, std::mem::take(&mut edits.edits))); } pub fn find_variable_references( From d59eedfa9a5f1245fb2c75f18ad34c67c648f4cf Mon Sep 17 00:00:00 2001 From: GearsDatapacks Date: Tue, 25 Feb 2025 10:35:02 +0000 Subject: [PATCH 05/27] Move usage detection to analyser --- compiler-core/src/analyse.rs | 8 +- compiler-core/src/ast.rs | 3 +- compiler-core/src/call_graph.rs | 82 ++++--------------- .../call_graph/into_dependency_order_tests.rs | 3 +- compiler-core/src/language_server/engine.rs | 19 ++++- compiler-core/src/language_server/rename.rs | 14 +++- compiler-core/src/type_/environment.rs | 11 ++- compiler-core/src/type_/expression.rs | 29 ++++++- 8 files changed, 87 insertions(+), 82 deletions(-) diff --git a/compiler-core/src/analyse.rs b/compiler-core/src/analyse.rs index 44b019ee791..83171d9ca35 100644 --- a/compiler-core/src/analyse.rs +++ b/compiler-core/src/analyse.rs @@ -15,7 +15,7 @@ use crate::{ UntypedImport, UntypedModule, UntypedModuleConstant, UntypedStatement, UntypedTypeAlias, }, build::{Origin, Outcome, Target}, - call_graph::{CallGraphNode, call_graph_info}, + call_graph::{CallGraphNode, into_dependency_order}, config::PackageConfig, dep_tree, line_numbers::LineNumbers, @@ -254,8 +254,8 @@ impl<'a, A> ModuleAnalyzer<'a, A> { // Sort functions and constants into dependency order for inference. Definitions that do // not depend on other definitions are inferred first, then ones that depend // on those, etc. - let (definition_groups, references) = - match call_graph_info(statements.functions, statements.constants) { + let definition_groups = + match into_dependency_order(statements.functions, statements.constants) { Ok(it) => it, Err(error) => return self.all_errors(error), }; @@ -348,7 +348,7 @@ impl<'a, A> ModuleAnalyzer<'a, A> { .into_iter() .map(|(name, _)| name) .collect(), - value_references: references, + value_references: env.references, }, }; diff --git a/compiler-core/src/ast.rs b/compiler-core/src/ast.rs index 6e27a8ada8f..4108fc5b8ad 100644 --- a/compiler-core/src/ast.rs +++ b/compiler-core/src/ast.rs @@ -13,7 +13,6 @@ pub use self::constant::{Constant, TypedConstant, UntypedConstant}; use crate::analyse::Inferred; use crate::build::{Located, Target}; -use crate::call_graph::ReferenceInformation; use crate::parse::SpannedString; use crate::type_::error::VariableOrigin; use crate::type_::expression::Implementations; @@ -72,7 +71,7 @@ impl TypedModule { #[derive(Debug, Clone, PartialEq, Eq, Default)] pub struct References { pub imported_modules: HashSet, - pub value_references: HashMap, + pub value_references: HashMap<(EcoString, EcoString), Vec>, } /// The `@target(erlang)` and `@target(javascript)` attributes can be used to diff --git a/compiler-core/src/call_graph.rs b/compiler-core/src/call_graph.rs index b942be7dda7..22e2f8037fc 100644 --- a/compiler-core/src/call_graph.rs +++ b/compiler-core/src/call_graph.rs @@ -4,8 +4,6 @@ #[cfg(test)] mod into_dependency_order_tests; -use std::collections::HashMap; - use crate::{ Result, ast::{ @@ -15,7 +13,6 @@ use crate::{ }, type_::Error, }; -use ecow::EcoString; use itertools::Itertools; use petgraph::stable_graph::NodeIndex; use petgraph::{Directed, stable_graph::StableGraph}; @@ -25,13 +22,6 @@ struct CallGraphBuilder<'a> { names: im::HashMap<&'a str, Option<(NodeIndex, SrcSpan)>>, graph: StableGraph<(), (), Directed>, current_function: NodeIndex, - references: HashMap, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct ReferenceInformation { - pub definition_location: SrcSpan, - pub references: Vec, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -42,13 +32,8 @@ pub enum CallGraphNode { } impl<'a> CallGraphBuilder<'a> { - fn into_info( - self, - ) -> ( - StableGraph<(), (), Directed>, - HashMap, - ) { - (self.graph, self.references) + fn into_graph(self) -> StableGraph<(), (), Directed> { + self.graph } /// Add each function to the graph, storing the index of the node under the @@ -57,7 +42,7 @@ impl<'a> CallGraphBuilder<'a> { &mut self, function: &'a UntypedFunction, ) -> Result<(), Error> { - let (name_location, name) = function + let (_, name) = function .name .as_ref() .expect("A module's function must be named"); @@ -73,15 +58,6 @@ impl<'a> CallGraphBuilder<'a> { name: name.clone(), }); } - - _ = self.references.insert( - name.clone(), - ReferenceInformation { - definition_location: *name_location, - references: Vec::new(), - }, - ); - Ok(()) } @@ -104,15 +80,6 @@ impl<'a> CallGraphBuilder<'a> { name: name.clone(), }); } - - _ = self.references.insert( - name.clone(), - ReferenceInformation { - definition_location: constant.name_location, - references: Vec::new(), - }, - ); - Ok(()) } @@ -152,7 +119,7 @@ impl<'a> CallGraphBuilder<'a> { self.names = names; } - fn referenced(&mut self, name: &str, location: SrcSpan) { + fn referenced(&mut self, name: &str) { // If we don't know what the target is then it's either a programmer // error to be detected later, or it's not a module function and as such // is not a value we are tracking. @@ -165,10 +132,6 @@ impl<'a> CallGraphBuilder<'a> { let Some((target, _)) = target else { return }; _ = self.graph.add_edge(self.current_function, *target, ()); - _ = self - .references - .get_mut(name) - .map(|information| information.references.push(location)); } fn statements(&mut self, statements: &'a [UntypedStatement]) { @@ -226,8 +189,8 @@ impl<'a> CallGraphBuilder<'a> { } // Aha! A variable is being referenced. - UntypedExpr::Var { name, location, .. } => { - self.referenced(name, *location); + UntypedExpr::Var { name, .. } => { + self.referenced(name); } UntypedExpr::Call { fun, arguments, .. } => { @@ -376,8 +339,8 @@ impl<'a> CallGraphBuilder<'a> { } } - Pattern::VarUsage { name, location, .. } => { - self.referenced(name, *location); + Pattern::VarUsage { name, .. } => { + self.referenced(name); } Pattern::Assign { name, pattern, .. } => { @@ -464,17 +427,13 @@ impl<'a> CallGraphBuilder<'a> { ClauseGuard::Not { expression, .. } => self.guard(expression), - ClauseGuard::Var { name, location, .. } => self.referenced(name, *location), + ClauseGuard::Var { name, .. } => self.referenced(name), ClauseGuard::TupleIndex { tuple, .. } => self.guard(tuple), ClauseGuard::FieldAccess { container, .. } => self.guard(container), - ClauseGuard::ModuleSelect { - module_name, - location, - .. - } => self.referenced(module_name, *location), + ClauseGuard::ModuleSelect { module_name, .. } => self.referenced(module_name), ClauseGuard::Constant(constant) => self.constant(constant), } @@ -503,11 +462,8 @@ impl<'a> CallGraphBuilder<'a> { } Constant::Var { - module: None, - name, - location, - .. - } => self.referenced(name, *location), + module: None, name, .. + } => self.referenced(name), Constant::BitArray { segments, .. } => { for segment in segments { @@ -529,16 +485,10 @@ impl<'a> CallGraphBuilder<'a> { /// Determine the order in which functions and constants should be compiled and if any /// mutually recursive functions need to be compiled together. /// -pub fn call_graph_info( +pub fn into_dependency_order( functions: Vec, constants: Vec, -) -> Result< - ( - Vec>, - HashMap, - ), - Error, -> { +) -> Result>, Error> { let mut grapher = CallGraphBuilder::default(); for function in &functions { @@ -559,7 +509,7 @@ pub fn call_graph_info( } // Consume the grapher to get the graph - let (graph, references) = grapher.into_info(); + let graph = grapher.into_graph(); // Determine the order in which the functions should be compiled by looking // at which other functions they depend on. @@ -591,5 +541,5 @@ pub fn call_graph_info( }) .collect_vec(); - Ok((ordered, references)) + Ok(ordered) } diff --git a/compiler-core/src/call_graph/into_dependency_order_tests.rs b/compiler-core/src/call_graph/into_dependency_order_tests.rs index 87fb5dd6751..e3f6bb48306 100644 --- a/compiler-core/src/call_graph/into_dependency_order_tests.rs +++ b/compiler-core/src/call_graph/into_dependency_order_tests.rs @@ -72,8 +72,7 @@ fn parse_and_order( }) .collect_vec(); - Ok(call_graph_info(functions, constants)? - .0 + Ok(into_dependency_order(functions, constants)? .into_iter() .map(|level| { level diff --git a/compiler-core/src/language_server/engine.rs b/compiler-core/src/language_server/engine.rs index 1830424620f..b9e57059acf 100644 --- a/compiler-core/src/language_server/engine.rs +++ b/compiler-core/src/language_server/engine.rs @@ -709,13 +709,26 @@ where constructor: ValueConstructor { variant: - ValueConstructorVariant::ModuleConstant { .. } - | ValueConstructorVariant::ModuleFn { .. }, + ValueConstructorVariant::ModuleConstant { + module: module_name, + .. + } + | ValueConstructorVariant::ModuleFn { + module: module_name, + .. + }, .. }, name, .. - }) => rename_module_value(module, &lines, ¶ms, name, &this.compiler.modules), + }) => rename_module_value( + module, + &lines, + ¶ms, + module_name, + name, + &this.compiler.modules, + ), _ => None, }) }) diff --git a/compiler-core/src/language_server/rename.rs b/compiler-core/src/language_server/rename.rs index b1a81e24698..8233e257564 100644 --- a/compiler-core/src/language_server/rename.rs +++ b/compiler-core/src/language_server/rename.rs @@ -69,6 +69,7 @@ pub fn rename_module_value( main_module: &Module, line_numbers: &LineNumbers, params: &RenameParams, + module_name: &EcoString, name: &EcoString, modules: &HashMap, ) -> Option { @@ -93,6 +94,7 @@ pub fn rename_module_value( main_module, &mut edits, &mut workspace_edit, + module_name, name, params.new_name.clone(), ); @@ -107,6 +109,7 @@ pub fn rename_module_value( module, &mut edits, &mut workspace_edit, + module_name, name, params.new_name.clone(), ); @@ -120,18 +123,23 @@ fn rename_references_in_module( module: &Module, edits: &mut TextEdits<'_>, workspace_edit: &mut WorkspaceEdit, + module_name: &EcoString, name: &EcoString, new_name: String, ) { - let Some(reference_information) = module.ast.references.value_references.get(name) else { + let Some(reference_information) = module + .ast + .references + .value_references + .get(&(module_name.clone(), name.clone())) + else { return; }; reference_information - .references .iter() .for_each(|location| edits.replace(*location, new_name.clone())); - edits.replace(reference_information.definition_location, new_name); + // edits.replace(reference_information.definition_location, new_name); let Ok(uri) = Url::from_file_path(&module.input_path) else { return; diff --git a/compiler-core/src/type_/environment.rs b/compiler-core/src/type_/environment.rs index 1b72e7f9c56..016f51e6ec8 100644 --- a/compiler-core/src/type_/environment.rs +++ b/compiler-core/src/type_/environment.rs @@ -69,6 +69,8 @@ pub struct Environment<'a> { /// Wether we ran into an `echo` or not while analysing the current module. pub echo_found: bool, + + pub references: HashMap<(EcoString, EcoString), Vec>, } impl<'a> Environment<'a> { @@ -122,8 +124,8 @@ impl<'a> Environment<'a> { names, module_type_aliases: HashMap::new(), echo_found: false, + references: HashMap::new(), } - } } #[derive(Debug, Clone, PartialEq, Eq)] @@ -807,6 +809,13 @@ impl Environment<'_> { .and_then(|type_constructors| type_constructors.variants.get(variant_index as usize)) .map(|variant| &variant.name) } + + pub fn register_reference(&mut self, module: EcoString, name: EcoString, location: SrcSpan) { + self.references + .entry((module, name)) + .or_default() + .push(location); + } } #[derive(Debug)] diff --git a/compiler-core/src/type_/expression.rs b/compiler-core/src/type_/expression.rs index 4199911e188..a26fd4fc21f 100644 --- a/compiler-core/src/type_/expression.rs +++ b/compiler-core/src/type_/expression.rs @@ -2337,7 +2337,22 @@ impl<'a, 'b> ExprTyper<'a, 'b> { let _ = self.environment.unused_modules.remove(module_alias); let _ = self.environment.unused_module_aliases.remove(module_alias); - (module.name.clone(), constructor.clone()) + let constructor = constructor.clone(); + let module_name = module.name.clone(); + + match &constructor.variant { + ValueConstructorVariant::ModuleFn { name, module, .. } => self + .environment + .register_reference(module.clone(), name.clone(), select_location), + ValueConstructorVariant::ModuleConstant { module, .. } => self + .environment + .register_reference(module.clone(), label.clone(), select_location), + ValueConstructorVariant::LocalVariable { .. } + | ValueConstructorVariant::LocalConstant { .. } + | ValueConstructorVariant::Record { .. } => {} + } + + (module_name, constructor) }; let type_ = self.instantiate(constructor.type_, &mut hashmap![]); @@ -2913,6 +2928,18 @@ impl<'a, 'b> ExprTyper<'a, 'b> { self.narrow_implementations(*location, &variant)?; + match &variant { + ValueConstructorVariant::ModuleFn { name, module, .. } => self + .environment + .register_reference(module.clone(), name.clone(), *location), + ValueConstructorVariant::ModuleConstant { module, .. } => self + .environment + .register_reference(module.clone(), name.clone(), *location), + ValueConstructorVariant::LocalVariable { .. } + | ValueConstructorVariant::LocalConstant { .. } + | ValueConstructorVariant::Record { .. } => {} + } + // Instantiate generic variables into unbound variables for this usage let type_ = self.instantiate(type_, &mut hashmap![]); Ok(ValueConstructor { From e91923aa9bfabf747e8b78939044b6fa89840667 Mon Sep 17 00:00:00 2001 From: GearsDatapacks Date: Tue, 25 Feb 2025 10:42:41 +0000 Subject: [PATCH 06/27] Properly rename definition name --- compiler-core/src/analyse.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/compiler-core/src/analyse.rs b/compiler-core/src/analyse.rs index 83171d9ca35..5384882d005 100644 --- a/compiler-core/src/analyse.rs +++ b/compiler-core/src/analyse.rs @@ -429,6 +429,12 @@ impl<'a, A> ModuleAnalyzer<'a, A> { ); environment.insert_module_value(name.clone(), variant); + environment.register_reference( + environment.current_module.clone(), + name.clone(), + name_location, + ); + if publicity.is_private() { environment.init_usage( name.clone(), @@ -642,6 +648,12 @@ impl<'a, A> ModuleAnalyzer<'a, A> { deprecation.clone(), ); + environment.register_reference( + environment.current_module.clone(), + name.clone(), + name_location, + ); + Definition::Function(Function { documentation: doc, location, From b54384859970e60287e87277ae90ac771e273b74 Mon Sep 17 00:00:00 2001 From: GearsDatapacks Date: Tue, 25 Feb 2025 21:48:54 +0000 Subject: [PATCH 07/27] Fix cross-module renaming --- compiler-core/src/language_server/engine.rs | 11 ++--- compiler-core/src/language_server/rename.rs | 15 +++--- compiler-core/src/language_server/tests.rs | 19 ++++--- .../src/language_server/tests/rename.rs | 49 +++++++++++++------ 4 files changed, 55 insertions(+), 39 deletions(-) diff --git a/compiler-core/src/language_server/engine.rs b/compiler-core/src/language_server/engine.rs index b9e57059acf..d1a921a866a 100644 --- a/compiler-core/src/language_server/engine.rs +++ b/compiler-core/src/language_server/engine.rs @@ -721,14 +721,9 @@ where }, name, .. - }) => rename_module_value( - module, - &lines, - ¶ms, - module_name, - name, - &this.compiler.modules, - ), + }) => { + rename_module_value(module, ¶ms, module_name, name, &this.compiler.modules) + } _ => None, }) }) diff --git a/compiler-core/src/language_server/rename.rs b/compiler-core/src/language_server/rename.rs index 8233e257564..15820bcc4c9 100644 --- a/compiler-core/src/language_server/rename.rs +++ b/compiler-core/src/language_server/rename.rs @@ -67,7 +67,6 @@ pub fn rename_local_variable( pub fn rename_module_value( main_module: &Module, - line_numbers: &LineNumbers, params: &RenameParams, module_name: &EcoString, name: &EcoString, @@ -83,7 +82,6 @@ pub fn rename_module_value( return None; } - let mut edits = TextEdits::new(line_numbers); let mut workspace_edit = WorkspaceEdit { changes: Some(HashMap::new()), document_changes: None, @@ -92,12 +90,12 @@ pub fn rename_module_value( rename_references_in_module( main_module, - &mut edits, &mut workspace_edit, module_name, name, params.new_name.clone(), ); + for (_, module) in modules { if module .ast @@ -107,7 +105,6 @@ pub fn rename_module_value( { rename_references_in_module( module, - &mut edits, &mut workspace_edit, module_name, name, @@ -121,13 +118,12 @@ pub fn rename_module_value( fn rename_references_in_module( module: &Module, - edits: &mut TextEdits<'_>, workspace_edit: &mut WorkspaceEdit, module_name: &EcoString, name: &EcoString, new_name: String, ) { - let Some(reference_information) = module + let Some(references) = module .ast .references .value_references @@ -136,7 +132,10 @@ fn rename_references_in_module( return; }; - reference_information + let line_numbers = LineNumbers::new(&module.code); + let mut edits = TextEdits::new(&line_numbers); + + references .iter() .for_each(|location| edits.replace(*location, new_name.clone())); // edits.replace(reference_information.definition_location, new_name); @@ -148,7 +147,7 @@ fn rename_references_in_module( _ = workspace_edit .changes .as_mut() - .map(|changes| changes.insert(uri, std::mem::take(&mut edits.edits))); + .map(|changes| changes.insert(uri, edits.edits)); } pub fn find_variable_references( diff --git a/compiler-core/src/language_server/tests.rs b/compiler-core/src/language_server/tests.rs index 90fd9b1361d..1f8353a2266 100644 --- a/compiler-core/src/language_server/tests.rs +++ b/compiler-core/src/language_server/tests.rs @@ -411,14 +411,19 @@ impl<'a> TestProject<'a> { } } + pub fn module_name_from_url(&self, url: &Url) -> Option { + Some( + url.path_segments()? + .skip_while(|segment| *segment != "src") + .skip(1) + .join("/") + .trim_end_matches(".gleam") + .into(), + ) + } + pub fn src_from_module_url(&self, url: &Url) -> Option<&str> { - let module_name: EcoString = url - .path_segments()? - .skip_while(|segment| *segment != "src") - .skip(1) - .join("/") - .trim_end_matches(".gleam") - .into(); + let module_name: EcoString = self.module_name_from_url(url)?.into(); if module_name == "app" { return Some(self.src); diff --git a/compiler-core/src/language_server/tests/rename.rs b/compiler-core/src/language_server/tests/rename.rs index 821d6d8b2d5..633a818aec5 100644 --- a/compiler-core/src/language_server/tests/rename.rs +++ b/compiler-core/src/language_server/tests/rename.rs @@ -7,7 +7,7 @@ use crate::language_server::tests::{TestProject, find_position_of}; use super::hover; fn rename( - tester: TestProject<'_>, + tester: &TestProject<'_>, new_name: &str, position: Position, ) -> Option { @@ -32,21 +32,31 @@ fn rename( }) } -fn apply_rename(tester: TestProject<'_>, new_name: &str, position: Position) -> String { - let src = tester.src; - let changes = rename(tester, new_name, position) +fn apply_rename( + tester: TestProject<'_>, + new_name: &str, + position: Position, +) -> HashMap { + let changes = rename(&tester, new_name, position) .expect("Rename failed") .changes .expect("No text edit found"); - apply_code_edit(src, changes) + apply_code_edit(tester, changes) } -fn apply_code_edit(src: &str, changes: HashMap>) -> String { - let mut result = src.to_string(); - for (_, change) in changes { - result = super::apply_code_edit(result.as_str(), change); +fn apply_code_edit( + tester: TestProject<'_>, + changes: HashMap>, +) -> HashMap { + let mut modules = HashMap::new(); + for (uri, change) in changes { + let module_name = tester.module_name_from_url(&uri).expect("Valid uri"); + let module_code = tester.src_from_module_url(&uri).expect("Module exists"); + + _ = modules.insert(module_name, super::apply_code_edit(module_code, change)); } - result + + modules } macro_rules! assert_rename { @@ -58,12 +68,19 @@ macro_rules! assert_rename { ($project:expr, $new_name:literal, $range:expr $(,)?) => { let src = $project.src; let range = $range.find_range(src); + let mut output = String::from("----- BEFORE RENAME\n"); + for (name, src) in $project.root_package_modules.iter() { + output.push_str(&format!("-- {name}.gleam\n{src}\n\n")); + } + output.push_str(&format!( + "-- app.gleam\n{}\n\n----- AFTER RENAME\n", + hover::show_hover(src, range, range.start) + )); + let result = apply_rename($project, $new_name, range.start); - let output = format!( - "----- BEFORE RENAME\n{}\n\n----- AFTER RENAME\n{}", - hover::show_hover(src, range, range.start), - result - ); + for (name, src) in result { + output.push_str(&format!("-- {name}.gleam\n{}\n\n", src)); + } insta::assert_snapshot!(insta::internals::AutoName, output, src); }; } @@ -71,7 +88,7 @@ macro_rules! assert_rename { macro_rules! assert_no_rename { ($code:literal, $new_name:literal, $range:expr $(,)?) => { let project = TestProject::for_source($code); - assert_no_rename!(project, $new_name, $range); + assert_no_rename!(&project, $new_name, $range); }; ($project:expr, $new_name:literal, $range:expr $(,)?) => { From e5b0c2e9b46b7415b02d098a02a1bf3870c7ea86 Mon Sep 17 00:00:00 2001 From: GearsDatapacks Date: Tue, 25 Feb 2025 22:26:50 +0000 Subject: [PATCH 08/27] Register usage on unqualified imports --- compiler-core/src/analyse/imports.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/compiler-core/src/analyse/imports.rs b/compiler-core/src/analyse/imports.rs index 54b18e9b9a4..1e77e6247cb 100644 --- a/compiler-core/src/analyse/imports.rs +++ b/compiler-core/src/analyse/imports.rs @@ -172,6 +172,17 @@ impl<'context, 'problems> Importer<'context, 'problems> { used_name.clone(), ); } + ValueConstructorVariant::ModuleConstant { module, .. } + | ValueConstructorVariant::ModuleFn { module, .. } => { + self.environment.init_usage( + used_name.clone(), + EntityKind::ImportedValue, + location, + self.problems, + ); + self.environment + .register_reference(module.clone(), import_name.clone(), location); + } _ => self.environment.init_usage( used_name.clone(), EntityKind::ImportedValue, From 6cd0e5027d8e8fb56b561a34db107910f7088fb8 Mon Sep 17 00:00:00 2001 From: GearsDatapacks Date: Tue, 25 Feb 2025 22:29:58 +0000 Subject: [PATCH 09/27] Clippy --- compiler-core/src/analyse.rs | 6 +----- compiler-core/src/language_server/rename.rs | 3 +-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/compiler-core/src/analyse.rs b/compiler-core/src/analyse.rs index 5384882d005..56d2fea23d5 100644 --- a/compiler-core/src/analyse.rs +++ b/compiler-core/src/analyse.rs @@ -343,11 +343,7 @@ impl<'a, A> ModuleAnalyzer<'a, A> { }, names: type_names, references: References { - imported_modules: env - .imported_modules - .into_iter() - .map(|(name, _)| name) - .collect(), + imported_modules: env.imported_modules.into_keys().collect(), value_references: env.references, }, }; diff --git a/compiler-core/src/language_server/rename.rs b/compiler-core/src/language_server/rename.rs index 15820bcc4c9..bcd2549db5c 100644 --- a/compiler-core/src/language_server/rename.rs +++ b/compiler-core/src/language_server/rename.rs @@ -96,7 +96,7 @@ pub fn rename_module_value( params.new_name.clone(), ); - for (_, module) in modules { + for module in modules.values() { if module .ast .references @@ -138,7 +138,6 @@ fn rename_references_in_module( references .iter() .for_each(|location| edits.replace(*location, new_name.clone())); - // edits.replace(reference_information.definition_location, new_name); let Ok(uri) = Url::from_file_path(&module.input_path) else { return; From 5c1c9bb79028d7829a074d718885d8e2bc83d690 Mon Sep 17 00:00:00 2001 From: GearsDatapacks Date: Tue, 25 Feb 2025 22:42:11 +0000 Subject: [PATCH 10/27] Update snapshots --- ...anguage_server__tests__rename__rename_local_variable.snap | 2 ++ ...erver__tests__rename__rename_local_variable_argument.snap | 2 ++ ...name__rename_local_variable_argument_from_definition.snap | 2 ++ ...ts__rename__rename_local_variable_assignment_pattern.snap | 2 ++ ...rename__rename_local_variable_from_bit_array_pattern.snap | 2 ++ ...tests__rename__rename_local_variable_from_definition.snap | 2 ++ ...me_local_variable_from_definition_assignment_pattern.snap | 2 ++ ...rename_local_variable_from_definition_nested_pattern.snap | 2 ++ ...r__tests__rename__rename_local_variable_guard_clause.snap | 2 ++ ...__rename__rename_local_variable_in_bit_array_pattern.snap | 2 ++ ...tests__rename__rename_local_variable_label_shorthand.snap | 2 ++ ...ename_local_variable_label_shorthand_from_definition.snap | 2 ++ ...__tests__rename__rename_local_variable_record_access.snap | 2 ++ ...erver__tests__rename__rename_shadowed_local_variable.snap | 2 ++ ...rver__tests__rename__rename_shadowing_local_variable.snap | 2 ++ .../gleam_core__parse__tests__const_string_concat.snap | 5 ++++- ..._parse__tests__deprecation_attribute_on_type_variant.snap | 5 ++++- .../snapshots/gleam_core__parse__tests__import_type.snap | 5 ++++- .../gleam_core__parse__tests__record_access_no_label.snap | 5 ++++- 19 files changed, 46 insertions(+), 4 deletions(-) diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable.snap index 2a00d13fdb6..c9fe2ef2a67 100644 --- a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable.snap +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable.snap @@ -3,6 +3,7 @@ source: compiler-core/src/language_server/tests/rename.rs expression: "\npub fn main() {\n let wibble = 10\n wibble\n}\n" --- ----- BEFORE RENAME +-- app.gleam pub fn main() { let wibble = 10 @@ -12,6 +13,7 @@ pub fn main() { ----- AFTER RENAME +-- app.gleam pub fn main() { let wobble = 10 diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_argument.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_argument.snap index 226f31e3814..f2525a9a51b 100644 --- a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_argument.snap +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_argument.snap @@ -3,6 +3,7 @@ source: compiler-core/src/language_server/tests/rename.rs expression: "\npub fn add(first_number: Int, x: Int) -> Int {\n x + first_number\n}\n" --- ----- BEFORE RENAME +-- app.gleam pub fn add(first_number: Int, x: Int) -> Int { x + first_number @@ -11,6 +12,7 @@ pub fn add(first_number: Int, x: Int) -> Int { ----- AFTER RENAME +-- app.gleam pub fn add(first_number: Int, second_number: Int) -> Int { second_number + first_number diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_argument_from_definition.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_argument_from_definition.snap index fa549c288e4..60cdfdadd77 100644 --- a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_argument_from_definition.snap +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_argument_from_definition.snap @@ -3,6 +3,7 @@ source: compiler-core/src/language_server/tests/rename.rs expression: "\npub fn wibble(wibble: Float) {\n wibble /. 0.3\n}\n" --- ----- BEFORE RENAME +-- app.gleam pub fn wibble(wibble: Float) { ↑ @@ -11,6 +12,7 @@ pub fn wibble(wibble: Float) { ----- AFTER RENAME +-- app.gleam pub fn wibble(wobble: Float) { wobble /. 0.3 diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_assignment_pattern.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_assignment_pattern.snap index 3a3fab80353..0e47e7a9c62 100644 --- a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_assignment_pattern.snap +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_assignment_pattern.snap @@ -3,6 +3,7 @@ source: compiler-core/src/language_server/tests/rename.rs expression: "\npub fn main() {\n let assert Error(12 as something) = Error(12)\n something\n}\n" --- ----- BEFORE RENAME +-- app.gleam pub fn main() { let assert Error(12 as something) = Error(12) @@ -12,6 +13,7 @@ pub fn main() { ----- AFTER RENAME +-- app.gleam pub fn main() { let assert Error(12 as the_error) = Error(12) diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_from_bit_array_pattern.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_from_bit_array_pattern.snap index 17caf9b3efe..7837a1f5efe 100644 --- a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_from_bit_array_pattern.snap +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_from_bit_array_pattern.snap @@ -3,6 +3,7 @@ source: compiler-core/src/language_server/tests/rename.rs expression: "\npub fn starts_with(bits: BitArray, prefix: BitArray) -> Bool {\n let prefix_size = bit_size(prefix)\n\n case bits {\n <> if pref == prefix -> True\n _ -> False\n }\n}\n" --- ----- BEFORE RENAME +-- app.gleam pub fn starts_with(bits: BitArray, prefix: BitArray) -> Bool { let prefix_size = bit_size(prefix) @@ -16,6 +17,7 @@ pub fn starts_with(bits: BitArray, prefix: BitArray) -> Bool { ----- AFTER RENAME +-- app.gleam pub fn starts_with(bits: BitArray, prefix: BitArray) -> Bool { let size_of_prefix = bit_size(prefix) diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_from_definition.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_from_definition.snap index afadbd45cce..5a044ab3ccf 100644 --- a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_from_definition.snap +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_from_definition.snap @@ -3,6 +3,7 @@ source: compiler-core/src/language_server/tests/rename.rs expression: "\npub fn main() {\n let wibble = 10\n let wobble = wibble + 1\n wobble - wibble\n}\n" --- ----- BEFORE RENAME +-- app.gleam pub fn main() { let wibble = 10 @@ -13,6 +14,7 @@ pub fn main() { ----- AFTER RENAME +-- app.gleam pub fn main() { let some_value = 10 diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_from_definition_assignment_pattern.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_from_definition_assignment_pattern.snap index d180c41f4a8..0804e5e405d 100644 --- a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_from_definition_assignment_pattern.snap +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_from_definition_assignment_pattern.snap @@ -3,6 +3,7 @@ source: compiler-core/src/language_server/tests/rename.rs expression: "\npub fn main() {\n let assert Error(12 as something) = Error(12)\n something\n}\n" --- ----- BEFORE RENAME +-- app.gleam pub fn main() { let assert Error(12 as something) = Error(12) @@ -12,6 +13,7 @@ pub fn main() { ----- AFTER RENAME +-- app.gleam pub fn main() { let assert Error(12 as the_error) = Error(12) diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_from_definition_nested_pattern.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_from_definition_nested_pattern.snap index 2886c401199..543e2a9d17c 100644 --- a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_from_definition_nested_pattern.snap +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_from_definition_nested_pattern.snap @@ -3,6 +3,7 @@ source: compiler-core/src/language_server/tests/rename.rs expression: "\npub fn main() {\n let assert Ok([_, wibble, ..]) = Error(12)\n wibble\n}\n" --- ----- BEFORE RENAME +-- app.gleam pub fn main() { let assert Ok([_, wibble, ..]) = Error(12) @@ -12,6 +13,7 @@ pub fn main() { ----- AFTER RENAME +-- app.gleam pub fn main() { let assert Ok([_, second_element, ..]) = Error(12) diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_guard_clause.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_guard_clause.snap index 11b1c7b637d..5a03711d387 100644 --- a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_guard_clause.snap +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_guard_clause.snap @@ -3,6 +3,7 @@ source: compiler-core/src/language_server/tests/rename.rs expression: "\npub fn main() {\n let wibble = True\n case Nil {\n Nil if wibble -> todo\n _ -> panic\n }\n wibble || False\n}\n" --- ----- BEFORE RENAME +-- app.gleam pub fn main() { let wibble = True @@ -16,6 +17,7 @@ pub fn main() { ----- AFTER RENAME +-- app.gleam pub fn main() { let wobble = True diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_in_bit_array_pattern.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_in_bit_array_pattern.snap index fae10100348..fbefaed1e72 100644 --- a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_in_bit_array_pattern.snap +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_in_bit_array_pattern.snap @@ -3,6 +3,7 @@ source: compiler-core/src/language_server/tests/rename.rs expression: "\npub fn starts_with(bits: BitArray, prefix: BitArray) -> Bool {\n let prefix_size = bit_size(prefix)\n\n case bits {\n <> if pref == prefix -> True\n _ -> False\n }\n}\n" --- ----- BEFORE RENAME +-- app.gleam pub fn starts_with(bits: BitArray, prefix: BitArray) -> Bool { let prefix_size = bit_size(prefix) @@ -16,6 +17,7 @@ pub fn starts_with(bits: BitArray, prefix: BitArray) -> Bool { ----- AFTER RENAME +-- app.gleam pub fn starts_with(bits: BitArray, prefix: BitArray) -> Bool { let size_of_prefix = bit_size(prefix) diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_label_shorthand.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_label_shorthand.snap index f8c0820843c..badbcd5a874 100644 --- a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_label_shorthand.snap +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_label_shorthand.snap @@ -3,6 +3,7 @@ source: compiler-core/src/language_server/tests/rename.rs expression: "\ntype Wibble {\n Wibble(wibble: Int)\n}\n\npub fn main() {\n let Wibble(wibble:) = todo\n wibble + 1\n}\n" --- ----- BEFORE RENAME +-- app.gleam type Wibble { Wibble(wibble: Int) @@ -16,6 +17,7 @@ pub fn main() { ----- AFTER RENAME +-- app.gleam type Wibble { Wibble(wibble: Int) diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_label_shorthand_from_definition.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_label_shorthand_from_definition.snap index 0c66607572f..0b408992b1d 100644 --- a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_label_shorthand_from_definition.snap +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_label_shorthand_from_definition.snap @@ -3,6 +3,7 @@ source: compiler-core/src/language_server/tests/rename.rs expression: "\ntype Wibble {\n Wibble(wibble: Int)\n}\n\npub fn main() {\n let Wibble(wibble:) = todo\n wibble + 1\n}\n" --- ----- BEFORE RENAME +-- app.gleam type Wibble { Wibble(wibble: Int) @@ -16,6 +17,7 @@ pub fn main() { ----- AFTER RENAME +-- app.gleam type Wibble { Wibble(wibble: Int) diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_record_access.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_record_access.snap index dbac89fd95b..b20ad3c57bc 100644 --- a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_record_access.snap +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_local_variable_record_access.snap @@ -3,6 +3,7 @@ source: compiler-core/src/language_server/tests/rename.rs expression: "\ntype Wibble {\n Wibble(wibble: Int)\n}\n\npub fn main() {\n let wibble = Wibble(wibble: 1)\n wibble.wibble\n}\n" --- ----- BEFORE RENAME +-- app.gleam type Wibble { Wibble(wibble: Int) @@ -16,6 +17,7 @@ pub fn main() { ----- AFTER RENAME +-- app.gleam type Wibble { Wibble(wibble: Int) diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_shadowed_local_variable.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_shadowed_local_variable.snap index 6b25f6f26e3..49147f64abc 100644 --- a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_shadowed_local_variable.snap +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_shadowed_local_variable.snap @@ -3,6 +3,7 @@ source: compiler-core/src/language_server/tests/rename.rs expression: "\npub fn main() {\n let wibble = 10\n let wibble = wibble / 2\n wibble\n}\n" --- ----- BEFORE RENAME +-- app.gleam pub fn main() { let wibble = 10 @@ -13,6 +14,7 @@ pub fn main() { ----- AFTER RENAME +-- app.gleam pub fn main() { let wobble = 10 diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_shadowing_local_variable.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_shadowing_local_variable.snap index 296cf7d36e5..41c2318b397 100644 --- a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_shadowing_local_variable.snap +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_shadowing_local_variable.snap @@ -3,6 +3,7 @@ source: compiler-core/src/language_server/tests/rename.rs expression: "\npub fn main() {\n let wibble = 10\n let wibble = wibble / 2\n wibble\n}\n" --- ----- BEFORE RENAME +-- app.gleam pub fn main() { let wibble = 10 @@ -13,6 +14,7 @@ pub fn main() { ----- AFTER RENAME +-- app.gleam pub fn main() { let wibble = 10 diff --git a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__const_string_concat.snap b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__const_string_concat.snap index 4adf196b592..59c29e1eaa5 100644 --- a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__const_string_concat.snap +++ b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__const_string_concat.snap @@ -101,7 +101,10 @@ Parsed { type_variables: {}, local_value_constructors: {}, }, - references: {}, + references: References { + imported_modules: {}, + value_references: {}, + }, }, extra: ModuleExtra { module_comments: [], diff --git a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__deprecation_attribute_on_type_variant.snap b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__deprecation_attribute_on_type_variant.snap index 7e22b65d1fe..32f8b4fcb0a 100644 --- a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__deprecation_attribute_on_type_variant.snap +++ b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__deprecation_attribute_on_type_variant.snap @@ -70,7 +70,10 @@ Parsed { type_variables: {}, local_value_constructors: {}, }, - references: {}, + references: References { + imported_modules: {}, + value_references: {}, + }, }, extra: ModuleExtra { module_comments: [], diff --git a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__import_type.snap b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__import_type.snap index 0fd832e7634..cd08720c9dd 100644 --- a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__import_type.snap +++ b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__import_type.snap @@ -58,7 +58,10 @@ Parsed { type_variables: {}, local_value_constructors: {}, }, - references: {}, + references: References { + imported_modules: {}, + value_references: {}, + }, }, extra: ModuleExtra { module_comments: [], diff --git a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__record_access_no_label.snap b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__record_access_no_label.snap index 1a349f7480b..2513ad75803 100644 --- a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__record_access_no_label.snap +++ b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__record_access_no_label.snap @@ -164,7 +164,10 @@ Parsed { type_variables: {}, local_value_constructors: {}, }, - references: {}, + references: References { + imported_modules: {}, + value_references: {}, + }, }, extra: ModuleExtra { module_comments: [], From 65851a9809287a93a62eaf73d01fa90d7e9dc656 Mon Sep 17 00:00:00 2001 From: GearsDatapacks Date: Tue, 25 Feb 2025 22:46:08 +0000 Subject: [PATCH 11/27] Changelog --- CHANGELOG.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 858bd652998..f104ae6b72a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,40 @@ ### Language server +- The language server now allows renaming of functions and constants across modules. + For example: + + ```gleam + // wibble.gleam + pub fn wibble() { + wibble() + //^ Trigger rename + } + // wobble.gleam + import wibble + + pub fn main() { + wibble.wibble() + } + ``` + + Becomes: + + ```gleam + // wibble.gleam + pub fn wobble() { + wobble() + } + // wobble.gleam + import wibble + + pub fn main() { + wibble.wobble() + } + ``` + + ([Surya Rose](https://github.com/GearsDatapacks)) + ### Formatter ### Bug fixes From 922529bceb703f12496093f6ad2d331ced33cdf9 Mon Sep 17 00:00:00 2001 From: GearsDatapacks Date: Tue, 25 Feb 2025 23:15:55 +0000 Subject: [PATCH 12/27] Fix renaming from the outside module a value is defined in --- compiler-core/src/language_server/engine.rs | 4 +--- compiler-core/src/language_server/rename.rs | 16 ++-------------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/compiler-core/src/language_server/engine.rs b/compiler-core/src/language_server/engine.rs index d1a921a866a..95491c3c3ad 100644 --- a/compiler-core/src/language_server/engine.rs +++ b/compiler-core/src/language_server/engine.rs @@ -721,9 +721,7 @@ where }, name, .. - }) => { - rename_module_value(module, ¶ms, module_name, name, &this.compiler.modules) - } + }) => rename_module_value(¶ms, module_name, name, &this.compiler.modules), _ => None, }) }) diff --git a/compiler-core/src/language_server/rename.rs b/compiler-core/src/language_server/rename.rs index bcd2549db5c..ce869f98e4a 100644 --- a/compiler-core/src/language_server/rename.rs +++ b/compiler-core/src/language_server/rename.rs @@ -66,7 +66,6 @@ pub fn rename_local_variable( } pub fn rename_module_value( - main_module: &Module, params: &RenameParams, module_name: &EcoString, name: &EcoString, @@ -88,20 +87,9 @@ pub fn rename_module_value( change_annotations: None, }; - rename_references_in_module( - main_module, - &mut workspace_edit, - module_name, - name, - params.new_name.clone(), - ); - for module in modules.values() { - if module - .ast - .references - .imported_modules - .contains(&main_module.name) + if &module.name == module_name + || module.ast.references.imported_modules.contains(module_name) { rename_references_in_module( module, From 88eea0588415cfc889b8fe061f149be5dc2c792c Mon Sep 17 00:00:00 2001 From: GearsDatapacks Date: Tue, 25 Feb 2025 23:23:56 +0000 Subject: [PATCH 13/27] Add more renaming locations for constants and functions --- compiler-core/src/language_server/engine.rs | 26 +++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/compiler-core/src/language_server/engine.rs b/compiler-core/src/language_server/engine.rs index 95491c3c3ad..b64d9145080 100644 --- a/compiler-core/src/language_server/engine.rs +++ b/compiler-core/src/language_server/engine.rs @@ -2,8 +2,8 @@ use crate::{ Error, Result, Warning, analyse::name::correct_name_case, ast::{ - self, ArgNames, CustomType, Definition, DefinitionLocation, ModuleConstant, Pattern, - SrcSpan, TypedArg, TypedExpr, TypedFunction, TypedModule, TypedPattern, + self, ArgNames, CustomType, Definition, DefinitionLocation, Function, ModuleConstant, + Pattern, SrcSpan, TypedArg, TypedExpr, TypedFunction, TypedModule, TypedPattern, }, build::{Located, Module, UnqualifiedImport, type_constructor_from_modules}, config::PackageConfig, @@ -611,6 +611,18 @@ where location, .. }) => success_response(*location), + Located::Expression(TypedExpr::ModuleSelect { + location, + field_start, + .. + }) => success_response(SrcSpan::new(*field_start, location.end)), + Located::ModuleStatement( + Definition::Function(Function { + name: Some((name_location, _)), + .. + }) + | Definition::ModuleConstant(ModuleConstant { name_location, .. }), + ) => success_response(*name_location), _ => None, }) }) @@ -722,6 +734,16 @@ where name, .. }) => rename_module_value(¶ms, module_name, name, &this.compiler.modules), + Located::Expression(TypedExpr::ModuleSelect { + module_name, label, .. + }) => rename_module_value(¶ms, module_name, label, &this.compiler.modules), + Located::ModuleStatement( + Definition::Function(Function { + name: Some((_, name)), + .. + }) + | Definition::ModuleConstant(ModuleConstant { name, .. }), + ) => rename_module_value(¶ms, &module.name, name, &this.compiler.modules), _ => None, }) }) From 86c8e510b5b9cad0e947d71978935d9512cc6fc4 Mon Sep 17 00:00:00 2001 From: GearsDatapacks Date: Wed, 26 Feb 2025 12:16:42 +0000 Subject: [PATCH 14/27] Allow renaming of type variants --- compiler-core/src/analyse.rs | 6 ++ compiler-core/src/analyse/imports.rs | 2 + compiler-core/src/ast.rs | 21 ++--- compiler-core/src/build.rs | 10 ++- compiler-core/src/language_server/engine.rs | 89 ++++++++++++++++++--- compiler-core/src/language_server/rename.rs | 3 +- compiler-core/src/type_/expression.rs | 12 +-- 7 files changed, 113 insertions(+), 30 deletions(-) diff --git a/compiler-core/src/analyse.rs b/compiler-core/src/analyse.rs index 56d2fea23d5..511e0878a4f 100644 --- a/compiler-core/src/analyse.rs +++ b/compiler-core/src/analyse.rs @@ -1095,6 +1095,12 @@ impl<'a, A> ModuleAnalyzer<'a, A> { }, ); + environment.register_reference( + environment.current_module.clone(), + constructor.name.clone(), + constructor.name_location, + ); + if value_constructor_publicity.is_private() { environment.init_usage( constructor.name.clone(), diff --git a/compiler-core/src/analyse/imports.rs b/compiler-core/src/analyse/imports.rs index 1e77e6247cb..603d3beaa20 100644 --- a/compiler-core/src/analyse/imports.rs +++ b/compiler-core/src/analyse/imports.rs @@ -171,6 +171,8 @@ impl<'context, 'problems> Importer<'context, 'problems> { name.clone(), used_name.clone(), ); + self.environment + .register_reference(module.clone(), import_name.clone(), location); } ValueConstructorVariant::ModuleConstant { module, .. } | ValueConstructorVariant::ModuleFn { module, .. } => { diff --git a/compiler-core/src/ast.rs b/compiler-core/src/ast.rs index 4108fc5b8ad..1795e3d4a0f 100644 --- a/compiler-core/src/ast.rs +++ b/compiler-core/src/ast.rs @@ -900,20 +900,21 @@ impl TypedDefinition { Definition::CustomType(custom) => { // Check if location is within the type of one of the arguments of a constructor. - if let Some(annotation) = custom + if let Some(constructor) = custom .constructors .iter() .find(|constructor| constructor.location.contains(byte_index)) - .and_then(|constructor| { - constructor - .arguments - .iter() - .find(|arg| arg.location.contains(byte_index)) - }) - .filter(|arg| arg.location.contains(byte_index)) - .and_then(|arg| arg.ast.find_node(byte_index, arg.type_.clone())) { - return Some(annotation); + if let Some(annotation) = constructor + .arguments + .iter() + .find(|arg| arg.location.contains(byte_index)) + .and_then(|arg| arg.ast.find_node(byte_index, arg.type_.clone())) + { + return Some(annotation); + } + + return Some(Located::RecordConstructor(constructor)); } // Note that the custom type `.location` covers the function diff --git a/compiler-core/src/build.rs b/compiler-core/src/build.rs index 7eb7d37a466..94fda87d161 100644 --- a/compiler-core/src/build.rs +++ b/compiler-core/src/build.rs @@ -17,8 +17,8 @@ pub use self::project_compiler::{Built, Options, ProjectCompiler}; pub use self::telemetry::{NullTelemetry, Telemetry}; use crate::ast::{ - self, CallArg, CustomType, DefinitionLocation, Pattern, TypeAst, TypedArg, TypedDefinition, - TypedExpr, TypedFunction, TypedPattern, TypedStatement, + self, CallArg, CustomType, DefinitionLocation, TypedArg, TypedDefinition, TypedExpr, + TypedFunction, TypedPattern, TypedRecordConstructor, TypedStatement, }; use crate::type_::Type; use crate::{ @@ -339,6 +339,7 @@ pub enum Located<'a> { Statement(&'a TypedStatement), Expression(&'a TypedExpr), ModuleStatement(&'a TypedDefinition), + RecordConstructor(&'a TypedRecordConstructor), FunctionBody(&'a TypedFunction), Arg(&'a TypedArg), Annotation(SrcSpan, std::sync::Arc), @@ -382,6 +383,10 @@ impl<'a> Located<'a> { module: None, span: statement.location(), }), + Self::RecordConstructor(record) => Some(DefinitionLocation { + module: None, + span: record.location, + }), Self::UnqualifiedImport(UnqualifiedImport { module, name, @@ -420,6 +425,7 @@ impl<'a> Located<'a> { Located::PatternSpread { .. } => None, Located::ModuleStatement(definition) => None, + Located::RecordConstructor(_) => None, Located::FunctionBody(function) => None, Located::UnqualifiedImport(unqualified_import) => None, Located::ModuleName { .. } => None, diff --git a/compiler-core/src/language_server/engine.rs b/compiler-core/src/language_server/engine.rs index b64d9145080..a205e72f44a 100644 --- a/compiler-core/src/language_server/engine.rs +++ b/compiler-core/src/language_server/engine.rs @@ -3,7 +3,8 @@ use crate::{ analyse::name::correct_name_case, ast::{ self, ArgNames, CustomType, Definition, DefinitionLocation, Function, ModuleConstant, - Pattern, SrcSpan, TypedArg, TypedExpr, TypedFunction, TypedModule, TypedPattern, + Pattern, RecordConstructor, SrcSpan, TypedArg, TypedExpr, TypedFunction, TypedModule, + TypedPattern, }, build::{Located, Module, UnqualifiedImport, type_constructor_from_modules}, config::PackageConfig, @@ -14,8 +15,10 @@ use crate::{ line_numbers::LineNumbers, paths::ProjectPaths, type_::{ - self, Deprecation, ModuleInterface, Type, TypeConstructor, ValueConstructor, - ValueConstructorVariant, error::VariableOrigin, printer::Printer, + self, Deprecation, ModuleInterface, ModuleValueConstructor, Type, TypeConstructor, + ValueConstructor, ValueConstructorVariant, + error::{Named, VariableOrigin}, + printer::Printer, }, }; use camino::Utf8PathBuf; @@ -300,9 +303,8 @@ where Located::FunctionBody(_) => Some(completer.completion_values()), - Located::ModuleStatement(Definition::TypeAlias(_) | Definition::CustomType(_)) => { - Some(completer.completion_types()) - } + Located::ModuleStatement(Definition::TypeAlias(_) | Definition::CustomType(_)) + | Located::RecordConstructor(_) => Some(completer.completion_types()), // If the import completions returned no results and we are in an import then // we should try to provide completions for unqualified values @@ -605,7 +607,8 @@ where ValueConstructor { variant: ValueConstructorVariant::ModuleConstant { .. } - | ValueConstructorVariant::ModuleFn { .. }, + | ValueConstructorVariant::ModuleFn { .. } + | ValueConstructorVariant::Record { .. }, .. }, location, @@ -623,6 +626,9 @@ where }) | Definition::ModuleConstant(ModuleConstant { name_location, .. }), ) => success_response(*name_location), + Located::RecordConstructor(RecordConstructor { name_location, .. }) => { + success_response(*name_location) + } _ => None, }) }) @@ -733,17 +739,77 @@ where }, name, .. - }) => rename_module_value(¶ms, module_name, name, &this.compiler.modules), + }) => rename_module_value( + ¶ms, + module_name, + name, + &this.compiler.modules, + Named::Function, + ), Located::Expression(TypedExpr::ModuleSelect { - module_name, label, .. - }) => rename_module_value(¶ms, module_name, label, &this.compiler.modules), + module_name, + label, + constructor: + ModuleValueConstructor::Fn { .. } | ModuleValueConstructor::Constant { .. }, + .. + }) => rename_module_value( + ¶ms, + module_name, + label, + &this.compiler.modules, + Named::Function, + ), Located::ModuleStatement( Definition::Function(Function { name: Some((_, name)), .. }) | Definition::ModuleConstant(ModuleConstant { name, .. }), - ) => rename_module_value(¶ms, &module.name, name, &this.compiler.modules), + ) => rename_module_value( + ¶ms, + &module.name, + name, + &this.compiler.modules, + Named::Function, + ), + Located::Expression(TypedExpr::Var { + constructor: + ValueConstructor { + variant: + ValueConstructorVariant::Record { + module: module_name, + name, + .. + }, + .. + }, + .. + }) => rename_module_value( + ¶ms, + module_name, + name, + &this.compiler.modules, + Named::CustomTypeVariant, + ), + Located::Expression(TypedExpr::ModuleSelect { + module_name, + label, + constructor: ModuleValueConstructor::Record { .. }, + .. + }) => rename_module_value( + ¶ms, + module_name, + label, + &this.compiler.modules, + Named::CustomTypeVariant, + ), + Located::RecordConstructor(RecordConstructor { name, .. }) => rename_module_value( + ¶ms, + &module.name, + name, + &this.compiler.modules, + Named::CustomTypeVariant, + ), _ => None, }) }) @@ -800,6 +866,7 @@ where )) } Located::ModuleStatement(_) => None, + Located::RecordConstructor(_) => None, Located::UnqualifiedImport(UnqualifiedImport { name, module: module_name, diff --git a/compiler-core/src/language_server/rename.rs b/compiler-core/src/language_server/rename.rs index ce869f98e4a..a360dd84a30 100644 --- a/compiler-core/src/language_server/rename.rs +++ b/compiler-core/src/language_server/rename.rs @@ -70,11 +70,12 @@ pub fn rename_module_value( module_name: &EcoString, name: &EcoString, modules: &HashMap, + name_kind: Named, ) -> Option { if name::check_name_case( Default::default(), ¶ms.new_name.as_str().into(), - Named::Function, + name_kind, ) .is_err() { diff --git a/compiler-core/src/type_/expression.rs b/compiler-core/src/type_/expression.rs index a26fd4fc21f..bbc60b84643 100644 --- a/compiler-core/src/type_/expression.rs +++ b/compiler-core/src/type_/expression.rs @@ -2341,15 +2341,15 @@ impl<'a, 'b> ExprTyper<'a, 'b> { let module_name = module.name.clone(); match &constructor.variant { - ValueConstructorVariant::ModuleFn { name, module, .. } => self + ValueConstructorVariant::ModuleFn { name, module, .. } + | ValueConstructorVariant::Record { name, module, .. } => self .environment .register_reference(module.clone(), name.clone(), select_location), ValueConstructorVariant::ModuleConstant { module, .. } => self .environment .register_reference(module.clone(), label.clone(), select_location), ValueConstructorVariant::LocalVariable { .. } - | ValueConstructorVariant::LocalConstant { .. } - | ValueConstructorVariant::Record { .. } => {} + | ValueConstructorVariant::LocalConstant { .. } => {} } (module_name, constructor) @@ -2929,15 +2929,15 @@ impl<'a, 'b> ExprTyper<'a, 'b> { self.narrow_implementations(*location, &variant)?; match &variant { - ValueConstructorVariant::ModuleFn { name, module, .. } => self + ValueConstructorVariant::ModuleFn { name, module, .. } + | ValueConstructorVariant::Record { name, module, .. } => self .environment .register_reference(module.clone(), name.clone(), *location), ValueConstructorVariant::ModuleConstant { module, .. } => self .environment .register_reference(module.clone(), name.clone(), *location), ValueConstructorVariant::LocalVariable { .. } - | ValueConstructorVariant::LocalConstant { .. } - | ValueConstructorVariant::Record { .. } => {} + | ValueConstructorVariant::LocalConstant { .. } => {} } // Instantiate generic variables into unbound variables for this usage From bcb7977a784599eb3393e27dc4a4d70bfc89ad19 Mon Sep 17 00:00:00 2001 From: GearsDatapacks Date: Wed, 26 Feb 2025 12:24:50 +0000 Subject: [PATCH 15/27] Fix renaming of non-name parts of definitions --- compiler-core/src/language_server/engine.rs | 23 ++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/compiler-core/src/language_server/engine.rs b/compiler-core/src/language_server/engine.rs index a205e72f44a..71b59405b6d 100644 --- a/compiler-core/src/language_server/engine.rs +++ b/compiler-core/src/language_server/engine.rs @@ -625,9 +625,26 @@ where .. }) | Definition::ModuleConstant(ModuleConstant { name_location, .. }), - ) => success_response(*name_location), - Located::RecordConstructor(RecordConstructor { name_location, .. }) => { - success_response(*name_location) + ) + | Located::RecordConstructor(RecordConstructor { name_location, .. }) => { + let byte_index = + lines.byte_index(params.position.line, params.position.character); + // When we locate a module statement, we don't know where exactly the cursor + // is positioned. In this example, we want to rename the first but not the second: + // ```gleam + // pub fn something() { + // // ^ Trigger rename + // } + // + // pub fn something_else() { + // //^ Trigger rename + // } + // ``` + if name_location.contains(byte_index) { + success_response(*name_location) + } else { + None + } } _ => None, }) From 8fd34bff9416a3447e3e13737bae0d261ecfed3d Mon Sep 17 00:00:00 2001 From: GearsDatapacks Date: Wed, 26 Feb 2025 13:59:02 +0000 Subject: [PATCH 16/27] Don't rename aliased unqualified imports --- compiler-core/generated/schema_capnp.rs | 283 +++++++++--------- compiler-core/schema.capnp | 1 + compiler-core/src/analyse.rs | 2 + compiler-core/src/analyse/imports.rs | 14 +- compiler-core/src/ast.rs | 2 + compiler-core/src/metadata/module_decoder.rs | 1 + compiler-core/src/metadata/module_encoder.rs | 2 + compiler-core/src/metadata/tests.rs | 4 + compiler-core/src/parse.rs | 5 +- ...gleam_core__parse__tests__import_type.snap | 12 + compiler-core/src/type_.rs | 1 + compiler-core/src/type_/environment.rs | 1 + compiler-core/src/type_/expression.rs | 24 +- compiler-core/src/type_/tests.rs | 1 + 14 files changed, 199 insertions(+), 154 deletions(-) diff --git a/compiler-core/generated/schema_capnp.rs b/compiler-core/generated/schema_capnp.rs index 62ab9f7588d..9273e8720de 100644 --- a/compiler-core/generated/schema_capnp.rs +++ b/compiler-core/generated/schema_capnp.rs @@ -195,14 +195,13 @@ pub mod property { /* Value */ } } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 51] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 50] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(106, 29, 126, 201, 93, 118, 154, 200), ::capnp::word(13, 0, 0, 0, 1, 0, 0, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(2, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 1, 0, 0, 0), - ::capnp::word(67, 1, 0, 0, 128, 1, 0, 0), ::capnp::word(21, 0, 0, 0, 178, 0, 0, 0), ::capnp::word(29, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -471,14 +470,13 @@ pub mod option { /* Value */ impl Pipeline where Value: ::capnp::traits::Pipelined, ::Pipeline: ::capnp::capability::FromTypelessPipeline { } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 51] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 50] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(253, 203, 85, 217, 186, 138, 221, 238), ::capnp::word(13, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(1, 0, 7, 0, 0, 0, 2, 0), ::capnp::word(0, 0, 0, 0, 1, 0, 0, 0), - ::capnp::word(130, 1, 0, 0, 207, 1, 0, 0), ::capnp::word(21, 0, 0, 0, 162, 0, 0, 0), ::capnp::word(29, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -973,14 +971,13 @@ pub mod module { } } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 306] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 305] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(129, 5, 219, 80, 68, 149, 82, 154), ::capnp::word(13, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(11, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(209, 1, 0, 0, 176, 3, 0, 0), ::capnp::word(21, 0, 0, 0, 162, 0, 0, 0), ::capnp::word(29, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -1606,14 +1603,13 @@ pub mod type_alias_constructor { } } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 128] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 127] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(77, 68, 194, 176, 34, 71, 88, 172), ::capnp::word(13, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(6, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(178, 3, 0, 0, 122, 4, 0, 0), ::capnp::word(21, 0, 0, 0, 18, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -1926,14 +1922,13 @@ pub mod version { impl Pipeline { } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 63] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 62] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(156, 250, 40, 69, 63, 108, 134, 252), ::capnp::word(13, 0, 0, 0, 1, 0, 2, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(0, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(124, 4, 0, 0, 202, 4, 0, 0), ::capnp::word(21, 0, 0, 0, 170, 0, 0, 0), ::capnp::word(29, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -2201,14 +2196,13 @@ pub mod types_variant_constructors { impl Pipeline { } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 76] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 75] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(242, 117, 25, 190, 73, 132, 187, 199), ::capnp::word(13, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(2, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(204, 4, 0, 0, 83, 5, 0, 0), ::capnp::word(21, 0, 0, 0, 50, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -2501,14 +2495,13 @@ pub mod type_value_constructor { impl Pipeline { } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 71] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 70] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(219, 85, 99, 173, 224, 242, 6, 232), ::capnp::word(13, 0, 0, 0, 1, 0, 0, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(3, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(85, 5, 0, 0, 213, 5, 0, 0), ::capnp::word(21, 0, 0, 0, 18, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -2775,14 +2768,13 @@ pub mod type_value_constructor_parameter { } } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 51] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 50] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(234, 83, 193, 19, 176, 48, 149, 161), ::capnp::word(13, 0, 0, 0, 1, 0, 0, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(2, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(215, 5, 0, 0, 34, 6, 0, 0), ::capnp::word(21, 0, 0, 0, 90, 1, 0, 0), ::capnp::word(41, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -3154,14 +3146,13 @@ pub mod type_constructor { } } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 132] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 131] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(122, 109, 11, 224, 98, 109, 251, 177), ::capnp::word(13, 0, 0, 0, 1, 0, 0, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(7, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(36, 6, 0, 0, 79, 7, 0, 0), ::capnp::word(21, 0, 0, 0, 234, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -3544,14 +3535,13 @@ pub mod accessors_map { } } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 104] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 103] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(143, 103, 68, 141, 152, 59, 35, 132), ::capnp::word(13, 0, 0, 0, 1, 0, 0, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(4, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(81, 7, 0, 0, 9, 8, 0, 0), ::capnp::word(21, 0, 0, 0, 210, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -3825,14 +3815,13 @@ pub mod variant_specific_accessors { impl Pipeline { } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 52] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 51] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(25, 53, 175, 243, 170, 173, 34, 197), ::capnp::word(13, 0, 0, 0, 1, 0, 0, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(11, 8, 0, 0, 94, 8, 0, 0), ::capnp::word(21, 0, 0, 0, 50, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -4090,14 +4079,13 @@ pub mod record_accessor { } } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 64] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 63] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(158, 200, 86, 219, 173, 1, 90, 174), ::capnp::word(13, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(2, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(96, 8, 0, 0, 176, 8, 0, 0), ::capnp::word(21, 0, 0, 0, 226, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -4349,14 +4337,13 @@ pub mod inferred_variant { impl Pipeline { } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 50] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 49] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(153, 102, 38, 126, 162, 160, 201, 166), ::capnp::word(13, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(0, 0, 7, 0, 0, 0, 2, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(27, 9, 0, 0, 114, 9, 0, 0), ::capnp::word(21, 0, 0, 0, 234, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -4639,14 +4626,13 @@ pub mod type_ { impl Pipeline { } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 50] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 49] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(0, 7, 151, 64, 46, 128, 246, 130), ::capnp::word(13, 0, 0, 0, 1, 0, 2, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(5, 0, 7, 0, 0, 0, 4, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(116, 9, 0, 0, 236, 10, 0, 0), ::capnp::word(21, 0, 0, 0, 146, 0, 0, 0), ::capnp::word(29, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -4972,14 +4958,13 @@ pub mod type_ { } } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 98] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 97] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(112, 148, 53, 107, 90, 14, 28, 212), ::capnp::word(18, 0, 0, 0, 1, 0, 2, 0), ::capnp::word(0, 7, 151, 64, 46, 128, 246, 130), ::capnp::word(5, 0, 7, 0, 1, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(21, 0, 0, 0, 178, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -5275,14 +5260,13 @@ pub mod type_ { } } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 52] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 51] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(107, 183, 96, 119, 140, 121, 242, 130), ::capnp::word(18, 0, 0, 0, 1, 0, 2, 0), ::capnp::word(0, 7, 151, 64, 46, 128, 246, 130), ::capnp::word(5, 0, 7, 0, 1, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(21, 0, 0, 0, 170, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -5490,14 +5474,13 @@ pub mod type_ { impl Pipeline { } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 32] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 31] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(54, 132, 226, 31, 115, 14, 218, 204), ::capnp::word(18, 0, 0, 0, 1, 0, 2, 0), ::capnp::word(0, 7, 151, 64, 46, 128, 246, 130), ::capnp::word(5, 0, 7, 0, 1, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(21, 0, 0, 0, 178, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -5696,14 +5679,13 @@ pub mod type_ { impl Pipeline { } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 37] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 36] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(61, 216, 21, 128, 12, 226, 23, 140), ::capnp::word(18, 0, 0, 0, 1, 0, 2, 0), ::capnp::word(0, 7, 151, 64, 46, 128, 246, 130), ::capnp::word(5, 0, 7, 0, 1, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(21, 0, 0, 0, 194, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -5989,14 +5971,13 @@ pub mod value_constructor { } } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 81] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 80] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(28, 5, 251, 168, 241, 216, 198, 212), ::capnp::word(13, 0, 0, 0, 1, 0, 0, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(4, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(238, 10, 0, 0, 115, 11, 0, 0), ::capnp::word(21, 0, 0, 0, 242, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -6295,14 +6276,13 @@ pub mod publicity { impl Pipeline { } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 76] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 75] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(102, 28, 233, 33, 200, 211, 73, 197), ::capnp::word(13, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(1, 0, 7, 0, 0, 0, 3, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(117, 11, 0, 0, 228, 11, 0, 0), ::capnp::word(21, 0, 0, 0, 186, 0, 0, 0), ::capnp::word(29, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -6590,14 +6570,13 @@ pub mod implementations { impl Pipeline { } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 101] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 100] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(223, 160, 58, 118, 252, 159, 29, 155), ::capnp::word(13, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(0, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(230, 11, 0, 0, 144, 12, 0, 0), ::capnp::word(21, 0, 0, 0, 234, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -6865,6 +6844,7 @@ pub mod value_constructor_variant { self.builder.reborrow().get_pointer_field(2).clear(); self.builder.reborrow().get_pointer_field(3).clear(); self.builder.reborrow().get_pointer_field(4).clear(); + self.builder.reborrow().get_pointer_field(5).clear(); self.builder.into() } #[inline] @@ -6926,14 +6906,13 @@ pub mod value_constructor_variant { impl Pipeline { } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 46] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 45] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(26, 168, 208, 43, 233, 121, 76, 225), ::capnp::word(13, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(8, 0, 7, 0, 0, 0, 3, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(146, 12, 0, 0, 210, 15, 0, 0), ::capnp::word(21, 0, 0, 0, 42, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -7105,6 +7084,14 @@ pub mod value_constructor_variant { pub fn has_implementations(&self) -> bool { !self.reader.get_pointer_field(4).is_null() } + #[inline] + pub fn get_name(self) -> ::capnp::Result<::capnp::text::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(5), ::core::option::Option::None) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.reader.get_pointer_field(5).is_null() + } } pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> } @@ -7239,6 +7226,22 @@ pub mod value_constructor_variant { pub fn has_implementations(&self) -> bool { !self.builder.is_pointer_field_null(4) } + #[inline] + pub fn get_name(self) -> ::capnp::Result<::capnp::text::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(5), ::core::option::Option::None) + } + #[inline] + pub fn set_name(&mut self, value: impl ::capnp::traits::SetterInput<::capnp::text::Owned>) { + ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(5), value, false).unwrap() + } + #[inline] + pub fn init_name(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.get_pointer_field(5).init_text(size) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.builder.is_pointer_field_null(5) + } } pub struct Pipeline { _typeless: ::capnp::any_pointer::Pipeline } @@ -7259,18 +7262,17 @@ pub mod value_constructor_variant { } } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 99] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 113] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(208, 251, 150, 129, 105, 157, 121, 149), ::capnp::word(37, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(26, 168, 208, 43, 233, 121, 76, 225), ::capnp::word(8, 0, 7, 0, 1, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(21, 0, 0, 0, 162, 1, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(37, 0, 0, 0, 31, 1, 0, 0), + ::capnp::word(37, 0, 0, 0, 87, 1, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(115, 99, 104, 101, 109, 97, 46, 99), @@ -7280,42 +7282,49 @@ pub mod value_constructor_variant { ::capnp::word(105, 97, 110, 116, 46, 109, 111, 100), ::capnp::word(117, 108, 101, 67, 111, 110, 115, 116), ::capnp::word(97, 110, 116, 0, 0, 0, 0, 0), - ::capnp::word(20, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(24, 0, 0, 0, 3, 0, 4, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(125, 0, 0, 0, 66, 0, 0, 0), + ::capnp::word(153, 0, 0, 0, 66, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(120, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(132, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(148, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(160, 0, 0, 0, 2, 0, 1, 0), ::capnp::word(1, 0, 0, 0, 1, 0, 0, 0), ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(129, 0, 0, 0, 74, 0, 0, 0), + ::capnp::word(157, 0, 0, 0, 74, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(128, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(140, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(156, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(168, 0, 0, 0, 2, 0, 1, 0), ::capnp::word(2, 0, 0, 0, 2, 0, 0, 0), ::capnp::word(0, 0, 1, 0, 2, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(137, 0, 0, 0, 58, 0, 0, 0), + ::capnp::word(165, 0, 0, 0, 58, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(132, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(144, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(3, 0, 0, 0, 3, 0, 0, 0), + ::capnp::word(160, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(172, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(4, 0, 0, 0, 3, 0, 0, 0), ::capnp::word(0, 0, 1, 0, 14, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(141, 0, 0, 0, 114, 0, 0, 0), + ::capnp::word(169, 0, 0, 0, 114, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(140, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(152, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(4, 0, 0, 0, 4, 0, 0, 0), + ::capnp::word(168, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(180, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(5, 0, 0, 0, 4, 0, 0, 0), ::capnp::word(0, 0, 1, 0, 19, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(149, 0, 0, 0, 130, 0, 0, 0), + ::capnp::word(177, 0, 0, 0, 130, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(148, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(160, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(176, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(188, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(3, 0, 0, 0, 5, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 22, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(185, 0, 0, 0, 42, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(180, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(192, 0, 0, 0, 2, 0, 1, 0), ::capnp::word(108, 105, 116, 101, 114, 97, 108, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(106, 82, 109, 230, 111, 220, 234, 230), @@ -7359,6 +7368,14 @@ pub mod value_constructor_variant { ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(110, 97, 109, 101, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ]; pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { match index { @@ -7367,6 +7384,7 @@ pub mod value_constructor_variant { 2 => <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect(), 3 => <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect(), 4 => ::introspect(), + 5 => <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect(), _ => panic!("invalid field index {}", index), } } @@ -7379,9 +7397,9 @@ pub mod value_constructor_variant { members_by_discriminant: MEMBERS_BY_DISCRIMINANT, members_by_name: MEMBERS_BY_NAME, }; - pub static NONUNION_MEMBERS : &[u16] = &[0,1,2,3,4]; + pub static NONUNION_MEMBERS : &[u16] = &[0,1,2,3,4,5]; pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; - pub static MEMBERS_BY_NAME : &[u16] = &[3,4,0,1,2]; + pub static MEMBERS_BY_NAME : &[u16] = &[3,4,0,1,2,5]; pub const TYPE_ID: u64 = 0x9579_9d69_8196_fbd0; } } @@ -7731,14 +7749,13 @@ pub mod value_constructor_variant { } } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 198] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 197] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(121, 55, 113, 152, 197, 21, 166, 174), ::capnp::word(37, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(26, 168, 208, 43, 233, 121, 76, 225), ::capnp::word(8, 0, 7, 0, 1, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(21, 0, 0, 0, 114, 1, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -8249,14 +8266,13 @@ pub mod value_constructor_variant { } } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 159] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 158] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(213, 61, 35, 233, 38, 21, 11, 240), ::capnp::word(37, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(26, 168, 208, 43, 233, 121, 76, 225), ::capnp::word(8, 0, 7, 0, 1, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(21, 0, 0, 0, 98, 1, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -8614,14 +8630,13 @@ pub mod external { impl Pipeline { } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 49] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 48] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(236, 212, 23, 222, 114, 58, 95, 198), ::capnp::word(13, 0, 0, 0, 1, 0, 0, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(2, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(212, 15, 0, 0, 15, 16, 0, 0), ::capnp::word(21, 0, 0, 0, 178, 0, 0, 0), ::capnp::word(29, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -8838,14 +8853,13 @@ pub mod src_span { impl Pipeline { } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 48] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 47] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(176, 122, 119, 83, 72, 147, 59, 230), ::capnp::word(13, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(0, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(17, 16, 0, 0, 73, 16, 0, 0), ::capnp::word(21, 0, 0, 0, 170, 0, 0, 0), ::capnp::word(29, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -9049,14 +9063,13 @@ pub mod boxed_u_int16 { impl Pipeline { } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 34] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 33] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(206, 188, 213, 112, 115, 74, 121, 191), ::capnp::word(13, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(0, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(146, 16, 0, 0, 188, 16, 0, 0), ::capnp::word(21, 0, 0, 0, 202, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -9245,14 +9258,13 @@ pub mod boxed_u_int32 { impl Pipeline { } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 34] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 33] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(229, 125, 51, 241, 210, 87, 45, 136), ::capnp::word(13, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(0, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(5, 17, 0, 0, 47, 17, 0, 0), ::capnp::word(21, 0, 0, 0, 202, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -9465,14 +9477,13 @@ pub mod field_map { impl Pipeline { } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 64] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 63] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(69, 235, 12, 250, 24, 243, 166, 215), ::capnp::word(13, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(49, 17, 0, 0, 130, 17, 0, 0), ::capnp::word(21, 0, 0, 0, 178, 0, 0, 0), ::capnp::word(29, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -9915,14 +9926,13 @@ pub mod constant { impl Pipeline { } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 136] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 135] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(106, 82, 109, 230, 111, 220, 234, 230), ::capnp::word(13, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(4, 0, 7, 0, 0, 0, 9, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(132, 17, 0, 0, 189, 19, 0, 0), ::capnp::word(21, 0, 0, 0, 178, 0, 0, 0), ::capnp::word(29, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -10272,14 +10282,13 @@ pub mod constant { } } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 53] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 52] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(187, 26, 170, 149, 101, 60, 254, 232), ::capnp::word(22, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(106, 82, 109, 230, 111, 220, 234, 230), ::capnp::word(4, 0, 7, 0, 1, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(21, 0, 0, 0, 218, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -10551,14 +10560,13 @@ pub mod constant { } } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 67] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 66] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(28, 159, 252, 166, 123, 114, 181, 230), ::capnp::word(22, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(106, 82, 109, 230, 111, 220, 234, 230), ::capnp::word(4, 0, 7, 0, 1, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(21, 0, 0, 0, 234, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -10872,14 +10880,13 @@ pub mod constant { } } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 79] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 78] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(167, 2, 255, 44, 84, 233, 10, 203), ::capnp::word(22, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(106, 82, 109, 230, 111, 220, 234, 230), ::capnp::word(4, 0, 7, 0, 1, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(21, 0, 0, 0, 210, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -11158,14 +11165,13 @@ pub mod constant { } } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 50] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 49] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(61, 195, 0, 38, 129, 28, 187, 154), ::capnp::word(22, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(106, 82, 109, 230, 111, 220, 234, 230), ::capnp::word(4, 0, 7, 0, 1, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(21, 0, 0, 0, 82, 1, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -11438,14 +11444,13 @@ pub mod bit_array_segment { } } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 68] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 67] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(181, 42, 182, 217, 246, 199, 65, 197), ::capnp::word(13, 0, 0, 0, 1, 0, 0, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(3, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(191, 19, 0, 0, 43, 20, 0, 0), ::capnp::word(21, 0, 0, 0, 234, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -11916,14 +11921,13 @@ pub mod bit_array_segment_option { impl Pipeline { } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 265] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 264] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(84, 4, 149, 82, 63, 31, 245, 176), ::capnp::word(13, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(1, 0, 7, 0, 0, 0, 17, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(45, 20, 0, 0, 83, 22, 0, 0), ::capnp::word(21, 0, 0, 0, 26, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -12406,14 +12410,13 @@ pub mod bit_array_segment_option { } } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 50] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 49] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(20, 184, 71, 227, 143, 218, 2, 146), ::capnp::word(35, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(84, 4, 149, 82, 63, 31, 245, 176), ::capnp::word(1, 0, 7, 0, 1, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(21, 0, 0, 0, 66, 1, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -12631,14 +12634,13 @@ pub mod bit_array_segment_option { impl Pipeline { } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 50] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 49] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(94, 12, 190, 163, 221, 253, 125, 207), ::capnp::word(35, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(84, 4, 149, 82, 63, 31, 245, 176), ::capnp::word(1, 0, 7, 0, 1, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(21, 0, 0, 0, 66, 1, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -12869,14 +12871,13 @@ pub mod line_numbers { impl Pipeline { } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 54] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + pub static ENCODED_NODE: [::capnp::Word; 53] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(101, 33, 49, 62, 78, 11, 246, 235), ::capnp::word(13, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(85, 22, 0, 0, 159, 22, 0, 0), ::capnp::word(21, 0, 0, 0, 202, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), diff --git a/compiler-core/schema.capnp b/compiler-core/schema.capnp index 91a6b14a629..bd62cb645f7 100644 --- a/compiler-core/schema.capnp +++ b/compiler-core/schema.capnp @@ -161,6 +161,7 @@ struct ValueConstructorVariant { literal @0 :Constant; location @1 :SrcSpan; module @2 :Text; + name @22 :Text; documentation @14 :Text; implementations @19 :Implementations; } diff --git a/compiler-core/src/analyse.rs b/compiler-core/src/analyse.rs index 511e0878a4f..91adfd3ff9d 100644 --- a/compiler-core/src/analyse.rs +++ b/compiler-core/src/analyse.rs @@ -411,6 +411,7 @@ impl<'a, A> ModuleAnalyzer<'a, A> { location, literal: typed_expr.clone(), module: self.module_name.clone(), + name: name.clone(), implementations, }, type_: type_.clone(), @@ -1646,6 +1647,7 @@ fn generalise_module_constant( literal: *value.clone(), module: module_name.clone(), implementations, + name: name.clone(), }; environment.insert_variable( name.clone(), diff --git a/compiler-core/src/analyse/imports.rs b/compiler-core/src/analyse/imports.rs index 603d3beaa20..36d641bb113 100644 --- a/compiler-core/src/analyse/imports.rs +++ b/compiler-core/src/analyse/imports.rs @@ -171,8 +171,11 @@ impl<'context, 'problems> Importer<'context, 'problems> { name.clone(), used_name.clone(), ); - self.environment - .register_reference(module.clone(), import_name.clone(), location); + self.environment.register_reference( + module.clone(), + import_name.clone(), + import.imported_name_location, + ); } ValueConstructorVariant::ModuleConstant { module, .. } | ValueConstructorVariant::ModuleFn { module, .. } => { @@ -182,8 +185,11 @@ impl<'context, 'problems> Importer<'context, 'problems> { location, self.problems, ); - self.environment - .register_reference(module.clone(), import_name.clone(), location); + self.environment.register_reference( + module.clone(), + import_name.clone(), + import.imported_name_location, + ); } _ => self.environment.init_usage( used_name.clone(), diff --git a/compiler-core/src/ast.rs b/compiler-core/src/ast.rs index 1795e3d4a0f..221c773f252 100644 --- a/compiler-core/src/ast.rs +++ b/compiler-core/src/ast.rs @@ -1086,6 +1086,8 @@ impl Definition { #[derive(Debug, Clone, PartialEq, Eq)] pub struct UnqualifiedImport { pub location: SrcSpan, + /// The location excluding the potential `as ...` clause, or the `type` keyword + pub imported_name_location: SrcSpan, pub name: EcoString, pub as_name: Option, } diff --git a/compiler-core/src/metadata/module_decoder.rs b/compiler-core/src/metadata/module_decoder.rs index b85936c38d3..5884e5b4eb9 100755 --- a/compiler-core/src/metadata/module_decoder.rs +++ b/compiler-core/src/metadata/module_decoder.rs @@ -527,6 +527,7 @@ impl ModuleDecoder { location: self.src_span(&reader.get_location()?)?, literal: self.constant(&reader.get_literal()?)?, module: self.string(reader.get_module()?)?, + name: self.string(reader.get_name()?)?, implementations: self.implementations(reader.get_implementations()?), }) } diff --git a/compiler-core/src/metadata/module_encoder.rs b/compiler-core/src/metadata/module_encoder.rs index b3c15f0dcc0..e5bf4c44491 100644 --- a/compiler-core/src/metadata/module_encoder.rs +++ b/compiler-core/src/metadata/module_encoder.rs @@ -336,12 +336,14 @@ impl<'a> ModuleEncoder<'a> { module, documentation: doc, implementations, + name, } => { let mut builder = builder.init_module_constant(); builder.set_documentation(doc.as_ref().map(EcoString::as_str).unwrap_or_default()); self.build_src_span(builder.reborrow().init_location(), *location); self.build_constant(builder.reborrow().init_literal(), literal); builder.reborrow().set_module(module); + builder.reborrow().set_name(name); self.build_implementations(builder.init_implementations(), *implementations) } diff --git a/compiler-core/src/metadata/tests.rs b/compiler-core/src/metadata/tests.rs index 98fa95f8303..23383fa58c3 100644 --- a/compiler-core/src/metadata/tests.rs +++ b/compiler-core/src/metadata/tests.rs @@ -57,6 +57,7 @@ fn constant_module(constant: TypedConstant) -> ModuleInterface { can_run_on_erlang: true, can_run_on_javascript: true, }, + name: "one".into(), }, }, )] @@ -1120,6 +1121,7 @@ fn constant_var() { can_run_on_erlang: true, can_run_on_javascript: true, }, + name: "one_original".into(), }, })), }; @@ -1152,6 +1154,7 @@ fn constant_var() { can_run_on_erlang: true, can_run_on_javascript: true, }, + name: "one".into(), }, }, ), @@ -1173,6 +1176,7 @@ fn constant_var() { can_run_on_erlang: true, can_run_on_javascript: true, }, + name: "one_original".into(), }, }, ), diff --git a/compiler-core/src/parse.rs b/compiler-core/src/parse.rs index 78a0be3748a..4cb8aebc342 100644 --- a/compiler-core/src/parse.rs +++ b/compiler-core/src/parse.rs @@ -2724,6 +2724,7 @@ where let mut import = UnqualifiedImport { name, location, + imported_name_location: location, as_name: None, }; if self.maybe_one(&Token::As).is_some() { @@ -2740,6 +2741,7 @@ where let mut import = UnqualifiedImport { name, location, + imported_name_location: location, as_name: None, }; if self.maybe_one(&Token::As).is_some() { @@ -2752,11 +2754,12 @@ where Some((start, Token::Type, _)) => { self.advance(); - let (_, name, end) = self.expect_upname()?; + let (name_start, name, end) = self.expect_upname()?; let location = SrcSpan { start, end }; let mut import = UnqualifiedImport { name, location, + imported_name_location: SrcSpan::new(name_start, end), as_name: None, }; if self.maybe_one(&Token::As).is_some() { diff --git a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__import_type.snap b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__import_type.snap index cd08720c9dd..9e7cef8413b 100644 --- a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__import_type.snap +++ b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__import_type.snap @@ -24,6 +24,10 @@ Parsed { start: 28, end: 34, }, + imported_name_location: SrcSpan { + start: 28, + end: 34, + }, name: "Wobble", as_name: None, }, @@ -34,6 +38,10 @@ Parsed { start: 15, end: 26, }, + imported_name_location: SrcSpan { + start: 20, + end: 26, + }, name: "Wobble", as_name: None, }, @@ -42,6 +50,10 @@ Parsed { start: 36, end: 47, }, + imported_name_location: SrcSpan { + start: 41, + end: 47, + }, name: "Wabble", as_name: None, }, diff --git a/compiler-core/src/type_.rs b/compiler-core/src/type_.rs index 05f828e7ba7..8471753a05e 100644 --- a/compiler-core/src/type_.rs +++ b/compiler-core/src/type_.rs @@ -630,6 +630,7 @@ pub enum ValueConstructorVariant { documentation: Option, location: SrcSpan, module: EcoString, + name: EcoString, literal: Constant, EcoString>, implementations: Implementations, }, diff --git a/compiler-core/src/type_/environment.rs b/compiler-core/src/type_/environment.rs index 016f51e6ec8..c5768f27a65 100644 --- a/compiler-core/src/type_/environment.rs +++ b/compiler-core/src/type_/environment.rs @@ -126,6 +126,7 @@ impl<'a> Environment<'a> { echo_found: false, references: HashMap::new(), } + } } #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/compiler-core/src/type_/expression.rs b/compiler-core/src/type_/expression.rs index bbc60b84643..6e90c9f646c 100644 --- a/compiler-core/src/type_/expression.rs +++ b/compiler-core/src/type_/expression.rs @@ -2342,12 +2342,10 @@ impl<'a, 'b> ExprTyper<'a, 'b> { match &constructor.variant { ValueConstructorVariant::ModuleFn { name, module, .. } - | ValueConstructorVariant::Record { name, module, .. } => self + | ValueConstructorVariant::Record { name, module, .. } + | ValueConstructorVariant::ModuleConstant { name, module, .. } => self .environment .register_reference(module.clone(), name.clone(), select_location), - ValueConstructorVariant::ModuleConstant { module, .. } => self - .environment - .register_reference(module.clone(), label.clone(), select_location), ValueConstructorVariant::LocalVariable { .. } | ValueConstructorVariant::LocalConstant { .. } => {} } @@ -2929,11 +2927,21 @@ impl<'a, 'b> ExprTyper<'a, 'b> { self.narrow_implementations(*location, &variant)?; match &variant { + // If the referenced name is different to the name of the original + // value, that means we are referencing it via an alias and don't + // want to track this reference. + ValueConstructorVariant::ModuleFn { + name: value_name, .. + } + | ValueConstructorVariant::Record { + name: value_name, .. + } + | ValueConstructorVariant::ModuleConstant { + name: value_name, .. + } if module.is_none() && value_name != name => {} ValueConstructorVariant::ModuleFn { name, module, .. } - | ValueConstructorVariant::Record { name, module, .. } => self - .environment - .register_reference(module.clone(), name.clone(), *location), - ValueConstructorVariant::ModuleConstant { module, .. } => self + | ValueConstructorVariant::Record { name, module, .. } + | ValueConstructorVariant::ModuleConstant { name, module, .. } => self .environment .register_reference(module.clone(), name.clone(), *location), ValueConstructorVariant::LocalVariable { .. } diff --git a/compiler-core/src/type_/tests.rs b/compiler-core/src/type_/tests.rs index dcd572ac894..271d40cf7d6 100644 --- a/compiler-core/src/type_/tests.rs +++ b/compiler-core/src/type_/tests.rs @@ -2742,6 +2742,7 @@ fn assert_suitable_main_function_not_module_function() { can_run_on_erlang: true, can_run_on_javascript: true, }, + name: "main".into(), }, }; assert!(assert_suitable_main_function(&value, &"module".into(), Target::Erlang).is_err(),); From 426cd381874a97a06062ab448de31b504f3117ac Mon Sep 17 00:00:00 2001 From: GearsDatapacks Date: Wed, 26 Feb 2025 14:44:37 +0000 Subject: [PATCH 17/27] Fix from_file_path for wasm --- compiler-core/src/language_server/rename.rs | 25 ++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/compiler-core/src/language_server/rename.rs b/compiler-core/src/language_server/rename.rs index a360dd84a30..a85aaaa88e7 100644 --- a/compiler-core/src/language_server/rename.rs +++ b/compiler-core/src/language_server/rename.rs @@ -128,7 +128,7 @@ fn rename_references_in_module( .iter() .for_each(|location| edits.replace(*location, new_name.clone())); - let Ok(uri) = Url::from_file_path(&module.input_path) else { + let Some(uri) = url_from_path(module.input_path.as_str()) else { return; }; @@ -138,6 +138,29 @@ fn rename_references_in_module( .map(|changes| changes.insert(uri, edits.edits)); } +fn url_from_path(path: &str) -> Option { + // The targets for which `from_file_path` is defined + #[cfg(any( + unix, + windows, + target_os = "redox", + target_os = "wasi", + target_os = "hermit" + ))] + let uri = Url::from_file_path(path).ok(); + + #[cfg(not(any( + unix, + windows, + target_os = "redox", + target_os = "wasi", + target_os = "hermit" + )))] + let uri = Url::parse(&format!("file://{path}")).ok(); + + uri +} + pub fn find_variable_references( module: &TypedModule, definition_location: SrcSpan, From c59b29c6b706eae044d89a765bf9110991766181 Mon Sep 17 00:00:00 2001 From: GearsDatapacks Date: Wed, 26 Feb 2025 18:06:49 +0000 Subject: [PATCH 18/27] Add tests --- .../src/language_server/tests/rename.rs | 514 +++++++++++++++++- ...ests__rename__rename_aliased_constant.snap | 41 ++ ...ests__rename__rename_aliased_function.snap | 45 ++ ...__rename__rename_aliased_type_variant.snap | 45 ++ ...name__rename_constant_from_definition.snap | 41 ++ ...ame_constant_from_qualified_reference.snap | 41 ++ ...ename__rename_constant_from_reference.snap | 41 ++ ...e_constant_from_unqualified_reference.snap | 41 ++ ...ame__rename_constant_shadowing_module.snap | 28 + ...name__rename_function_from_definition.snap | 45 ++ ...ame_function_from_qualified_reference.snap | 37 ++ ...ename__rename_function_from_reference.snap | 45 ++ ...e_function_from_unqualified_reference.snap | 39 ++ ...ame__rename_function_shadowing_module.snap | 32 ++ ...__rename_type_variant_from_definition.snap | 45 ++ ...type_variant_from_qualified_reference.snap | 45 ++ ...e__rename_type_variant_from_reference.snap | 45 ++ 17 files changed, 1159 insertions(+), 11 deletions(-) create mode 100644 compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_aliased_constant.snap create mode 100644 compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_aliased_function.snap create mode 100644 compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_aliased_type_variant.snap create mode 100644 compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_from_definition.snap create mode 100644 compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_from_qualified_reference.snap create mode 100644 compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_from_reference.snap create mode 100644 compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_from_unqualified_reference.snap create mode 100644 compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_shadowing_module.snap create mode 100644 compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_from_definition.snap create mode 100644 compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_from_qualified_reference.snap create mode 100644 compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_from_reference.snap create mode 100644 compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_from_unqualified_reference.snap create mode 100644 compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_shadowing_module.snap create mode 100644 compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_type_variant_from_definition.snap create mode 100644 compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_type_variant_from_qualified_reference.snap create mode 100644 compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_type_variant_from_reference.snap diff --git a/compiler-core/src/language_server/tests/rename.rs b/compiler-core/src/language_server/tests/rename.rs index 633a818aec5..7057277228c 100644 --- a/compiler-core/src/language_server/tests/rename.rs +++ b/compiler-core/src/language_server/tests/rename.rs @@ -33,11 +33,11 @@ fn rename( } fn apply_rename( - tester: TestProject<'_>, + tester: &TestProject<'_>, new_name: &str, position: Position, ) -> HashMap { - let changes = rename(&tester, new_name, position) + let changes = rename(tester, new_name, position) .expect("Rename failed") .changes .expect("No text edit found"); @@ -45,7 +45,7 @@ fn apply_rename( } fn apply_code_edit( - tester: TestProject<'_>, + tester: &TestProject<'_>, changes: HashMap>, ) -> HashMap { let mut modules = HashMap::new(); @@ -61,26 +61,48 @@ fn apply_code_edit( macro_rules! assert_rename { ($code:literal, $new_name:literal, $range:expr $(,)?) => { - let project = TestProject::for_source($code); - assert_rename!(project, $new_name, $range); + assert_rename!(TestProject::for_source($code), $new_name, $range); + }; + + (($module_name:literal, $module_src:literal), $code:literal, $new_name:literal, $range:expr $(,)?) => { + assert_rename!( + TestProject::for_source($code).add_module($module_name, $module_src), + $new_name, + $range + ); }; ($project:expr, $new_name:literal, $range:expr $(,)?) => { - let src = $project.src; + let project = $project; + let src = project.src; let range = $range.find_range(src); + let result = apply_rename(&project, $new_name, range.start); + let mut output = String::from("----- BEFORE RENAME\n"); - for (name, src) in $project.root_package_modules.iter() { + for (name, src) in project.root_package_modules.iter() { output.push_str(&format!("-- {name}.gleam\n{src}\n\n")); } output.push_str(&format!( "-- app.gleam\n{}\n\n----- AFTER RENAME\n", hover::show_hover(src, range, range.start) )); - - let result = apply_rename($project, $new_name, range.start); - for (name, src) in result { - output.push_str(&format!("-- {name}.gleam\n{}\n\n", src)); + for (name, src) in project.root_package_modules.iter() { + output.push_str(&format!( + "-- {name}.gleam\n{}\n\n", + result + .get(*name) + .map(|string| string.as_str()) + .unwrap_or(*src) + )); } + output.push_str(&format!( + "-- app.gleam\n{}", + result + .get("app") + .map(|string| string.as_str()) + .unwrap_or(src) + )); + insta::assert_snapshot!(insta::internals::AutoName, output, src); }; } @@ -359,3 +381,473 @@ pub fn main() { find_position_of("wibble").nth_occurrence(2).to_selection() ); } + +#[test] +fn rename_function_from_definition() { + assert_rename!( + ( + "mod", + " +import app + +fn wibble() { + app.something() +} +" + ), + " +pub fn something() { + something() +} + +fn something_else() { + something() +} +", + "some_function", + find_position_of("something").to_selection() + ); +} + +#[test] +fn rename_function_from_reference() { + assert_rename!( + ( + "mod", + " +import app + +fn wibble() { + app.something() +} +" + ), + " +pub fn something() { + something() +} + +fn something_else() { + something() +} +", + "some_function", + find_position_of("something") + .nth_occurrence(2) + .to_selection() + ); +} + +#[test] +fn rename_function_from_qualified_reference() { + assert_rename!( + ( + "mod", + " +pub fn wibble() { + wibble() +} +" + ), + " +import mod + +pub fn main() { + mod.wibble() +} +", + "some_function", + find_position_of("wibble").to_selection() + ); +} + +#[test] +fn rename_function_from_unqualified_reference() { + assert_rename!( + ( + "mod", + " +pub fn wibble() { + wibble() +} +" + ), + " +import mod.{wibble} + +pub fn main() { + wibble() + mod.wibble() +} +", + "some_function", + find_position_of("wibble(").to_selection() + ); +} + +#[test] +fn rename_aliased_function() { + assert_rename!( + ( + "mod", + " +import app.{something as something_else} + +fn wibble() { + something_else() +} +" + ), + " +pub fn something() { + something() +} + +fn something_else() { + something() +} +", + "some_function", + find_position_of("something").to_selection() + ); +} + +#[test] +fn rename_function_shadowing_module() { + let src = " +import gleam/list + +pub fn list() { + [] +} + +pub fn main() { + list.map(todo, todo) +} + "; + + assert_rename!( + TestProject::for_source(src).add_hex_module("gleam/list", "pub fn map(_, _) {}"), + "empty_list", + find_position_of("list()").to_selection() + ); +} + +#[test] +fn no_rename_function_with_invalid_name() { + assert_no_rename!( + " +pub fn main() { + let wibble = 10 + wibble +} +", + "Not_AValid_Name", + find_position_of("main").to_selection() + ); +} + +#[test] +fn rename_constant_from_definition() { + assert_rename!( + ( + "mod", + " +import app + +fn wibble() { + app.something +} +" + ), + " +pub const something = 10 + +pub fn main() { + something + { 4 * something } +} +", + "ten", + find_position_of("something").to_selection() + ); +} + +#[test] +fn rename_constant_from_reference() { + assert_rename!( + ( + "mod", + " +import app + +fn wibble() { + app.something +} +" + ), + " +pub const something = 10 + +pub fn main() { + something + { 4 * something } +} +", + "ten", + find_position_of("something") + .nth_occurrence(2) + .to_selection() + ); +} + +#[test] +fn rename_constant_from_qualified_reference() { + assert_rename!( + ( + "mod", + " +pub const something = 10 + +fn wibble() { + something +} +" + ), + " +import mod + +pub fn main() { + mod.something +} +", + "ten", + find_position_of("something").to_selection() + ); +} + +#[test] +fn rename_constant_from_unqualified_reference() { + assert_rename!( + ( + "mod", + " +pub const something = 10 + +fn wibble() { + something +} +" + ), + " +import mod.{something} + +pub fn main() { + something + mod.something +} +", + "ten", + find_position_of("something +").to_selection() + ); +} + +#[test] +fn rename_aliased_constant() { + assert_rename!( + ( + "mod", + " +import app.{something as some_constant} + +fn wibble() { + some_constant +} +" + ), + " +pub const something = 10 + +pub fn main() { + something + { 4 * something } +} +", + "ten", + find_position_of("something").to_selection() + ); +} + +#[test] +fn rename_constant_shadowing_module() { + let src = " +import gleam/list + +const list = [] + +pub fn main() { + list.map(todo, todo) +} + "; + + assert_rename!( + TestProject::for_source(src).add_hex_module("gleam/list", "pub fn map(_, _) {}"), + "empty_list", + find_position_of("list =").to_selection() + ); +} + +#[test] +fn no_rename_constant_with_invalid_name() { + assert_no_rename!( + " +const value = 10 +", + "Ten", + find_position_of("value").to_selection() + ); +} + +#[test] +fn rename_type_variant_from_definition() { + assert_rename!( + ( + "mod", + " +import app + +fn wibble() { + app.Constructor(4) +} +" + ), + " +pub type Wibble { + Constructor(Int) +} + +pub fn main() { + Constructor(10) +} +", + "Wibble", + find_position_of("Constructor(Int").to_selection() + ); +} + +#[test] +fn rename_type_variant_from_reference() { + assert_rename!( + ( + "mod", + " +import app + +fn wibble() { + app.Constructor(4) +} +" + ), + " +pub type Wibble { + Constructor(Int) +} + +pub fn main() { + Constructor(10) +} +", + "Wibble", + find_position_of("Constructor(10").to_selection() + ); +} + +#[test] +fn rename_type_variant_from_qualified_reference() { + assert_rename!( + ( + "mod", + " +pub type Wibble { + Constructor(Int) +} + +fn wibble() { + Constructor(42) +} +" + ), + " +import mod + +pub fn main() { + mod.Constructor +} +", + "Variant", + find_position_of("Constructor").to_selection() + ); +} + +#[test] +fn rename_type_variant_from_unqualified_reference() { + assert_rename!( + ( + "mod", + " +pub type Wibble { + Constructor(Int) +} + +fn wibble() { + Constructor(81) +} +" + ), + " +import mod.{Constructor} + +pub fn main() { + #(Constructor(75), mod.Constructor(57)) +} +", + "Number", + find_position_of("Constructor,").to_selection() + ); +} + +#[test] +fn rename_aliased_type_variant() { + assert_rename!( + ( + "mod", + " +import app.{Constructor as ValueConstructor} + +fn wibble() { + ValueConstructor(172) +} +" + ), + " +pub type Wibble { + Constructor(Int) +} + +pub fn main() { + Constructor(42) +} +", + "MakeAWibble", + find_position_of("Constructor").to_selection() + ); +} + +#[test] +fn no_rename_type_variant_with_invalid_name() { + assert_no_rename!( + " +pub type Wibble { + Constructor(Int) +} +", + "name_in_snake_case", + find_position_of("Constructor").to_selection() + ); +} diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_aliased_constant.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_aliased_constant.snap new file mode 100644 index 00000000000..607d64d6ded --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_aliased_constant.snap @@ -0,0 +1,41 @@ +--- +source: compiler-core/src/language_server/tests/rename.rs +expression: "\npub const something = 10\n\npub fn main() {\n something + { 4 * something }\n}\n" +--- +----- BEFORE RENAME +-- mod.gleam + +import app.{something as some_constant} + +fn wibble() { + some_constant +} + + +-- app.gleam + +pub const something = 10 + ↑ + +pub fn main() { + something + { 4 * something } +} + + +----- AFTER RENAME +-- mod.gleam + +import app.{ten as some_constant} + +fn wibble() { + some_constant +} + + +-- app.gleam + +pub const ten = 10 + +pub fn main() { + ten + { 4 * ten } +} diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_aliased_function.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_aliased_function.snap new file mode 100644 index 00000000000..20ece8890d2 --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_aliased_function.snap @@ -0,0 +1,45 @@ +--- +source: compiler-core/src/language_server/tests/rename.rs +expression: "\npub fn something() {\n something()\n}\n\nfn something_else() {\n something()\n}\n" +--- +----- BEFORE RENAME +-- mod.gleam + +import app.{something as something_else} + +fn wibble() { + something_else() +} + + +-- app.gleam + +pub fn something() { + ↑ + something() +} + +fn something_else() { + something() +} + + +----- AFTER RENAME +-- mod.gleam + +import app.{some_function as something_else} + +fn wibble() { + something_else() +} + + +-- app.gleam + +pub fn some_function() { + some_function() +} + +fn something_else() { + some_function() +} diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_aliased_type_variant.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_aliased_type_variant.snap new file mode 100644 index 00000000000..efd6a4f7094 --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_aliased_type_variant.snap @@ -0,0 +1,45 @@ +--- +source: compiler-core/src/language_server/tests/rename.rs +expression: "\npub type Wibble {\n Constructor(Int)\n}\n\npub fn main() {\n Constructor(42)\n}\n" +--- +----- BEFORE RENAME +-- mod.gleam + +import app.{Constructor as ValueConstructor} + +fn wibble() { + ValueConstructor(172) +} + + +-- app.gleam + +pub type Wibble { + Constructor(Int) + ↑ +} + +pub fn main() { + Constructor(42) +} + + +----- AFTER RENAME +-- mod.gleam + +import app.{MakeAWibble as ValueConstructor} + +fn wibble() { + ValueConstructor(172) +} + + +-- app.gleam + +pub type Wibble { + MakeAWibble(Int) +} + +pub fn main() { + MakeAWibble(42) +} diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_from_definition.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_from_definition.snap new file mode 100644 index 00000000000..befafaac34e --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_from_definition.snap @@ -0,0 +1,41 @@ +--- +source: compiler-core/src/language_server/tests/rename.rs +expression: "\npub const something = 10\n\npub fn main() {\n something + { 4 * something }\n}\n" +--- +----- BEFORE RENAME +-- mod.gleam + +import app + +fn wibble() { + app.something +} + + +-- app.gleam + +pub const something = 10 + ↑ + +pub fn main() { + something + { 4 * something } +} + + +----- AFTER RENAME +-- mod.gleam + +import app + +fn wibble() { + app.ten +} + + +-- app.gleam + +pub const ten = 10 + +pub fn main() { + ten + { 4 * ten } +} diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_from_qualified_reference.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_from_qualified_reference.snap new file mode 100644 index 00000000000..ad52109ad3a --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_from_qualified_reference.snap @@ -0,0 +1,41 @@ +--- +source: compiler-core/src/language_server/tests/rename.rs +expression: "\nimport mod\n\npub fn main() {\n mod.something\n}\n" +--- +----- BEFORE RENAME +-- mod.gleam + +pub const something = 10 + +fn wibble() { + something +} + + +-- app.gleam + +import mod + +pub fn main() { + mod.something + ↑ +} + + +----- AFTER RENAME +-- mod.gleam + +pub const ten = 10 + +fn wibble() { + ten +} + + +-- app.gleam + +import mod + +pub fn main() { + mod.ten +} diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_from_reference.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_from_reference.snap new file mode 100644 index 00000000000..703f23342ef --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_from_reference.snap @@ -0,0 +1,41 @@ +--- +source: compiler-core/src/language_server/tests/rename.rs +expression: "\npub const something = 10\n\npub fn main() {\n something + { 4 * something }\n}\n" +--- +----- BEFORE RENAME +-- mod.gleam + +import app + +fn wibble() { + app.something +} + + +-- app.gleam + +pub const something = 10 + +pub fn main() { + something + { 4 * something } + ↑ +} + + +----- AFTER RENAME +-- mod.gleam + +import app + +fn wibble() { + app.ten +} + + +-- app.gleam + +pub const ten = 10 + +pub fn main() { + ten + { 4 * ten } +} diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_from_unqualified_reference.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_from_unqualified_reference.snap new file mode 100644 index 00000000000..698044aaefa --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_from_unqualified_reference.snap @@ -0,0 +1,41 @@ +--- +source: compiler-core/src/language_server/tests/rename.rs +expression: "\nimport mod.{something}\n\npub fn main() {\n something + mod.something\n}\n" +--- +----- BEFORE RENAME +-- mod.gleam + +pub const something = 10 + +fn wibble() { + something +} + + +-- app.gleam + +import mod.{something} + +pub fn main() { + something + mod.something + ↑ +} + + +----- AFTER RENAME +-- mod.gleam + +pub const ten = 10 + +fn wibble() { + ten +} + + +-- app.gleam + +import mod.{ten} + +pub fn main() { + ten + mod.ten +} diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_shadowing_module.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_shadowing_module.snap new file mode 100644 index 00000000000..835d9242037 --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_shadowing_module.snap @@ -0,0 +1,28 @@ +--- +source: compiler-core/src/language_server/tests/rename.rs +expression: "\nimport gleam/list\n\nconst list = []\n\npub fn main() {\n list.map(todo, todo)\n}\n " +--- +----- BEFORE RENAME +-- app.gleam + +import gleam/list + +const list = [] + ↑ + +pub fn main() { + list.map(todo, todo) +} + + + +----- AFTER RENAME +-- app.gleam + +import gleam/list + +const empty_list = [] + +pub fn main() { + list.map(todo, todo) +} diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_from_definition.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_from_definition.snap new file mode 100644 index 00000000000..7eb7a28fe60 --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_from_definition.snap @@ -0,0 +1,45 @@ +--- +source: compiler-core/src/language_server/tests/rename.rs +expression: "\npub fn something() {\n something()\n}\n\nfn something_else() {\n something()\n}\n" +--- +----- BEFORE RENAME +-- mod.gleam + +import app + +fn wibble() { + app.something() +} + + +-- app.gleam + +pub fn something() { + ↑ + something() +} + +fn something_else() { + something() +} + + +----- AFTER RENAME +-- mod.gleam + +import app + +fn wibble() { + app.some_function() +} + + +-- app.gleam + +pub fn some_function() { + some_function() +} + +fn something_else() { + some_function() +} diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_from_qualified_reference.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_from_qualified_reference.snap new file mode 100644 index 00000000000..4a0e163d1fd --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_from_qualified_reference.snap @@ -0,0 +1,37 @@ +--- +source: compiler-core/src/language_server/tests/rename.rs +expression: "\nimport mod\n\npub fn main() {\n mod.wibble()\n}\n" +--- +----- BEFORE RENAME +-- mod.gleam + +pub fn wibble() { + wibble() +} + + +-- app.gleam + +import mod + +pub fn main() { + mod.wibble() + ↑ +} + + +----- AFTER RENAME +-- mod.gleam + +pub fn some_function() { + some_function() +} + + +-- app.gleam + +import mod + +pub fn main() { + mod.some_function() +} diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_from_reference.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_from_reference.snap new file mode 100644 index 00000000000..e60f01e14d3 --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_from_reference.snap @@ -0,0 +1,45 @@ +--- +source: compiler-core/src/language_server/tests/rename.rs +expression: "\npub fn something() {\n something()\n}\n\nfn something_else() {\n something()\n}\n" +--- +----- BEFORE RENAME +-- mod.gleam + +import app + +fn wibble() { + app.something() +} + + +-- app.gleam + +pub fn something() { + something() + ↑ +} + +fn something_else() { + something() +} + + +----- AFTER RENAME +-- mod.gleam + +import app + +fn wibble() { + app.some_function() +} + + +-- app.gleam + +pub fn some_function() { + some_function() +} + +fn something_else() { + some_function() +} diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_from_unqualified_reference.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_from_unqualified_reference.snap new file mode 100644 index 00000000000..b63422ad5e6 --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_from_unqualified_reference.snap @@ -0,0 +1,39 @@ +--- +source: compiler-core/src/language_server/tests/rename.rs +expression: "\nimport mod.{wibble}\n\npub fn main() {\n wibble()\n mod.wibble()\n}\n" +--- +----- BEFORE RENAME +-- mod.gleam + +pub fn wibble() { + wibble() +} + + +-- app.gleam + +import mod.{wibble} + +pub fn main() { + wibble() + ↑ + mod.wibble() +} + + +----- AFTER RENAME +-- mod.gleam + +pub fn some_function() { + some_function() +} + + +-- app.gleam + +import mod.{some_function} + +pub fn main() { + some_function() + mod.some_function() +} diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_shadowing_module.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_shadowing_module.snap new file mode 100644 index 00000000000..44cdbbc5093 --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_shadowing_module.snap @@ -0,0 +1,32 @@ +--- +source: compiler-core/src/language_server/tests/rename.rs +expression: "\nimport gleam/list\n\npub fn list() {\n []\n}\n\npub fn main() {\n list.map(todo, todo)\n}\n " +--- +----- BEFORE RENAME +-- app.gleam + +import gleam/list + +pub fn list() { + ↑ + [] +} + +pub fn main() { + list.map(todo, todo) +} + + + +----- AFTER RENAME +-- app.gleam + +import gleam/list + +pub fn empty_list() { + [] +} + +pub fn main() { + list.map(todo, todo) +} diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_type_variant_from_definition.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_type_variant_from_definition.snap new file mode 100644 index 00000000000..9d9a670c436 --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_type_variant_from_definition.snap @@ -0,0 +1,45 @@ +--- +source: compiler-core/src/language_server/tests/rename.rs +expression: "\npub type Wibble {\n Constructor(Int)\n}\n\npub fn main() {\n Constructor(10)\n}\n" +--- +----- BEFORE RENAME +-- mod.gleam + +import app + +fn wibble() { + app.Constructor(4) +} + + +-- app.gleam + +pub type Wibble { + Constructor(Int) + ↑ +} + +pub fn main() { + Constructor(10) +} + + +----- AFTER RENAME +-- mod.gleam + +import app + +fn wibble() { + app.Wibble(4) +} + + +-- app.gleam + +pub type Wibble { + Wibble(Int) +} + +pub fn main() { + Wibble(10) +} diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_type_variant_from_qualified_reference.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_type_variant_from_qualified_reference.snap new file mode 100644 index 00000000000..a3644bfa41b --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_type_variant_from_qualified_reference.snap @@ -0,0 +1,45 @@ +--- +source: compiler-core/src/language_server/tests/rename.rs +expression: "\nimport mod\n\npub fn main() {\n mod.Constructor\n}\n" +--- +----- BEFORE RENAME +-- mod.gleam + +pub type Wibble { + Constructor(Int) +} + +fn wibble() { + Constructor(42) +} + + +-- app.gleam + +import mod + +pub fn main() { + mod.Constructor + ↑ +} + + +----- AFTER RENAME +-- mod.gleam + +pub type Wibble { + Variant(Int) +} + +fn wibble() { + Variant(42) +} + + +-- app.gleam + +import mod + +pub fn main() { + mod.Variant +} diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_type_variant_from_reference.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_type_variant_from_reference.snap new file mode 100644 index 00000000000..286465c7c32 --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_type_variant_from_reference.snap @@ -0,0 +1,45 @@ +--- +source: compiler-core/src/language_server/tests/rename.rs +expression: "\npub type Wibble {\n Constructor(Int)\n}\n\npub fn main() {\n Constructor(10)\n}\n" +--- +----- BEFORE RENAME +-- mod.gleam + +import app + +fn wibble() { + app.Constructor(4) +} + + +-- app.gleam + +pub type Wibble { + Constructor(Int) +} + +pub fn main() { + Constructor(10) + ↑ +} + + +----- AFTER RENAME +-- mod.gleam + +import app + +fn wibble() { + app.Wibble(4) +} + + +-- app.gleam + +pub type Wibble { + Wibble(Int) +} + +pub fn main() { + Wibble(10) +} From 4d98cc9cc2d41945ec2d3151199a03b6672218f4 Mon Sep 17 00:00:00 2001 From: GearsDatapacks Date: Fri, 28 Feb 2025 20:22:56 +0000 Subject: [PATCH 19/27] Fix bug with module access shadowing --- .../src/language_server/tests/rename.rs | 56 ++++++- ...ame_constant_shadowed_by_field_access.snap | 43 +++++ ...ame__rename_constant_shadowing_module.snap | 4 +- ...ame_function_shadowed_by_field_access.snap | 47 ++++++ ...ame__rename_function_shadowing_module.snap | 4 +- ...pe_variant_from_unqualified_reference.snap | 45 +++++ compiler-core/src/type_/expression.rs | 156 ++++++++++++++---- 7 files changed, 322 insertions(+), 33 deletions(-) create mode 100644 compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_shadowed_by_field_access.snap create mode 100644 compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_shadowed_by_field_access.snap create mode 100644 compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_type_variant_from_unqualified_reference.snap diff --git a/compiler-core/src/language_server/tests/rename.rs b/compiler-core/src/language_server/tests/rename.rs index 7057277228c..359018ce078 100644 --- a/compiler-core/src/language_server/tests/rename.rs +++ b/compiler-core/src/language_server/tests/rename.rs @@ -533,6 +533,34 @@ pub fn main() { ); } +#[test] +fn rename_function_shadowed_by_field_access() { + assert_rename!( + ( + "mod", + " +import app + +type App { + App(something: Int) +} + +pub fn main() { + let app = App(10) + app.something +} +" + ), + " +pub fn something() { + todo +} +", + "function", + find_position_of("something").to_selection() + ); +} + #[test] fn no_rename_function_with_invalid_name() { assert_no_rename!( @@ -693,6 +721,32 @@ pub fn main() { ); } +#[test] +fn rename_constant_shadowed_by_field_access() { + assert_rename!( + ( + "mod", + " +import app + +type App { + App(something: Int) +} + +pub fn main() { + let app = App(10) + app.something +} +" + ), + " +pub const something = 10 +", + "constant", + find_position_of("something").to_selection() + ); +} + #[test] fn no_rename_constant_with_invalid_name() { assert_no_rename!( @@ -808,7 +862,7 @@ pub fn main() { } ", "Number", - find_position_of("Constructor,").to_selection() + find_position_of("Constructor(75").to_selection() ); } diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_shadowed_by_field_access.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_shadowed_by_field_access.snap new file mode 100644 index 00000000000..5ad56062309 --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_shadowed_by_field_access.snap @@ -0,0 +1,43 @@ +--- +source: compiler-core/src/language_server/tests/rename.rs +expression: "\npub const something = 10\n" +--- +----- BEFORE RENAME +-- mod.gleam + +import app + +type App { + App(something: Int) +} + +pub fn main() { + let app = App(10) + app.something +} + + +-- app.gleam + +pub const something = 10 + ↑ + + +----- AFTER RENAME +-- mod.gleam + +import app + +type App { + App(something: Int) +} + +pub fn main() { + let app = App(10) + app.something +} + + +-- app.gleam + +pub const constant = 10 diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_shadowing_module.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_shadowing_module.snap index 835d9242037..4e7245625d9 100644 --- a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_shadowing_module.snap +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_constant_shadowing_module.snap @@ -8,12 +8,12 @@ expression: "\nimport gleam/list\n\nconst list = []\n\npub fn main() {\n list.m import gleam/list const list = [] - ↑ + ↑ pub fn main() { list.map(todo, todo) } - + ----- AFTER RENAME diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_shadowed_by_field_access.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_shadowed_by_field_access.snap new file mode 100644 index 00000000000..992b1a2aef7 --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_shadowed_by_field_access.snap @@ -0,0 +1,47 @@ +--- +source: compiler-core/src/language_server/tests/rename.rs +expression: "\npub fn something() {\n todo\n}\n" +--- +----- BEFORE RENAME +-- mod.gleam + +import app + +type App { + App(something: Int) +} + +pub fn main() { + let app = App(10) + app.something +} + + +-- app.gleam + +pub fn something() { + ↑ + todo +} + + +----- AFTER RENAME +-- mod.gleam + +import app + +type App { + App(something: Int) +} + +pub fn main() { + let app = App(10) + app.something +} + + +-- app.gleam + +pub fn function() { + todo +} diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_shadowing_module.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_shadowing_module.snap index 44cdbbc5093..193d1c7e8bb 100644 --- a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_shadowing_module.snap +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_function_shadowing_module.snap @@ -8,14 +8,14 @@ expression: "\nimport gleam/list\n\npub fn list() {\n []\n}\n\npub fn main() {\ import gleam/list pub fn list() { - ↑ + ↑ [] } pub fn main() { list.map(todo, todo) } - + ----- AFTER RENAME diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_type_variant_from_unqualified_reference.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_type_variant_from_unqualified_reference.snap new file mode 100644 index 00000000000..1141c222adc --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_type_variant_from_unqualified_reference.snap @@ -0,0 +1,45 @@ +--- +source: compiler-core/src/language_server/tests/rename.rs +expression: "\nimport mod.{Constructor}\n\npub fn main() {\n #(Constructor(75), mod.Constructor(57))\n}\n" +--- +----- BEFORE RENAME +-- mod.gleam + +pub type Wibble { + Constructor(Int) +} + +fn wibble() { + Constructor(81) +} + + +-- app.gleam + +import mod.{Constructor} + +pub fn main() { + #(Constructor(75), mod.Constructor(57)) + ↑ +} + + +----- AFTER RENAME +-- mod.gleam + +pub type Wibble { + Number(Int) +} + +fn wibble() { + Number(81) +} + + +-- app.gleam + +import mod.{Number} + +pub fn main() { + #(Number(75), mod.Number(57)) +} diff --git a/compiler-core/src/type_/expression.rs b/compiler-core/src/type_/expression.rs index 6e90c9f646c..93c05dee5ca 100644 --- a/compiler-core/src/type_/expression.rs +++ b/compiler-core/src/type_/expression.rs @@ -304,7 +304,9 @@ impl<'a, 'b> ExprTyper<'a, 'b> { expression, } => self.infer_echo(location, expression), - UntypedExpr::Var { location, name, .. } => self.infer_var(name, location), + UntypedExpr::Var { location, name, .. } => { + self.infer_var(name, location, ReferenceRegistration::RegisterReferences) + } UntypedExpr::Int { location, @@ -949,8 +951,14 @@ impl<'a, 'b> ExprTyper<'a, 'b> { }) } - fn infer_var(&mut self, name: EcoString, location: SrcSpan) -> Result { - let constructor = self.infer_value_constructor(&None, &name, &location)?; + fn infer_var( + &mut self, + name: EcoString, + location: SrcSpan, + register_reference: ReferenceRegistration, + ) -> Result { + let constructor = + self.do_infer_value_constructor(&None, &name, &location, register_reference)?; self.narrow_implementations(location, &constructor.variant)?; Ok(TypedExpr::Var { constructor, @@ -1032,7 +1040,17 @@ impl<'a, 'b> ExprTyper<'a, 'b> { } _ => None, }; - let record = self.infer(container); + let record = match container { + // If the left-hand-side of the record access is a variable, this might actually be + // module access. In that case, we only want to register a reference to the variable + // if we actually referencing it in the record access. + UntypedExpr::Var { location, name } => self.infer_var( + name, + location, + ReferenceRegistration::DoNotRegisterReferences, + ), + _ => self.infer(container), + }; // TODO: is this clone avoidable? we need to box the record for inference in both // the success case and in the valid record but invalid label case let record_access = match record.clone() { @@ -1046,9 +1064,60 @@ impl<'a, 'b> ExprTyper<'a, 'b> { }; match (record_access, module_access) { // Record access is valid - (Ok(record_access), _) => record_access, + (Ok(record_access), _) => { + // If this is actually record access and not module access, and we didn't register + // the reference earlier, we register it now. + match &record_access { + TypedExpr::RecordAccess { record, .. } => match record.as_ref() { + TypedExpr::Var { + location, + constructor, + name, + } => self.register_value_constructor_reference( + name, + &constructor.variant, + *location, + ), + _ => {} + }, + _ => {} + } + record_access + } // Record access is invalid but module access is valid - (_, Some((Ok(module_access), _))) => module_access, + ( + _, + Some(( + Ok(TypedExpr::ModuleSelect { + location, + field_start, + type_, + label, + module_name, + module_alias, + constructor, + }), + _, + )), + ) => { + // We only register the reference here, if we know that this is a module access. + // Otherwise we would register module access even if we are actually accessing + // the field on a record + self.environment.register_reference( + module_name.clone(), + label.clone(), + SrcSpan::new(field_start, location.end), + ); + TypedExpr::ModuleSelect { + location, + field_start, + type_, + label, + module_name, + module_alias, + constructor, + } + } // Module access was attempted but failed and it does not shadow an existing variable (_, Some((Err(module_access_err), false))) => { self.problems.error(module_access_err); @@ -2263,6 +2332,12 @@ impl<'a, 'b> ExprTyper<'a, 'b> { constructor, } => match constructor { ModuleValueConstructor::Constant { literal, .. } => { + self.environment.register_reference( + module_name.clone(), + label.clone(), + location, + ); + Ok(ClauseGuard::ModuleSelect { location, type_, @@ -2340,16 +2415,6 @@ impl<'a, 'b> ExprTyper<'a, 'b> { let constructor = constructor.clone(); let module_name = module.name.clone(); - match &constructor.variant { - ValueConstructorVariant::ModuleFn { name, module, .. } - | ValueConstructorVariant::Record { name, module, .. } - | ValueConstructorVariant::ModuleConstant { name, module, .. } => self - .environment - .register_reference(module.clone(), name.clone(), select_location), - ValueConstructorVariant::LocalVariable { .. } - | ValueConstructorVariant::LocalConstant { .. } => {} - } - (module_name, constructor) }; @@ -2864,6 +2929,21 @@ impl<'a, 'b> ExprTyper<'a, 'b> { module: &Option<(EcoString, SrcSpan)>, name: &EcoString, location: &SrcSpan, + ) -> Result { + self.do_infer_value_constructor( + module, + name, + location, + ReferenceRegistration::RegisterReferences, + ) + } + + fn do_infer_value_constructor( + &mut self, + module: &Option<(EcoString, SrcSpan)>, + name: &EcoString, + location: &SrcSpan, + register_reference: ReferenceRegistration, ) -> Result { let constructor = match module { // Look in the current scope for a binding with this name @@ -2926,7 +3006,30 @@ impl<'a, 'b> ExprTyper<'a, 'b> { self.narrow_implementations(*location, &variant)?; - match &variant { + if matches!( + register_reference, + ReferenceRegistration::RegisterReferences + ) { + self.register_value_constructor_reference(name, &variant, *location); + } + + // Instantiate generic variables into unbound variables for this usage + let type_ = self.instantiate(type_, &mut hashmap![]); + Ok(ValueConstructor { + publicity, + deprecation, + variant, + type_, + }) + } + + fn register_value_constructor_reference( + &mut self, + referenced_name: &EcoString, + variant: &ValueConstructorVariant, + location: SrcSpan, + ) { + match variant { // If the referenced name is different to the name of the original // value, that means we are referencing it via an alias and don't // want to track this reference. @@ -2938,24 +3041,15 @@ impl<'a, 'b> ExprTyper<'a, 'b> { } | ValueConstructorVariant::ModuleConstant { name: value_name, .. - } if module.is_none() && value_name != name => {} + } if value_name != referenced_name => {} ValueConstructorVariant::ModuleFn { name, module, .. } | ValueConstructorVariant::Record { name, module, .. } | ValueConstructorVariant::ModuleConstant { name, module, .. } => self .environment - .register_reference(module.clone(), name.clone(), *location), + .register_reference(module.clone(), name.clone(), location), ValueConstructorVariant::LocalVariable { .. } | ValueConstructorVariant::LocalConstant { .. } => {} } - - // Instantiate generic variables into unbound variables for this usage - let type_ = self.instantiate(type_, &mut hashmap![]); - Ok(ValueConstructor { - publicity, - deprecation, - variant, - type_, - }) } fn report_name_error(&mut self, name: &EcoString, location: &SrcSpan) -> Error { @@ -4015,6 +4109,12 @@ impl<'a, 'b> ExprTyper<'a, 'b> { } } +#[derive(Debug, Clone, Copy)] +enum ReferenceRegistration { + RegisterReferences, + DoNotRegisterReferences, +} + fn extract_typed_use_call_assignments( call: &TypedExpr, assignments_count: usize, From ce9ba660ae9c0ecceab2c87a9148c2f64204a001 Mon Sep 17 00:00:00 2001 From: GearsDatapacks Date: Fri, 28 Feb 2025 20:28:09 +0000 Subject: [PATCH 20/27] Clippy --- compiler-core/src/type_/expression.rs | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/compiler-core/src/type_/expression.rs b/compiler-core/src/type_/expression.rs index 93c05dee5ca..0812d5c47a1 100644 --- a/compiler-core/src/type_/expression.rs +++ b/compiler-core/src/type_/expression.rs @@ -1067,21 +1067,15 @@ impl<'a, 'b> ExprTyper<'a, 'b> { (Ok(record_access), _) => { // If this is actually record access and not module access, and we didn't register // the reference earlier, we register it now. - match &record_access { - TypedExpr::RecordAccess { record, .. } => match record.as_ref() { - TypedExpr::Var { - location, - constructor, - name, - } => self.register_value_constructor_reference( - name, - &constructor.variant, - *location, - ), - _ => {} - }, - _ => {} - } + if let TypedExpr::RecordAccess { record, .. } = &record_access { if let TypedExpr::Var { + location, + constructor, + name, + } = record.as_ref() { self.register_value_constructor_reference( + name, + &constructor.variant, + *location, + ) } } record_access } // Record access is invalid but module access is valid From d81edf41588abfeb12b2cd726fc8917ad82d5c5d Mon Sep 17 00:00:00 2001 From: GearsDatapacks Date: Fri, 28 Feb 2025 20:29:50 +0000 Subject: [PATCH 21/27] Format --- compiler-core/src/type_/expression.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/compiler-core/src/type_/expression.rs b/compiler-core/src/type_/expression.rs index 0812d5c47a1..60207875b4c 100644 --- a/compiler-core/src/type_/expression.rs +++ b/compiler-core/src/type_/expression.rs @@ -1067,15 +1067,20 @@ impl<'a, 'b> ExprTyper<'a, 'b> { (Ok(record_access), _) => { // If this is actually record access and not module access, and we didn't register // the reference earlier, we register it now. - if let TypedExpr::RecordAccess { record, .. } = &record_access { if let TypedExpr::Var { + if let TypedExpr::RecordAccess { record, .. } = &record_access { + if let TypedExpr::Var { location, constructor, name, - } = record.as_ref() { self.register_value_constructor_reference( - name, - &constructor.variant, - *location, - ) } } + } = record.as_ref() + { + self.register_value_constructor_reference( + name, + &constructor.variant, + *location, + ) + } + } record_access } // Record access is invalid but module access is valid From 71ac89dfe421c46b4df80c72540091896458dbe1 Mon Sep 17 00:00:00 2001 From: Louis Pilfold Date: Sat, 1 Mar 2025 12:19:39 +0000 Subject: [PATCH 22/27] Add failing tests --- .../src/language_server/tests/rename.rs | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/compiler-core/src/language_server/tests/rename.rs b/compiler-core/src/language_server/tests/rename.rs index 359018ce078..871e01464d8 100644 --- a/compiler-core/src/language_server/tests/rename.rs +++ b/compiler-core/src/language_server/tests/rename.rs @@ -905,3 +905,78 @@ pub type Wibble { find_position_of("Constructor").to_selection() ); } + +#[test] +fn rename_custom_type_variant_pattern() { + assert_rename!( + " +pub type Type { + X + Y +} + +pub fn main(t) { + case t { + X -> 0 + Y -> 0 + } +} +", + "Renamed", + find_position_of("X").to_selection() + ); +} + +#[test] +fn rename_imported_custom_type_variant_pattern() { + assert_rename!( + ( + "other", + " +import app + +pub fn main(t) { + case t { + app.X -> 0 + app.Y -> 0 + } +} +" + ), + " +pub type Type { + X + Y +} +", + "Renamed", + find_position_of("X").to_selection() + ); +} + +#[test] +fn rename_imported_unqualified_custom_type_variant_pattern() { + assert_rename!( + ( + "other", + " +import app.{X, Y} + +pub fn main(t) { + case t { + X -> 0 + Y -> 0 + } +} +" + ), + " +pub type Type { + X + Y +} +", + "Renamed", + find_position_of("X").to_selection() + ); +} From fd39b57d008847d95ccda42b69d764ece1b207cb Mon Sep 17 00:00:00 2001 From: GearsDatapacks Date: Sat, 1 Mar 2025 21:00:21 +0000 Subject: [PATCH 23/27] Implement renaming in patterns --- compiler-core/src/ast.rs | 1 + compiler-core/src/ast/visit.rs | 5 +++ compiler-core/src/ast_folder.rs | 14 +++++- .../src/language_server/code_action.rs | 8 ++++ compiler-core/src/language_server/engine.rs | 23 ++++++++-- .../src/language_server/tests/rename.rs | 42 +++++++++++++++++ ...e__rename_custom_type_variant_pattern.snap | 35 +++++++++++++++ ..._imported_custom_type_variant_pattern.snap | 45 +++++++++++++++++++ ...qualified_custom_type_variant_pattern.snap | 45 +++++++++++++++++++ ...ame__rename_type_variant_from_pattern.snap | 35 +++++++++++++++ ...e_type_variant_pattern_with_arguments.snap | 35 +++++++++++++++ compiler-core/src/parse.rs | 6 ++- compiler-core/src/type_/pattern.rs | 9 ++++ 13 files changed, 297 insertions(+), 6 deletions(-) create mode 100644 compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_custom_type_variant_pattern.snap create mode 100644 compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_imported_custom_type_variant_pattern.snap create mode 100644 compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_imported_unqualified_custom_type_variant_pattern.snap create mode 100644 compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_type_variant_from_pattern.snap create mode 100644 compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_type_variant_pattern_with_arguments.snap diff --git a/compiler-core/src/ast.rs b/compiler-core/src/ast.rs index 221c773f252..49e051563c1 100644 --- a/compiler-core/src/ast.rs +++ b/compiler-core/src/ast.rs @@ -1830,6 +1830,7 @@ pub enum Pattern { /// The constructor for a custom type. Starts with an uppercase letter. Constructor { location: SrcSpan, + name_location: SrcSpan, name: EcoString, arguments: Vec>, module: Option<(EcoString, SrcSpan)>, diff --git a/compiler-core/src/ast/visit.rs b/compiler-core/src/ast/visit.rs index e425a5566b6..bb7f762fcc5 100644 --- a/compiler-core/src/ast/visit.rs +++ b/compiler-core/src/ast/visit.rs @@ -469,6 +469,7 @@ pub trait Visit<'ast> { fn visit_typed_pattern_constructor( &mut self, location: &'ast SrcSpan, + name_location: &'ast SrcSpan, name: &'ast EcoString, arguments: &'ast Vec>, module: &'ast Option<(EcoString, SrcSpan)>, @@ -479,6 +480,7 @@ pub trait Visit<'ast> { visit_typed_pattern_constructor( self, location, + name_location, name, arguments, module, @@ -1473,6 +1475,7 @@ where } => v.visit_typed_pattern_list(location, elements, tail, type_), Pattern::Constructor { location, + name_location, name, arguments, module, @@ -1481,6 +1484,7 @@ where type_, } => v.visit_typed_pattern_constructor( location, + name_location, name, arguments, module, @@ -1593,6 +1597,7 @@ pub fn visit_typed_pattern_list<'a, V>( pub fn visit_typed_pattern_constructor<'a, V>( v: &mut V, _location: &'a SrcSpan, + _name_location: &'a SrcSpan, _name: &'a EcoString, arguments: &'a Vec>, _module: &'a Option<(EcoString, SrcSpan)>, diff --git a/compiler-core/src/ast_folder.rs b/compiler-core/src/ast_folder.rs index e1948c8cf53..7ec107394f8 100644 --- a/compiler-core/src/ast_folder.rs +++ b/compiler-core/src/ast_folder.rs @@ -1173,13 +1173,21 @@ pub trait PatternFolder { Pattern::Constructor { location, + name_location, name, arguments, module, spread, constructor: _, type_: (), - } => self.fold_pattern_constructor(location, name, arguments, module, spread), + } => self.fold_pattern_constructor( + location, + name_location, + name, + arguments, + module, + spread, + ), Pattern::Tuple { location, elems } => self.fold_pattern_tuple(location, elems), @@ -1289,6 +1297,7 @@ pub trait PatternFolder { fn fold_pattern_constructor( &mut self, location: SrcSpan, + name_location: SrcSpan, name: EcoString, arguments: Vec>, module: Option<(EcoString, SrcSpan)>, @@ -1296,6 +1305,7 @@ pub trait PatternFolder { ) -> UntypedPattern { Pattern::Constructor { location, + name_location, name, arguments, module, @@ -1390,6 +1400,7 @@ pub trait PatternFolder { Pattern::Constructor { location, + name_location, name, arguments, module, @@ -1406,6 +1417,7 @@ pub trait PatternFolder { .collect(); Pattern::Constructor { location, + name_location, name, arguments, module, diff --git a/compiler-core/src/language_server/code_action.rs b/compiler-core/src/language_server/code_action.rs index 89926504621..8065f4751e7 100644 --- a/compiler-core/src/language_server/code_action.rs +++ b/compiler-core/src/language_server/code_action.rs @@ -1405,6 +1405,7 @@ impl<'ast> ast::visit::Visit<'ast> for QualifiedToUnqualifiedImportFirstPass<'as fn visit_typed_pattern_constructor( &mut self, location: &'ast SrcSpan, + name_location: &'ast SrcSpan, name: &'ast EcoString, arguments: &'ast Vec>, module: &'ast Option<(EcoString, SrcSpan)>, @@ -1433,6 +1434,7 @@ impl<'ast> ast::visit::Visit<'ast> for QualifiedToUnqualifiedImportFirstPass<'as ast::visit::visit_typed_pattern_constructor( self, location, + name_location, name, arguments, module, @@ -1708,6 +1710,7 @@ impl<'ast> ast::visit::Visit<'ast> for QualifiedToUnqualifiedImportSecondPass<'a fn visit_typed_pattern_constructor( &mut self, location: &'ast SrcSpan, + name_location: &'ast SrcSpan, name: &'ast EcoString, arguments: &'ast Vec>, module: &'ast Option<(EcoString, SrcSpan)>, @@ -1732,6 +1735,7 @@ impl<'ast> ast::visit::Visit<'ast> for QualifiedToUnqualifiedImportSecondPass<'a ast::visit::visit_typed_pattern_constructor( self, location, + name_location, name, arguments, module, @@ -1916,6 +1920,7 @@ impl<'ast> ast::visit::Visit<'ast> for UnqualifiedToQualifiedImportFirstPass<'as fn visit_typed_pattern_constructor( &mut self, location: &'ast SrcSpan, + name_location: &'ast SrcSpan, name: &'ast EcoString, arguments: &'ast Vec>, module: &'ast Option<(EcoString, SrcSpan)>, @@ -1937,6 +1942,7 @@ impl<'ast> ast::visit::Visit<'ast> for UnqualifiedToQualifiedImportFirstPass<'as ast::visit::visit_typed_pattern_constructor( self, location, + name_location, name, arguments, module, @@ -2110,6 +2116,7 @@ impl<'ast> ast::visit::Visit<'ast> for UnqualifiedToQualifiedImportSecondPass<'a fn visit_typed_pattern_constructor( &mut self, location: &'ast SrcSpan, + name_location: &'ast SrcSpan, name: &'ast EcoString, arguments: &'ast Vec>, module: &'ast Option<(EcoString, SrcSpan)>, @@ -2130,6 +2137,7 @@ impl<'ast> ast::visit::Visit<'ast> for UnqualifiedToQualifiedImportSecondPass<'a ast::visit::visit_typed_pattern_constructor( self, location, + name_location, name, arguments, module, diff --git a/compiler-core/src/language_server/engine.rs b/compiler-core/src/language_server/engine.rs index 71b59405b6d..7ba2e0b1ff0 100644 --- a/compiler-core/src/language_server/engine.rs +++ b/compiler-core/src/language_server/engine.rs @@ -1,6 +1,6 @@ use crate::{ Error, Result, Warning, - analyse::name::correct_name_case, + analyse::{self, name::correct_name_case}, ast::{ self, ArgNames, CustomType, Definition, DefinitionLocation, Function, ModuleConstant, Pattern, RecordConstructor, SrcSpan, TypedArg, TypedExpr, TypedFunction, TypedModule, @@ -564,6 +564,8 @@ where ))) }; + let byte_index = lines.byte_index(params.position.line, params.position.character); + Ok(match found { Located::Expression(TypedExpr::Var { constructor: @@ -594,6 +596,13 @@ where _ => None, }), Located::Pattern(Pattern::Assign { location, .. }) => success_response(*location), + Located::Pattern(Pattern::Constructor { name_location, .. }) => { + if name_location.contains(byte_index) { + success_response(*name_location) + } else { + None + } + } Located::Arg(arg) => match &arg.names { ArgNames::Named { location, .. } | ArgNames::NamedLabelled { @@ -627,8 +636,6 @@ where | Definition::ModuleConstant(ModuleConstant { name_location, .. }), ) | Located::RecordConstructor(RecordConstructor { name_location, .. }) => { - let byte_index = - lines.byte_index(params.position.line, params.position.character); // When we locate a module statement, we don't know where exactly the cursor // is positioned. In this example, we want to rename the first but not the second: // ```gleam @@ -827,6 +834,16 @@ where &this.compiler.modules, Named::CustomTypeVariant, ), + Located::Pattern(Pattern::Constructor { + constructor: analyse::Inferred::Known(constructor), + .. + }) => rename_module_value( + ¶ms, + &constructor.module, + &constructor.name, + &this.compiler.modules, + Named::CustomTypeVariant, + ), _ => None, }) }) diff --git a/compiler-core/src/language_server/tests/rename.rs b/compiler-core/src/language_server/tests/rename.rs index 871e01464d8..1bb5c53c8b4 100644 --- a/compiler-core/src/language_server/tests/rename.rs +++ b/compiler-core/src/language_server/tests/rename.rs @@ -980,3 +980,45 @@ pub type Type { find_position_of("X").to_selection() ); } + +#[test] +fn rename_type_variant_pattern_with_arguments() { + assert_rename!( + " +pub type Wibble { + Wibble(Int) + Wobble(Float) +} + +fn wibble() { + case Wibble(10) { + Wibble(20) -> todo + Wibble(_) -> panic + } +} +", + "Variant", + find_position_of("Wibble(10)").to_selection() + ); +} + +#[test] +fn rename_type_variant_from_pattern() { + assert_rename!( + " +pub type Type { + X + Y +} + +pub fn main(t) { + case t { + X -> 0 + Y -> 0 + } +} +", + "Renamed", + find_position_of("X ->").to_selection() + ); +} diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_custom_type_variant_pattern.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_custom_type_variant_pattern.snap new file mode 100644 index 00000000000..8cb7c61c1d3 --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_custom_type_variant_pattern.snap @@ -0,0 +1,35 @@ +--- +source: compiler-core/src/language_server/tests/rename.rs +expression: "\npub type Type {\n X\n Y\n}\n\npub fn main(t) {\n case t {\n X -> 0\n Y -> 0\n }\n}\n" +--- +----- BEFORE RENAME +-- app.gleam + +pub type Type { + X + ↑ + Y +} + +pub fn main(t) { + case t { + X -> 0 + Y -> 0 + } +} + + +----- AFTER RENAME +-- app.gleam + +pub type Type { + Renamed + Y +} + +pub fn main(t) { + case t { + Renamed -> 0 + Y -> 0 + } +} diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_imported_custom_type_variant_pattern.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_imported_custom_type_variant_pattern.snap new file mode 100644 index 00000000000..f8fd8d42d3f --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_imported_custom_type_variant_pattern.snap @@ -0,0 +1,45 @@ +--- +source: compiler-core/src/language_server/tests/rename.rs +expression: "\npub type Type {\n X\n Y\n}\n" +--- +----- BEFORE RENAME +-- other.gleam + +import app + +pub fn main(t) { + case t { + app.X -> 0 + app.Y -> 0 + } +} + + +-- app.gleam + +pub type Type { + X + ↑ + Y +} + + +----- AFTER RENAME +-- other.gleam + +import app + +pub fn main(t) { + case t { + app.Renamed -> 0 + app.Y -> 0 + } +} + + +-- app.gleam + +pub type Type { + Renamed + Y +} diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_imported_unqualified_custom_type_variant_pattern.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_imported_unqualified_custom_type_variant_pattern.snap new file mode 100644 index 00000000000..aa145d678b5 --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_imported_unqualified_custom_type_variant_pattern.snap @@ -0,0 +1,45 @@ +--- +source: compiler-core/src/language_server/tests/rename.rs +expression: "\npub type Type {\n X\n Y\n}\n" +--- +----- BEFORE RENAME +-- other.gleam + +import app.{X, Y} + +pub fn main(t) { + case t { + X -> 0 + Y -> 0 + } +} + + +-- app.gleam + +pub type Type { + X + ↑ + Y +} + + +----- AFTER RENAME +-- other.gleam + +import app.{Renamed, Y} + +pub fn main(t) { + case t { + Renamed -> 0 + Y -> 0 + } +} + + +-- app.gleam + +pub type Type { + Renamed + Y +} diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_type_variant_from_pattern.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_type_variant_from_pattern.snap new file mode 100644 index 00000000000..0ff22a8694b --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_type_variant_from_pattern.snap @@ -0,0 +1,35 @@ +--- +source: compiler-core/src/language_server/tests/rename.rs +expression: "\npub type Type {\n X\n Y\n}\n\npub fn main(t) {\n case t {\n X -> 0\n Y -> 0\n }\n}\n" +--- +----- BEFORE RENAME +-- app.gleam + +pub type Type { + X + Y +} + +pub fn main(t) { + case t { + X -> 0 + ↑ + Y -> 0 + } +} + + +----- AFTER RENAME +-- app.gleam + +pub type Type { + Renamed + Y +} + +pub fn main(t) { + case t { + Renamed -> 0 + Y -> 0 + } +} diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_type_variant_pattern_with_arguments.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_type_variant_pattern_with_arguments.snap new file mode 100644 index 00000000000..9c0a820641d --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__rename__rename_type_variant_pattern_with_arguments.snap @@ -0,0 +1,35 @@ +--- +source: compiler-core/src/language_server/tests/rename.rs +expression: "\npub type Wibble {\n Wibble(Int)\n Wobble(Float)\n}\n\nfn wibble() {\n case Wibble(10) {\n Wibble(20) -> todo\n Wibble(_) -> panic\n }\n}\n" +--- +----- BEFORE RENAME +-- app.gleam + +pub type Wibble { + Wibble(Int) + Wobble(Float) +} + +fn wibble() { + case Wibble(10) { + ↑ + Wibble(20) -> todo + Wibble(_) -> panic + } +} + + +----- AFTER RENAME +-- app.gleam + +pub type Wibble { + Variant(Int) + Wobble(Float) +} + +fn wibble() { + case Variant(10) { + Variant(20) -> todo + Variant(_) -> panic + } +} diff --git a/compiler-core/src/parse.rs b/compiler-core/src/parse.rs index 4cb8aebc342..7349746da1b 100644 --- a/compiler-core/src/parse.rs +++ b/compiler-core/src/parse.rs @@ -1772,13 +1772,15 @@ where &mut self, module: Option<(u32, EcoString, u32)>, ) -> Result { - let (mut start, name, end) = self.expect_upname()?; - let (args, spread, end) = self.parse_constructor_pattern_args(end)?; + let (name_start, name, name_end) = self.expect_upname()?; + let mut start = name_start; + let (args, spread, end) = self.parse_constructor_pattern_args(name_end)?; if let Some((s, _, _)) = module { start = s; } Ok(Pattern::Constructor { location: SrcSpan { start, end }, + name_location: SrcSpan::new(name_start, name_end), arguments: args, module: module.map(|(start, n, end)| (n, SrcSpan { start, end })), name, diff --git a/compiler-core/src/type_/pattern.rs b/compiler-core/src/type_/pattern.rs index d7bccbbbae3..42c5f479e1e 100644 --- a/compiler-core/src/type_/pattern.rs +++ b/compiler-core/src/type_/pattern.rs @@ -648,6 +648,7 @@ impl<'a, 'b> PatternTyper<'a, 'b> { Pattern::Constructor { location, module, + name_location, name, arguments: mut pattern_args, spread, @@ -816,6 +817,12 @@ impl<'a, 'b> PatternTyper<'a, 'b> { } } + self.environment.register_reference( + constructor.module.clone(), + constructor.name.clone(), + name_location, + ); + let instantiated_constructor_type = self.environment .instantiate(constructor_typ, &mut hashmap![], self.hydrator); @@ -862,6 +869,7 @@ impl<'a, 'b> PatternTyper<'a, 'b> { Ok(Pattern::Constructor { location, + name_location, module, name, arguments: pattern_args, @@ -897,6 +905,7 @@ impl<'a, 'b> PatternTyper<'a, 'b> { Ok(Pattern::Constructor { location, + name_location, module, name, arguments: vec![], From 6e5051bdc53d217ca064aa6686caeafcd6c892eb Mon Sep 17 00:00:00 2001 From: GearsDatapacks Date: Sat, 1 Mar 2025 21:07:07 +0000 Subject: [PATCH 24/27] Address style comments --- compiler-core/src/ast.rs | 2 +- compiler-core/src/build.rs | 6 +++--- compiler-core/src/language_server/engine.rs | 24 ++++++++++++--------- compiler-core/src/language_server/rename.rs | 4 +++- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/compiler-core/src/ast.rs b/compiler-core/src/ast.rs index 49e051563c1..c5a52e9f461 100644 --- a/compiler-core/src/ast.rs +++ b/compiler-core/src/ast.rs @@ -914,7 +914,7 @@ impl TypedDefinition { return Some(annotation); } - return Some(Located::RecordConstructor(constructor)); + return Some(Located::VariantConstructorDefinition(constructor)); } // Note that the custom type `.location` covers the function diff --git a/compiler-core/src/build.rs b/compiler-core/src/build.rs index 94fda87d161..fb8c83b2196 100644 --- a/compiler-core/src/build.rs +++ b/compiler-core/src/build.rs @@ -339,7 +339,7 @@ pub enum Located<'a> { Statement(&'a TypedStatement), Expression(&'a TypedExpr), ModuleStatement(&'a TypedDefinition), - RecordConstructor(&'a TypedRecordConstructor), + VariantConstructorDefinition(&'a TypedRecordConstructor), FunctionBody(&'a TypedFunction), Arg(&'a TypedArg), Annotation(SrcSpan, std::sync::Arc), @@ -383,7 +383,7 @@ impl<'a> Located<'a> { module: None, span: statement.location(), }), - Self::RecordConstructor(record) => Some(DefinitionLocation { + Self::VariantConstructorDefinition(record) => Some(DefinitionLocation { module: None, span: record.location, }), @@ -425,7 +425,7 @@ impl<'a> Located<'a> { Located::PatternSpread { .. } => None, Located::ModuleStatement(definition) => None, - Located::RecordConstructor(_) => None, + Located::VariantConstructorDefinition(_) => None, Located::FunctionBody(function) => None, Located::UnqualifiedImport(unqualified_import) => None, Located::ModuleName { .. } => None, diff --git a/compiler-core/src/language_server/engine.rs b/compiler-core/src/language_server/engine.rs index 7ba2e0b1ff0..746fee6072d 100644 --- a/compiler-core/src/language_server/engine.rs +++ b/compiler-core/src/language_server/engine.rs @@ -304,7 +304,7 @@ where Located::FunctionBody(_) => Some(completer.completion_values()), Located::ModuleStatement(Definition::TypeAlias(_) | Definition::CustomType(_)) - | Located::RecordConstructor(_) => Some(completer.completion_types()), + | Located::VariantConstructorDefinition(_) => Some(completer.completion_types()), // If the import completions returned no results and we are in an import then // we should try to provide completions for unqualified values @@ -635,7 +635,9 @@ where }) | Definition::ModuleConstant(ModuleConstant { name_location, .. }), ) - | Located::RecordConstructor(RecordConstructor { name_location, .. }) => { + | Located::VariantConstructorDefinition(RecordConstructor { + name_location, .. + }) => { // When we locate a module statement, we don't know where exactly the cursor // is positioned. In this example, we want to rename the first but not the second: // ```gleam @@ -827,13 +829,15 @@ where &this.compiler.modules, Named::CustomTypeVariant, ), - Located::RecordConstructor(RecordConstructor { name, .. }) => rename_module_value( - ¶ms, - &module.name, - name, - &this.compiler.modules, - Named::CustomTypeVariant, - ), + Located::VariantConstructorDefinition(RecordConstructor { name, .. }) => { + rename_module_value( + ¶ms, + &module.name, + name, + &this.compiler.modules, + Named::CustomTypeVariant, + ) + } Located::Pattern(Pattern::Constructor { constructor: analyse::Inferred::Known(constructor), .. @@ -900,7 +904,7 @@ where )) } Located::ModuleStatement(_) => None, - Located::RecordConstructor(_) => None, + Located::VariantConstructorDefinition(_) => None, Located::UnqualifiedImport(UnqualifiedImport { name, module: module_name, diff --git a/compiler-core/src/language_server/rename.rs b/compiler-core/src/language_server/rename.rs index a85aaaa88e7..4086ea79b4a 100644 --- a/compiler-core/src/language_server/rename.rs +++ b/compiler-core/src/language_server/rename.rs @@ -73,7 +73,9 @@ pub fn rename_module_value( name_kind: Named, ) -> Option { if name::check_name_case( - Default::default(), + // We don't care about the actual error here, just whether the name is valid, + // so we just use the default span. + SrcSpan::default(), ¶ms.new_name.as_str().into(), name_kind, ) From 1afbf2bb24951f00c61a15207fb62d9153bf1b59 Mon Sep 17 00:00:00 2001 From: GearsDatapacks Date: Sun, 2 Mar 2025 12:49:27 +0000 Subject: [PATCH 25/27] Cache reference information --- compiler-core/generated/schema_capnp.rs | 684 ++++++++++++++++-- compiler-core/schema.capnp | 12 + compiler-core/src/analyse.rs | 20 +- compiler-core/src/ast.rs | 8 - .../src/build/package_loader/tests.rs | 1 + compiler-core/src/language_server/engine.rs | 21 +- compiler-core/src/language_server/rename.rs | 25 +- compiler-core/src/metadata/module_decoder.rs | 40 +- compiler-core/src/metadata/module_encoder.rs | 27 + compiler-core/src/metadata/tests.rs | 106 ++- compiler-core/src/parse.rs | 1 - ...re__parse__tests__const_string_concat.snap | 4 - ...deprecation_attribute_on_type_variant.snap | 4 - ...gleam_core__parse__tests__import_type.snap | 4 - ..._parse__tests__record_access_no_label.snap | 4 - compiler-core/src/type_.rs | 7 + compiler-core/src/type_/prelude.rs | 3 +- compiler-core/src/type_/tests.rs | 2 +- 18 files changed, 864 insertions(+), 109 deletions(-) diff --git a/compiler-core/generated/schema_capnp.rs b/compiler-core/generated/schema_capnp.rs index 9273e8720de..a0908fdab01 100644 --- a/compiler-core/generated/schema_capnp.rs +++ b/compiler-core/generated/schema_capnp.rs @@ -708,11 +708,19 @@ pub mod module { pub fn get_contains_echo(self) -> bool { self.reader.get_bool_field(1) } + #[inline] + pub fn get_references(self) -> ::capnp::Result> { + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(11), ::core::option::Option::None) + } + #[inline] + pub fn has_references(&self) -> bool { + !self.reader.get_pointer_field(11).is_null() + } } pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> } impl <> ::capnp::traits::HasStructSize for Builder<'_,> { - const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 1, pointers: 11 }; + const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 1, pointers: 12 }; } impl <> ::capnp::traits::HasTypeId for Builder<'_,> { const TYPE_ID: u64 = _private::TYPE_ID; @@ -954,6 +962,22 @@ pub mod module { pub fn set_contains_echo(&mut self, value: bool) { self.builder.set_bool_field(1, value); } + #[inline] + pub fn get_references(self) -> ::capnp::Result> { + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(11), ::core::option::Option::None) + } + #[inline] + pub fn set_references(&mut self, value: crate::schema_capnp::references::Reader<'_>) -> ::capnp::Result<()> { + ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(11), value, false) + } + #[inline] + pub fn init_references(self, ) -> crate::schema_capnp::references::Builder<'a> { + ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(11), 0) + } + #[inline] + pub fn has_references(&self) -> bool { + !self.builder.is_pointer_field_null(11) + } } pub struct Pipeline { _typeless: ::capnp::any_pointer::Pipeline } @@ -969,117 +993,127 @@ pub mod module { pub fn get_required_version(&self) -> crate::schema_capnp::version::Pipeline { ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(8)) } + pub fn get_references(&self) -> crate::schema_capnp::references::Pipeline { + ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(11)) + } } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 305] = [ + pub static ENCODED_NODE: [::capnp::Word; 321] = [ ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), ::capnp::word(129, 5, 219, 80, 68, 149, 82, 154), ::capnp::word(13, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), - ::capnp::word(11, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(12, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(21, 0, 0, 0, 162, 0, 0, 0), ::capnp::word(29, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(25, 0, 0, 0, 223, 2, 0, 0), + ::capnp::word(25, 0, 0, 0, 23, 3, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(115, 99, 104, 101, 109, 97, 46, 99), ::capnp::word(97, 112, 110, 112, 58, 77, 111, 100), ::capnp::word(117, 108, 101, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), - ::capnp::word(52, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(56, 0, 0, 0, 3, 0, 4, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(93, 1, 0, 0, 42, 0, 0, 0), + ::capnp::word(121, 1, 0, 0, 42, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(88, 1, 0, 0, 3, 0, 1, 0), - ::capnp::word(100, 1, 0, 0, 2, 0, 1, 0), + ::capnp::word(116, 1, 0, 0, 3, 0, 1, 0), + ::capnp::word(128, 1, 0, 0, 2, 0, 1, 0), ::capnp::word(1, 0, 0, 0, 1, 0, 0, 0), ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(97, 1, 0, 0, 50, 0, 0, 0), + ::capnp::word(125, 1, 0, 0, 50, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(92, 1, 0, 0, 3, 0, 1, 0), - ::capnp::word(168, 1, 0, 0, 2, 0, 1, 0), + ::capnp::word(120, 1, 0, 0, 3, 0, 1, 0), + ::capnp::word(196, 1, 0, 0, 2, 0, 1, 0), ::capnp::word(2, 0, 0, 0, 2, 0, 0, 0), ::capnp::word(0, 0, 1, 0, 2, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(165, 1, 0, 0, 58, 0, 0, 0), + ::capnp::word(193, 1, 0, 0, 58, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(160, 1, 0, 0, 3, 0, 1, 0), - ::capnp::word(236, 1, 0, 0, 2, 0, 1, 0), + ::capnp::word(188, 1, 0, 0, 3, 0, 1, 0), + ::capnp::word(8, 2, 0, 0, 2, 0, 1, 0), ::capnp::word(3, 0, 0, 0, 3, 0, 0, 0), ::capnp::word(0, 0, 1, 0, 3, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(233, 1, 0, 0, 82, 0, 0, 0), + ::capnp::word(5, 2, 0, 0, 82, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(232, 1, 0, 0, 3, 0, 1, 0), - ::capnp::word(52, 2, 0, 0, 2, 0, 1, 0), + ::capnp::word(4, 2, 0, 0, 3, 0, 1, 0), + ::capnp::word(80, 2, 0, 0, 2, 0, 1, 0), ::capnp::word(4, 0, 0, 0, 4, 0, 0, 0), ::capnp::word(0, 0, 1, 0, 4, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(49, 2, 0, 0, 66, 0, 0, 0), + ::capnp::word(77, 2, 0, 0, 66, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(44, 2, 0, 0, 3, 0, 1, 0), - ::capnp::word(56, 2, 0, 0, 2, 0, 1, 0), + ::capnp::word(72, 2, 0, 0, 3, 0, 1, 0), + ::capnp::word(84, 2, 0, 0, 2, 0, 1, 0), ::capnp::word(5, 0, 0, 0, 5, 0, 0, 0), ::capnp::word(0, 0, 1, 0, 5, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(53, 2, 0, 0, 146, 0, 0, 0), + ::capnp::word(81, 2, 0, 0, 146, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(56, 2, 0, 0, 3, 0, 1, 0), - ::capnp::word(132, 2, 0, 0, 2, 0, 1, 0), + ::capnp::word(84, 2, 0, 0, 3, 0, 1, 0), + ::capnp::word(160, 2, 0, 0, 2, 0, 1, 0), ::capnp::word(6, 0, 0, 0, 6, 0, 0, 0), ::capnp::word(0, 0, 1, 0, 6, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(129, 2, 0, 0, 98, 0, 0, 0), + ::capnp::word(157, 2, 0, 0, 98, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(128, 2, 0, 0, 3, 0, 1, 0), - ::capnp::word(140, 2, 0, 0, 2, 0, 1, 0), + ::capnp::word(156, 2, 0, 0, 3, 0, 1, 0), + ::capnp::word(168, 2, 0, 0, 2, 0, 1, 0), ::capnp::word(7, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 1, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(137, 2, 0, 0, 66, 0, 0, 0), + ::capnp::word(165, 2, 0, 0, 66, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(132, 2, 0, 0, 3, 0, 1, 0), - ::capnp::word(144, 2, 0, 0, 2, 0, 1, 0), + ::capnp::word(160, 2, 0, 0, 3, 0, 1, 0), + ::capnp::word(172, 2, 0, 0, 2, 0, 1, 0), ::capnp::word(8, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 1, 0, 8, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(141, 2, 0, 0, 90, 0, 0, 0), + ::capnp::word(169, 2, 0, 0, 90, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(140, 2, 0, 0, 3, 0, 1, 0), - ::capnp::word(152, 2, 0, 0, 2, 0, 1, 0), + ::capnp::word(168, 2, 0, 0, 3, 0, 1, 0), + ::capnp::word(180, 2, 0, 0, 2, 0, 1, 0), ::capnp::word(9, 0, 0, 0, 8, 0, 0, 0), ::capnp::word(0, 0, 1, 0, 9, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(149, 2, 0, 0, 130, 0, 0, 0), + ::capnp::word(177, 2, 0, 0, 130, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(148, 2, 0, 0, 3, 0, 1, 0), - ::capnp::word(160, 2, 0, 0, 2, 0, 1, 0), + ::capnp::word(176, 2, 0, 0, 3, 0, 1, 0), + ::capnp::word(188, 2, 0, 0, 2, 0, 1, 0), ::capnp::word(10, 0, 0, 0, 9, 0, 0, 0), ::capnp::word(0, 0, 1, 0, 10, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(157, 2, 0, 0, 98, 0, 0, 0), + ::capnp::word(185, 2, 0, 0, 98, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(156, 2, 0, 0, 3, 0, 1, 0), - ::capnp::word(232, 2, 0, 0, 2, 0, 1, 0), + ::capnp::word(184, 2, 0, 0, 3, 0, 1, 0), + ::capnp::word(4, 3, 0, 0, 2, 0, 1, 0), ::capnp::word(11, 0, 0, 0, 10, 0, 0, 0), ::capnp::word(0, 0, 1, 0, 11, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(229, 2, 0, 0, 114, 0, 0, 0), + ::capnp::word(1, 3, 0, 0, 114, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(228, 2, 0, 0, 3, 0, 1, 0), - ::capnp::word(0, 3, 0, 0, 2, 0, 1, 0), + ::capnp::word(0, 3, 0, 0, 3, 0, 1, 0), + ::capnp::word(28, 3, 0, 0, 2, 0, 1, 0), ::capnp::word(12, 0, 0, 0, 1, 0, 0, 0), ::capnp::word(0, 0, 1, 0, 12, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(253, 2, 0, 0, 106, 0, 0, 0), + ::capnp::word(25, 3, 0, 0, 106, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(24, 3, 0, 0, 3, 0, 1, 0), + ::capnp::word(36, 3, 0, 0, 2, 0, 1, 0), + ::capnp::word(13, 0, 0, 0, 11, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 13, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(33, 3, 0, 0, 90, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(252, 2, 0, 0, 3, 0, 1, 0), - ::capnp::word(8, 3, 0, 0, 2, 0, 1, 0), + ::capnp::word(32, 3, 0, 0, 3, 0, 1, 0), + ::capnp::word(44, 3, 0, 0, 2, 0, 1, 0), ::capnp::word(110, 97, 109, 101, 0, 0, 0, 0), ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -1277,6 +1311,15 @@ pub mod module { ::capnp::word(1, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(114, 101, 102, 101, 114, 101, 110, 99), + ::capnp::word(101, 115, 0, 0, 0, 0, 0, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(101, 145, 82, 27, 227, 203, 200, 215), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ]; pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { match index { @@ -1293,6 +1336,7 @@ pub mod module { 10 => <::capnp::struct_list::Owned> as ::capnp::introspect::Introspect>::introspect(), 11 => <::capnp::text_list::Owned as ::capnp::introspect::Introspect>::introspect(), 12 => ::introspect(), + 13 => ::introspect(), _ => panic!("invalid field index {}", index), } } @@ -1305,13 +1349,561 @@ pub mod module { members_by_discriminant: MEMBERS_BY_DISCRIMINANT, members_by_name: MEMBERS_BY_NAME, }; - pub static NONUNION_MEMBERS : &[u16] = &[0,1,2,3,4,5,6,7,8,9,10,11,12]; + pub static NONUNION_MEMBERS : &[u16] = &[0,1,2,3,4,5,6,7,8,9,10,11,12,13]; pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; - pub static MEMBERS_BY_NAME : &[u16] = &[3,12,11,8,6,0,4,9,7,10,1,5,2]; + pub static MEMBERS_BY_NAME : &[u16] = &[3,12,11,8,6,0,4,13,9,7,10,1,5,2]; pub const TYPE_ID: u64 = 0x9a52_9544_50db_0581; } } +pub mod references { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl ::capnp::introspect::Introspect for Owned { fn introspect() -> ::capnp::introspect::Type { ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }).into() } } + impl ::capnp::traits::Owned for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } + impl ::capnp::traits::OwnedStruct for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } + impl ::capnp::traits::Pipelined for Owned { type Pipeline = Pipeline; } + + pub struct Reader<'a> { reader: ::capnp::private::layout::StructReader<'a> } + impl <> ::core::marker::Copy for Reader<'_,> {} + impl <> ::core::clone::Clone for Reader<'_,> { + fn clone(&self) -> Self { *self } + } + + impl <> ::capnp::traits::HasTypeId for Reader<'_,> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl <'a,> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a,> { + fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { + Self { reader, } + } + } + + impl <'a,> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a,>) -> Self { + Self::Struct(::capnp::dynamic_struct::Reader::new(reader.reader, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + } + } + + impl <> ::core::fmt::Debug for Reader<'_,> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt(&::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), f) + } + } + + impl <'a,> ::capnp::traits::FromPointerReader<'a> for Reader<'a,> { + fn get_from_pointer(reader: &::capnp::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl <'a,> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a,> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl <'a,> ::capnp::traits::Imbue<'a> for Reader<'a,> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader.imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl <'a,> Reader<'a,> { + pub fn reborrow(&self) -> Reader<'_,> { + Self { .. *self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_imported_modules(self) -> ::capnp::Result<::capnp::text_list::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn has_imported_modules(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_value_references(self) -> ::capnp::Result<::capnp::struct_list::Reader<'a,crate::schema_capnp::value_reference::Owned>> { + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(1), ::core::option::Option::None) + } + #[inline] + pub fn has_value_references(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + } + + pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> } + impl <> ::capnp::traits::HasStructSize for Builder<'_,> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 0, pointers: 2 }; + } + impl <> ::capnp::traits::HasTypeId for Builder<'_,> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl <'a,> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a,> { + fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { + Self { builder, } + } + } + + impl <'a,> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a,>) -> Self { + Self::Struct(::capnp::dynamic_struct::Builder::new(builder.builder, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + } + } + + impl <'a,> ::capnp::traits::ImbueMut<'a> for Builder<'a,> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder.imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl <'a,> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a,> { + fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder.init_struct(::STRUCT_SIZE).into() + } + fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { + ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) + } + } + + impl <> ::capnp::traits::SetterInput> for Reader<'_,> { + fn set_pointer_builder(mut pointer: ::capnp::private::layout::PointerBuilder<'_>, value: Self, canonicalize: bool) -> ::capnp::Result<()> { pointer.set_struct(&value.reader, canonicalize) } + } + + impl <'a,> Builder<'a,> { + pub fn into_reader(self) -> Reader<'a,> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_,> { + Builder { builder: self.builder.reborrow() } + } + pub fn reborrow_as_reader(&self) -> Reader<'_,> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_imported_modules(self) -> ::capnp::Result<::capnp::text_list::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn set_imported_modules(&mut self, value: impl ::capnp::traits::SetterInput<::capnp::text_list::Owned>) -> ::capnp::Result<()> { + ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) + } + #[inline] + pub fn init_imported_modules(self, size: u32) -> ::capnp::text_list::Builder<'a> { + ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), size) + } + #[inline] + pub fn has_imported_modules(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_value_references(self) -> ::capnp::Result<::capnp::struct_list::Builder<'a,crate::schema_capnp::value_reference::Owned>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(1), ::core::option::Option::None) + } + #[inline] + pub fn set_value_references(&mut self, value: ::capnp::struct_list::Reader<'_,crate::schema_capnp::value_reference::Owned>) -> ::capnp::Result<()> { + ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false) + } + #[inline] + pub fn init_value_references(self, size: u32) -> ::capnp::struct_list::Builder<'a,crate::schema_capnp::value_reference::Owned> { + ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), size) + } + #[inline] + pub fn has_value_references(&self) -> bool { + !self.builder.is_pointer_field_null(1) + } + } + + pub struct Pipeline { _typeless: ::capnp::any_pointer::Pipeline } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { + Self { _typeless: typeless, } + } + } + impl Pipeline { + } + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 57] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), + ::capnp::word(101, 145, 82, 27, 227, 203, 200, 215), + ::capnp::word(13, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), + ::capnp::word(2, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(21, 0, 0, 0, 194, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(25, 0, 0, 0, 119, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(115, 99, 104, 101, 109, 97, 46, 99), + ::capnp::word(97, 112, 110, 112, 58, 82, 101, 102), + ::capnp::word(101, 114, 101, 110, 99, 101, 115, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(8, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(41, 0, 0, 0, 130, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(40, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(68, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(65, 0, 0, 0, 130, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(64, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(92, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(105, 109, 112, 111, 114, 116, 101, 100), + ::capnp::word(77, 111, 100, 117, 108, 101, 115, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(118, 97, 108, 117, 101, 82, 101, 102), + ::capnp::word(101, 114, 101, 110, 99, 101, 115, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(104, 93, 146, 250, 170, 165, 141, 205), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { + match index { + 0 => <::capnp::text_list::Owned as ::capnp::introspect::Introspect>::introspect(), + 1 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types(child_index: Option, index: u32) -> ::capnp::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = ::capnp::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + members_by_name: MEMBERS_BY_NAME, + }; + pub static NONUNION_MEMBERS : &[u16] = &[0,1]; + pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; + pub static MEMBERS_BY_NAME : &[u16] = &[0,1]; + pub const TYPE_ID: u64 = 0xd7c8_cbe3_1b52_9165; + } +} + +pub mod value_reference { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl ::capnp::introspect::Introspect for Owned { fn introspect() -> ::capnp::introspect::Type { ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }).into() } } + impl ::capnp::traits::Owned for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } + impl ::capnp::traits::OwnedStruct for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } + impl ::capnp::traits::Pipelined for Owned { type Pipeline = Pipeline; } + + pub struct Reader<'a> { reader: ::capnp::private::layout::StructReader<'a> } + impl <> ::core::marker::Copy for Reader<'_,> {} + impl <> ::core::clone::Clone for Reader<'_,> { + fn clone(&self) -> Self { *self } + } + + impl <> ::capnp::traits::HasTypeId for Reader<'_,> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl <'a,> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a,> { + fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { + Self { reader, } + } + } + + impl <'a,> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a,>) -> Self { + Self::Struct(::capnp::dynamic_struct::Reader::new(reader.reader, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + } + } + + impl <> ::core::fmt::Debug for Reader<'_,> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt(&::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), f) + } + } + + impl <'a,> ::capnp::traits::FromPointerReader<'a> for Reader<'a,> { + fn get_from_pointer(reader: &::capnp::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl <'a,> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a,> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl <'a,> ::capnp::traits::Imbue<'a> for Reader<'a,> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader.imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl <'a,> Reader<'a,> { + pub fn reborrow(&self) -> Reader<'_,> { + Self { .. *self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_module(self) -> ::capnp::Result<::capnp::text::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn has_module(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_name(self) -> ::capnp::Result<::capnp::text::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(1), ::core::option::Option::None) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + #[inline] + pub fn get_references(self) -> ::capnp::Result<::capnp::struct_list::Reader<'a,crate::schema_capnp::src_span::Owned>> { + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(2), ::core::option::Option::None) + } + #[inline] + pub fn has_references(&self) -> bool { + !self.reader.get_pointer_field(2).is_null() + } + } + + pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> } + impl <> ::capnp::traits::HasStructSize for Builder<'_,> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 0, pointers: 3 }; + } + impl <> ::capnp::traits::HasTypeId for Builder<'_,> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl <'a,> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a,> { + fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { + Self { builder, } + } + } + + impl <'a,> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a,>) -> Self { + Self::Struct(::capnp::dynamic_struct::Builder::new(builder.builder, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + } + } + + impl <'a,> ::capnp::traits::ImbueMut<'a> for Builder<'a,> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder.imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl <'a,> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a,> { + fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder.init_struct(::STRUCT_SIZE).into() + } + fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { + ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) + } + } + + impl <> ::capnp::traits::SetterInput> for Reader<'_,> { + fn set_pointer_builder(mut pointer: ::capnp::private::layout::PointerBuilder<'_>, value: Self, canonicalize: bool) -> ::capnp::Result<()> { pointer.set_struct(&value.reader, canonicalize) } + } + + impl <'a,> Builder<'a,> { + pub fn into_reader(self) -> Reader<'a,> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_,> { + Builder { builder: self.builder.reborrow() } + } + pub fn reborrow_as_reader(&self) -> Reader<'_,> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_module(self) -> ::capnp::Result<::capnp::text::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn set_module(&mut self, value: impl ::capnp::traits::SetterInput<::capnp::text::Owned>) { + ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false).unwrap() + } + #[inline] + pub fn init_module(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_module(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_name(self) -> ::capnp::Result<::capnp::text::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(1), ::core::option::Option::None) + } + #[inline] + pub fn set_name(&mut self, value: impl ::capnp::traits::SetterInput<::capnp::text::Owned>) { + ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false).unwrap() + } + #[inline] + pub fn init_name(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.get_pointer_field(1).init_text(size) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.builder.is_pointer_field_null(1) + } + #[inline] + pub fn get_references(self) -> ::capnp::Result<::capnp::struct_list::Builder<'a,crate::schema_capnp::src_span::Owned>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(2), ::core::option::Option::None) + } + #[inline] + pub fn set_references(&mut self, value: ::capnp::struct_list::Reader<'_,crate::schema_capnp::src_span::Owned>) -> ::capnp::Result<()> { + ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(2), value, false) + } + #[inline] + pub fn init_references(self, size: u32) -> ::capnp::struct_list::Builder<'a,crate::schema_capnp::src_span::Owned> { + ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(2), size) + } + #[inline] + pub fn has_references(&self) -> bool { + !self.builder.is_pointer_field_null(2) + } + } + + pub struct Pipeline { _typeless: ::capnp::any_pointer::Pipeline } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { + Self { _typeless: typeless, } + } + } + impl Pipeline { + } + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 68] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), + ::capnp::word(104, 93, 146, 250, 170, 165, 141, 205), + ::capnp::word(13, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(190, 237, 188, 253, 156, 169, 51, 181), + ::capnp::word(3, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(21, 0, 0, 0, 226, 0, 0, 0), + ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 175, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(115, 99, 104, 101, 109, 97, 46, 99), + ::capnp::word(97, 112, 110, 112, 58, 86, 97, 108), + ::capnp::word(117, 101, 82, 101, 102, 101, 114, 101), + ::capnp::word(110, 99, 101, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(12, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(69, 0, 0, 0, 58, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(64, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(76, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(73, 0, 0, 0, 42, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(68, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(80, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(2, 0, 0, 0, 2, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 2, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(77, 0, 0, 0, 90, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(76, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(104, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(109, 111, 100, 117, 108, 101, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(110, 97, 109, 101, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(114, 101, 102, 101, 114, 101, 110, 99), + ::capnp::word(101, 115, 0, 0, 0, 0, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(176, 122, 119, 83, 72, 147, 59, 230), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { + match index { + 0 => <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect(), + 1 => <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect(), + 2 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types(child_index: Option, index: u32) -> ::capnp::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = ::capnp::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + members_by_name: MEMBERS_BY_NAME, + }; + pub static NONUNION_MEMBERS : &[u16] = &[0,1,2]; + pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; + pub static MEMBERS_BY_NAME : &[u16] = &[0,1,2]; + pub const TYPE_ID: u64 = 0xcd8d_a5aa_fa92_5d68; + } +} + pub mod type_alias_constructor { #[derive(Copy, Clone)] pub struct Owned(()); diff --git a/compiler-core/schema.capnp b/compiler-core/schema.capnp index bd62cb645f7..b30a92e272d 100644 --- a/compiler-core/schema.capnp +++ b/compiler-core/schema.capnp @@ -33,6 +33,18 @@ struct Module { typeAliases @10 :List(Property(TypeAliasConstructor)); documentation @11 :List(Text); containsEcho @12 :Bool; + references @13 :References; +} + +struct References { + importedModules @0 :List(Text); + valueReferences @1 :List(ValueReference); +} + +struct ValueReference { + module @0 :Text; + name @1 :Text; + references @2 :List(SrcSpan); } struct TypeAliasConstructor { diff --git a/compiler-core/src/analyse.rs b/compiler-core/src/analyse.rs index 91adfd3ff9d..0af316e7568 100644 --- a/compiler-core/src/analyse.rs +++ b/compiler-core/src/analyse.rs @@ -9,10 +9,10 @@ use crate::{ ast::{ self, Arg, BitArrayOption, CustomType, Definition, DefinitionLocation, Function, GroupedStatements, Import, ModuleConstant, Publicity, RecordConstructor, - RecordConstructorArg, References, SrcSpan, Statement, TypeAlias, TypeAst, - TypeAstConstructor, TypeAstFn, TypeAstHole, TypeAstTuple, TypeAstVar, TypedDefinition, - TypedExpr, TypedFunction, TypedModule, UntypedArg, UntypedCustomType, UntypedFunction, - UntypedImport, UntypedModule, UntypedModuleConstant, UntypedStatement, UntypedTypeAlias, + RecordConstructorArg, SrcSpan, Statement, TypeAlias, TypeAst, TypeAstConstructor, + TypeAstFn, TypeAstHole, TypeAstTuple, TypeAstVar, TypedDefinition, TypedExpr, + TypedFunction, TypedModule, UntypedArg, UntypedCustomType, UntypedFunction, UntypedImport, + UntypedModule, UntypedModuleConstant, UntypedStatement, UntypedTypeAlias, }, build::{Origin, Outcome, Target}, call_graph::{CallGraphNode, into_dependency_order}, @@ -22,8 +22,8 @@ use crate::{ parse::SpannedString, type_::{ self, AccessorsMap, Deprecation, ModuleInterface, Opaque, PatternConstructor, - RecordAccessor, Type, TypeAliasConstructor, TypeConstructor, TypeValueConstructor, - TypeValueConstructorField, TypeVariantConstructors, ValueConstructor, + RecordAccessor, References, Type, TypeAliasConstructor, TypeConstructor, + TypeValueConstructor, TypeValueConstructorField, TypeVariantConstructors, ValueConstructor, ValueConstructorVariant, Warning, environment::*, error::{Error, FeatureKind, MissingAnnotation, Named, Problems, convert_unify_error}, @@ -340,12 +340,12 @@ impl<'a, A> ModuleAnalyzer<'a, A> { type_aliases, documentation, contains_echo: echo_found, + references: References { + imported_modules: env.imported_modules.into_keys().collect(), + value_references: env.references, + }, }, names: type_names, - references: References { - imported_modules: env.imported_modules.into_keys().collect(), - value_references: env.references, - }, }; match Vec1::try_from_vec(self.problems.take_errors()) { diff --git a/compiler-core/src/ast.rs b/compiler-core/src/ast.rs index c5a52e9f461..9cc934e79a3 100644 --- a/compiler-core/src/ast.rs +++ b/compiler-core/src/ast.rs @@ -20,7 +20,6 @@ use crate::type_::printer::Names; use crate::type_::{ self, Deprecation, ModuleValueConstructor, PatternConstructor, Type, ValueConstructor, }; -use std::collections::{HashMap, HashSet}; use std::sync::Arc; use ecow::EcoString; @@ -51,7 +50,6 @@ pub struct Module { pub type_info: Info, pub definitions: Vec, pub names: Names, - pub references: References, } impl TypedModule { @@ -68,12 +66,6 @@ impl TypedModule { } } -#[derive(Debug, Clone, PartialEq, Eq, Default)] -pub struct References { - pub imported_modules: HashSet, - pub value_references: HashMap<(EcoString, EcoString), Vec>, -} - /// The `@target(erlang)` and `@target(javascript)` attributes can be used to /// mark a definition as only being for a specific target. /// diff --git a/compiler-core/src/build/package_loader/tests.rs b/compiler-core/src/build/package_loader/tests.rs index a4271826ea0..705f59b1a6b 100644 --- a/compiler-core/src/build/package_loader/tests.rs +++ b/compiler-core/src/build/package_loader/tests.rs @@ -64,6 +64,7 @@ fn write_cache( type_aliases: Default::default(), documentation: Default::default(), contains_echo: false, + references: Default::default(), }; let path = Utf8Path::new("/artefact").join(format!("{name}.cache")); fs.write_bytes( diff --git a/compiler-core/src/language_server/engine.rs b/compiler-core/src/language_server/engine.rs index 746fee6072d..85d4bb8a8f7 100644 --- a/compiler-core/src/language_server/engine.rs +++ b/compiler-core/src/language_server/engine.rs @@ -769,7 +769,8 @@ where ¶ms, module_name, name, - &this.compiler.modules, + this.compiler.project_compiler.get_importable_modules(), + &this.compiler.sources, Named::Function, ), Located::Expression(TypedExpr::ModuleSelect { @@ -782,7 +783,8 @@ where ¶ms, module_name, label, - &this.compiler.modules, + this.compiler.project_compiler.get_importable_modules(), + &this.compiler.sources, Named::Function, ), Located::ModuleStatement( @@ -795,7 +797,8 @@ where ¶ms, &module.name, name, - &this.compiler.modules, + this.compiler.project_compiler.get_importable_modules(), + &this.compiler.sources, Named::Function, ), Located::Expression(TypedExpr::Var { @@ -814,7 +817,8 @@ where ¶ms, module_name, name, - &this.compiler.modules, + this.compiler.project_compiler.get_importable_modules(), + &this.compiler.sources, Named::CustomTypeVariant, ), Located::Expression(TypedExpr::ModuleSelect { @@ -826,7 +830,8 @@ where ¶ms, module_name, label, - &this.compiler.modules, + this.compiler.project_compiler.get_importable_modules(), + &this.compiler.sources, Named::CustomTypeVariant, ), Located::VariantConstructorDefinition(RecordConstructor { name, .. }) => { @@ -834,7 +839,8 @@ where ¶ms, &module.name, name, - &this.compiler.modules, + this.compiler.project_compiler.get_importable_modules(), + &this.compiler.sources, Named::CustomTypeVariant, ) } @@ -845,7 +851,8 @@ where ¶ms, &constructor.module, &constructor.name, - &this.compiler.modules, + this.compiler.project_compiler.get_importable_modules(), + &this.compiler.sources, Named::CustomTypeVariant, ), _ => None, diff --git a/compiler-core/src/language_server/rename.rs b/compiler-core/src/language_server/rename.rs index 4086ea79b4a..91bed8d4f2f 100644 --- a/compiler-core/src/language_server/rename.rs +++ b/compiler-core/src/language_server/rename.rs @@ -8,10 +8,10 @@ use crate::{ ast::{self, SrcSpan, TypedModule, visit::Visit}, build::Module, line_numbers::LineNumbers, - type_::{ValueConstructor, ValueConstructorVariant, error::Named}, + type_::{ModuleInterface, ValueConstructor, ValueConstructorVariant, error::Named}, }; -use super::TextEdits; +use super::{TextEdits, compiler::ModuleSourceInformation}; fn workspace_edit(uri: Url, edits: Vec) -> WorkspaceEdit { let mut changes = HashMap::new(); @@ -69,7 +69,8 @@ pub fn rename_module_value( params: &RenameParams, module_name: &EcoString, name: &EcoString, - modules: &HashMap, + modules: &im::HashMap, + sources: &HashMap, name_kind: Named, ) -> Option { if name::check_name_case( @@ -91,11 +92,14 @@ pub fn rename_module_value( }; for module in modules.values() { - if &module.name == module_name - || module.ast.references.imported_modules.contains(module_name) - { + if &module.name == module_name || module.references.imported_modules.contains(module_name) { + let Some(source_information) = sources.get(&module.name) else { + continue; + }; + rename_references_in_module( module, + source_information, &mut workspace_edit, module_name, name, @@ -108,14 +112,14 @@ pub fn rename_module_value( } fn rename_references_in_module( - module: &Module, + module: &ModuleInterface, + source_information: &ModuleSourceInformation, workspace_edit: &mut WorkspaceEdit, module_name: &EcoString, name: &EcoString, new_name: String, ) { let Some(references) = module - .ast .references .value_references .get(&(module_name.clone(), name.clone())) @@ -123,14 +127,13 @@ fn rename_references_in_module( return; }; - let line_numbers = LineNumbers::new(&module.code); - let mut edits = TextEdits::new(&line_numbers); + let mut edits = TextEdits::new(&source_information.line_numbers); references .iter() .for_each(|location| edits.replace(*location, new_name.clone())); - let Some(uri) = url_from_path(module.input_path.as_str()) else { + let Some(uri) = url_from_path(source_information.path.as_str()) else { return; }; diff --git a/compiler-core/src/metadata/module_decoder.rs b/compiler-core/src/metadata/module_decoder.rs index 5884e5b4eb9..966a92f0165 100755 --- a/compiler-core/src/metadata/module_decoder.rs +++ b/compiler-core/src/metadata/module_decoder.rs @@ -14,14 +14,14 @@ use crate::{ line_numbers::LineNumbers, schema_capnp::{self as schema, *}, type_::{ - self, AccessorsMap, Deprecation, FieldMap, ModuleInterface, Opaque, RecordAccessor, Type, - TypeAliasConstructor, TypeConstructor, TypeValueConstructor, TypeValueConstructorField, - TypeVariantConstructors, ValueConstructor, ValueConstructorVariant, - expression::Implementations, + self, AccessorsMap, Deprecation, FieldMap, ModuleInterface, Opaque, RecordAccessor, + References, Type, TypeAliasConstructor, TypeConstructor, TypeValueConstructor, + TypeValueConstructorField, TypeVariantConstructors, ValueConstructor, + ValueConstructorVariant, expression::Implementations, }, uid::UniqueIdGenerator, }; -use std::{collections::HashMap, io::BufRead, sync::Arc}; +use std::{collections::HashMap, collections::HashSet, io::BufRead, sync::Arc}; macro_rules! read_vec { ($reader:expr, $self:expr, $method:ident) => {{ @@ -87,6 +87,7 @@ impl ModuleDecoder { type_aliases: read_hashmap!(reader.get_type_aliases()?, self, type_alias_constructor), documentation: self.string_list(reader.get_documentation()?)?, contains_echo: reader.get_contains_echo(), + references: self.references(reader.get_references()?)?, }) } @@ -108,6 +109,35 @@ impl ModuleDecoder { .map_err(|_| capnp::Error::failed("String contains non-utf8 characters".into()).into()) } + fn references(&self, reader: references::Reader<'_>) -> Result { + Ok(References { + imported_modules: self.string_set(reader.get_imported_modules()?)?, + value_references: self.value_references(reader.get_value_references()?)?, + }) + } + + fn string_set(&self, reader: text_list::Reader<'_>) -> Result> { + let mut set = HashSet::with_capacity(reader.len() as usize); + for reader in reader.into_iter() { + let _ = set.insert(self.string(reader?)?); + } + Ok(set) + } + + fn value_references( + &self, + reader: capnp::struct_list::Reader<'_, value_reference::Owned>, + ) -> Result>> { + let mut map = HashMap::with_capacity(reader.len() as usize); + for prop in reader.into_iter() { + let module = self.string(prop.get_module()?)?; + let name = self.string(prop.get_name()?)?; + let references = read_vec!(prop.get_references()?, self, src_span); + let _ = map.insert((module, name), references); + } + Ok(map) + } + fn type_constructor( &mut self, reader: &type_constructor::Reader<'_>, diff --git a/compiler-core/src/metadata/module_encoder.rs b/compiler-core/src/metadata/module_encoder.rs index e5bf4c44491..1c3ad093527 100644 --- a/compiler-core/src/metadata/module_encoder.rs +++ b/compiler-core/src/metadata/module_encoder.rs @@ -52,6 +52,7 @@ impl<'a> ModuleEncoder<'a> { self.set_version(&mut module); self.set_module_documentation(&mut module); self.set_module_type_aliases(&mut module); + self.set_module_references(&mut module); capnp::serialize_packed::write_message(&mut buffer, &message).expect("capnp encode"); Ok(buffer) @@ -197,6 +198,32 @@ impl<'a> ModuleEncoder<'a> { } } + fn set_module_references(&mut self, module: &mut module::Builder<'_>) { + let references = &self.data.references; + let mut builder = module.reborrow().init_references(); + let mut imported_modules = builder + .reborrow() + .init_imported_modules(references.imported_modules.len() as u32); + for (i, module) in references.imported_modules.iter().enumerate() { + imported_modules.set(i as u32, module); + } + + let mut value_references = builder + .reborrow() + .init_value_references(references.value_references.len() as u32); + for (i, ((module, name), references)) in references.value_references.iter().enumerate() { + let mut builder = value_references.reborrow().get(i as u32); + builder.set_module(module); + builder.set_name(name); + let mut references_builder = + builder.reborrow().init_references(references.len() as u32); + for (i, reference) in references.iter().enumerate() { + let builder = references_builder.reborrow().get(i as u32); + self.build_src_span(builder, *reference); + } + } + } + fn set_version(&mut self, module: &mut module::Builder<'_>) { let mut version = module.reborrow().init_required_version(); version.set_major(self.data.minimum_required_version.major); diff --git a/compiler-core/src/metadata/tests.rs b/compiler-core/src/metadata/tests.rs index 23383fa58c3..94f893b60cb 100644 --- a/compiler-core/src/metadata/tests.rs +++ b/compiler-core/src/metadata/tests.rs @@ -11,9 +11,9 @@ use crate::{ build::Origin, line_numbers::LineNumbers, type_::{ - self, Deprecation, ModuleInterface, Opaque, Type, TypeAliasConstructor, TypeConstructor, - TypeValueConstructor, TypeValueConstructorField, TypeVariantConstructors, ValueConstructor, - ValueConstructorVariant, expression::Implementations, prelude, + self, Deprecation, ModuleInterface, Opaque, References, Type, TypeAliasConstructor, + TypeConstructor, TypeValueConstructor, TypeValueConstructorField, TypeVariantConstructors, + ValueConstructor, ValueConstructorVariant, expression::Implementations, prelude, }, uid::UniqueIdGenerator, }; @@ -68,6 +68,8 @@ fn constant_module(constant: TypedConstant) -> ModuleInterface { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + + references: References::default(), } } @@ -105,6 +107,8 @@ fn empty_module() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + + references: References::default(), }; assert_eq!(roundtrip(&module), module); } @@ -131,6 +135,8 @@ fn with_line_numbers() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + + references: References::default(), }; assert_eq!(roundtrip(&module), module); } @@ -165,6 +171,8 @@ fn module_with_private_type() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + + references: References::default(), }; assert_eq!(roundtrip(&module), module); } @@ -199,6 +207,8 @@ fn module_with_app_type() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + + references: References::default(), }; assert_eq!(roundtrip(&module), module); } @@ -233,6 +243,8 @@ fn module_with_fn_type() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + + references: References::default(), }; assert_eq!(roundtrip(&module), module); } @@ -267,6 +279,8 @@ fn module_with_tuple_type() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + + references: References::default(), }; assert_eq!(roundtrip(&module), module); } @@ -307,6 +321,7 @@ fn module_with_generic_type() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + references: References::default(), } } @@ -347,6 +362,7 @@ fn module_with_type_links() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + references: References::default(), } } @@ -387,6 +403,7 @@ fn module_with_type_constructor_documentation() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + references: References::default(), } } @@ -430,6 +447,7 @@ fn module_with_type_constructor_origin() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + references: References::default(), } } @@ -466,6 +484,8 @@ fn module_type_to_constructors_mapping() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + + references: References::default(), }; assert_eq!(roundtrip(&module), module); @@ -517,6 +537,8 @@ fn module_fn_value() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + + references: References::default(), }; assert_eq!(roundtrip(&module), module); } @@ -569,6 +591,8 @@ fn deprecated_module_fn_value() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + + references: References::default(), }; assert_eq!(roundtrip(&module), module); } @@ -619,6 +643,8 @@ fn private_module_fn_value() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + + references: References::default(), }; assert_eq!(roundtrip(&module), module); @@ -671,6 +697,8 @@ fn module_fn_value_regression() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + + references: References::default(), }; assert_eq!(roundtrip(&module), module); @@ -722,6 +750,8 @@ fn module_fn_value_with_field_map() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + + references: References::default(), }; assert_eq!(roundtrip(&module), module); @@ -768,6 +798,8 @@ fn record_value() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + + references: References::default(), }; assert_eq!(roundtrip(&module), module); @@ -818,6 +850,8 @@ fn record_value_with_field_map() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + + references: References::default(), }; assert_eq!(roundtrip(&module), module); @@ -889,6 +923,8 @@ fn accessors() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + + references: References::default(), }; assert_eq!(roundtrip(&module), module); @@ -960,6 +996,7 @@ fn private_accessors() { minimum_required_version: Version::new(0, 1, 0), type_aliases: HashMap::new(), documentation: Vec::new(), + references: References::default(), }; assert_eq!(roundtrip(&module), module); @@ -1188,6 +1225,8 @@ fn constant_var() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + + references: References::default(), }; assert_eq!(roundtrip(&module), module); @@ -1383,6 +1422,8 @@ fn deprecated_type() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + + references: References::default(), }; assert_eq!(roundtrip(&module), module); } @@ -1433,6 +1474,7 @@ fn module_fn_value_with_external_implementations() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + references: References::default(), }; assert_eq!(roundtrip(&module), module); @@ -1456,6 +1498,7 @@ fn module_containing_echo() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: true, + references: References::default(), }; assert_eq!(roundtrip(&module), module); @@ -1509,6 +1552,8 @@ fn internal_module_fn() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + + references: References::default(), }; assert_eq!(roundtrip(&module), module); @@ -1565,6 +1610,8 @@ fn internal_annotated_module_fn() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + + references: References::default(), }; assert_eq!(roundtrip(&module), module); @@ -1613,6 +1660,8 @@ fn type_variable_ids_in_constructors_are_shared() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + + references: References::default(), }; let expected = HashMap::from([( @@ -1681,6 +1730,7 @@ fn type_with_inferred_variant() { minimum_required_version: Version::new(0, 1, 0), type_aliases: HashMap::new(), documentation: Vec::new(), + references: References::default(), }; assert_eq!(roundtrip(&module), module); } @@ -1715,6 +1765,8 @@ fn module_with_type_aliases() { .into(), documentation: Vec::new(), contains_echo: false, + + references: References::default(), }; assert_eq!(roundtrip(&module), module); } @@ -1741,6 +1793,8 @@ fn module_with_documentation() { "And finally, a third".into(), ], contains_echo: false, + + references: References::default(), }; assert_eq!(roundtrip(&module), module); } @@ -1775,6 +1829,52 @@ fn module_with_opaque_type() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + references: References::default(), + }; + + assert_eq!(roundtrip(&module), module); +} + +#[test] +fn module_with_references() { + let module = ModuleInterface { + warnings: vec![], + is_internal: false, + package: "some_package".into(), + origin: Origin::Src, + name: "a".into(), + types: HashMap::new(), + types_value_constructors: HashMap::new(), + accessors: HashMap::new(), + values: HashMap::new(), + line_numbers: LineNumbers::new(""), + src_path: "some_path".into(), + minimum_required_version: Version::new(0, 1, 0), + type_aliases: HashMap::new(), + documentation: Vec::new(), + contains_echo: false, + references: References { + imported_modules: ["some_module".into(), "some_other_module".into()].into(), + value_references: [ + ( + ("some_module".into(), "some_function".into()), + vec![SrcSpan::new(1, 6), SrcSpan::new(7, 11)], + ), + ( + ("some_other_module".into(), "some_constant".into()), + vec![SrcSpan::new(6, 9), SrcSpan::new(90, 108)], + ), + ( + ("some_other_module".into(), "SomeTypeVariant".into()), + vec![ + SrcSpan::new(26, 35), + SrcSpan::new(152, 204), + SrcSpan::new(0, 8), + ], + ), + ] + .into(), + }, }; assert_eq!(roundtrip(&module), module); diff --git a/compiler-core/src/parse.rs b/compiler-core/src/parse.rs index 7349746da1b..adc4ed1dde5 100644 --- a/compiler-core/src/parse.rs +++ b/compiler-core/src/parse.rs @@ -243,7 +243,6 @@ where type_info: (), definitions, names: Default::default(), - references: Default::default(), }; Ok(Parsed { module, diff --git a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__const_string_concat.snap b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__const_string_concat.snap index 59c29e1eaa5..6b7d2acca51 100644 --- a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__const_string_concat.snap +++ b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__const_string_concat.snap @@ -101,10 +101,6 @@ Parsed { type_variables: {}, local_value_constructors: {}, }, - references: References { - imported_modules: {}, - value_references: {}, - }, }, extra: ModuleExtra { module_comments: [], diff --git a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__deprecation_attribute_on_type_variant.snap b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__deprecation_attribute_on_type_variant.snap index 32f8b4fcb0a..46bf2af06c0 100644 --- a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__deprecation_attribute_on_type_variant.snap +++ b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__deprecation_attribute_on_type_variant.snap @@ -70,10 +70,6 @@ Parsed { type_variables: {}, local_value_constructors: {}, }, - references: References { - imported_modules: {}, - value_references: {}, - }, }, extra: ModuleExtra { module_comments: [], diff --git a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__import_type.snap b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__import_type.snap index 9e7cef8413b..58a85c0f5df 100644 --- a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__import_type.snap +++ b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__import_type.snap @@ -70,10 +70,6 @@ Parsed { type_variables: {}, local_value_constructors: {}, }, - references: References { - imported_modules: {}, - value_references: {}, - }, }, extra: ModuleExtra { module_comments: [], diff --git a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__record_access_no_label.snap b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__record_access_no_label.snap index 2513ad75803..ad0330040fa 100644 --- a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__record_access_no_label.snap +++ b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__record_access_no_label.snap @@ -164,10 +164,6 @@ Parsed { type_variables: {}, local_value_constructors: {}, }, - references: References { - imported_modules: {}, - value_references: {}, - }, }, extra: ModuleExtra { module_comments: [], diff --git a/compiler-core/src/type_.rs b/compiler-core/src/type_.rs index 8471753a05e..aeb8bb34c4c 100644 --- a/compiler-core/src/type_.rs +++ b/compiler-core/src/type_.rs @@ -891,6 +891,7 @@ pub struct ModuleInterface { pub documentation: Vec, /// Wether there's any echo in the module. pub contains_echo: bool, + pub references: References, } impl ModuleInterface { @@ -899,6 +900,12 @@ impl ModuleInterface { } } +#[derive(Debug, Clone, PartialEq, Eq, Default)] +pub struct References { + pub imported_modules: HashSet, + pub value_references: HashMap<(EcoString, EcoString), Vec>, +} + #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Opaque { Opaque, diff --git a/compiler-core/src/type_/prelude.rs b/compiler-core/src/type_/prelude.rs index 63eeee10545..abc7e74256b 100644 --- a/compiler-core/src/type_/prelude.rs +++ b/compiler-core/src/type_/prelude.rs @@ -9,7 +9,7 @@ use crate::{ }; use super::{ - ModuleInterface, Opaque, Type, TypeConstructor, TypeValueConstructor, + ModuleInterface, Opaque, References, Type, TypeConstructor, TypeValueConstructor, TypeValueConstructorField, TypeVar, TypeVariantConstructors, ValueConstructor, ValueConstructorVariant, }; @@ -245,6 +245,7 @@ pub fn build_prelude(ids: &UniqueIdGenerator) -> ModuleInterface { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + references: References::default(), }; for t in PreludeType::iter() { diff --git a/compiler-core/src/type_/tests.rs b/compiler-core/src/type_/tests.rs index 271d40cf7d6..2cfe8913c3d 100644 --- a/compiler-core/src/type_/tests.rs +++ b/compiler-core/src/type_/tests.rs @@ -786,7 +786,6 @@ fn infer_module_type_retention_test() { definitions: vec![], type_info: (), names: Default::default(), - references: Default::default(), }; let direct_dependencies = HashMap::from_iter(vec![]); let ids = UniqueIdGenerator::new(); @@ -887,6 +886,7 @@ fn infer_module_type_retention_test() { type_aliases: HashMap::new(), documentation: Vec::new(), contains_echo: false, + references: References::default() } ); } From 5e00fad4541a6eebfb3383cce788881d1ff8a870 Mon Sep 17 00:00:00 2001 From: GearsDatapacks Date: Sun, 9 Mar 2025 17:38:35 +0000 Subject: [PATCH 26/27] Add call graph to reference tracking --- compiler-core/src/analyse.rs | 12 ++++-- compiler-core/src/analyse/imports.rs | 4 +- compiler-core/src/lib.rs | 1 + compiler-core/src/reference.rs | 60 ++++++++++++++++++++++++++ compiler-core/src/type_/environment.rs | 12 ++---- compiler-core/src/type_/expression.rs | 5 ++- compiler-core/src/type_/pattern.rs | 2 +- 7 files changed, 78 insertions(+), 18 deletions(-) create mode 100644 compiler-core/src/reference.rs diff --git a/compiler-core/src/analyse.rs b/compiler-core/src/analyse.rs index 0af316e7568..1ca0ece012e 100644 --- a/compiler-core/src/analyse.rs +++ b/compiler-core/src/analyse.rs @@ -342,7 +342,7 @@ impl<'a, A> ModuleAnalyzer<'a, A> { contains_echo: echo_found, references: References { imported_modules: env.imported_modules.into_keys().collect(), - value_references: env.references, + value_references: env.references.into_locations(), }, }, names: type_names, @@ -426,7 +426,7 @@ impl<'a, A> ModuleAnalyzer<'a, A> { ); environment.insert_module_value(name.clone(), variant); - environment.register_reference( + environment.references.register_reference( environment.current_module.clone(), name.clone(), name_location, @@ -527,6 +527,10 @@ impl<'a, A> ModuleAnalyzer<'a, A> { .map(|(a, t)| a.set_type(t.clone())) .collect_vec(); + environment + .references + .enter_function(environment.current_module.clone(), name.clone()); + // Infer the type using the preregistered args + return types as a starting point let result = environment.in_new_scope(&mut self.problems, |environment, problems| { let mut expr_typer = ExprTyper::new(environment, definition, problems); @@ -645,7 +649,7 @@ impl<'a, A> ModuleAnalyzer<'a, A> { deprecation.clone(), ); - environment.register_reference( + environment.references.register_reference( environment.current_module.clone(), name.clone(), name_location, @@ -1096,7 +1100,7 @@ impl<'a, A> ModuleAnalyzer<'a, A> { }, ); - environment.register_reference( + environment.references.register_reference( environment.current_module.clone(), constructor.name.clone(), constructor.name_location, diff --git a/compiler-core/src/analyse/imports.rs b/compiler-core/src/analyse/imports.rs index 36d641bb113..1d036165050 100644 --- a/compiler-core/src/analyse/imports.rs +++ b/compiler-core/src/analyse/imports.rs @@ -171,7 +171,7 @@ impl<'context, 'problems> Importer<'context, 'problems> { name.clone(), used_name.clone(), ); - self.environment.register_reference( + self.environment.references.register_reference( module.clone(), import_name.clone(), import.imported_name_location, @@ -185,7 +185,7 @@ impl<'context, 'problems> Importer<'context, 'problems> { location, self.problems, ); - self.environment.register_reference( + self.environment.references.register_reference( module.clone(), import_name.clone(), import.imported_name_location, diff --git a/compiler-core/src/lib.rs b/compiler-core/src/lib.rs index 34b9e8b467c..1bce1714a0d 100644 --- a/compiler-core/src/lib.rs +++ b/compiler-core/src/lib.rs @@ -95,6 +95,7 @@ mod call_graph; mod dep_tree; mod exhaustiveness; pub(crate) mod graph; +mod reference; pub use error::{Error, Result}; pub use warning::Warning; diff --git a/compiler-core/src/reference.rs b/compiler-core/src/reference.rs new file mode 100644 index 00000000000..4c8d21f5fd0 --- /dev/null +++ b/compiler-core/src/reference.rs @@ -0,0 +1,60 @@ +use std::collections::HashMap; + +use crate::ast::SrcSpan; +use ecow::EcoString; +use petgraph::{ + Directed, + stable_graph::{NodeIndex, StableGraph}, +}; + +#[derive(Debug, Default)] +pub struct ReferenceTracker { + /// A call-graph which tracks which values are referenced by which other value, + /// used for dead code detection. + graph: StableGraph<(), (), Directed>, + names: HashMap<(EcoString, EcoString), NodeIndex>, + current_function: NodeIndex, + + /// The locations of the references to each value in this module, used for + /// renaming and go-to reference. + reference_locations: HashMap<(EcoString, EcoString), Vec>, +} + +impl ReferenceTracker { + pub fn new() -> Self { + Self::default() + } +} + +impl ReferenceTracker { + pub fn into_locations(self) -> HashMap<(EcoString, EcoString), Vec> { + self.reference_locations + } + + fn get_or_create_node(&mut self, module: EcoString, name: EcoString) -> NodeIndex { + let key: (EcoString, EcoString) = (module, name); + match self.names.get(&key) { + Some(index) => *index, + None => { + let index = self.graph.add_node(()); + _ = self.names.insert(key, index); + index + } + } + } + + pub fn enter_function(&mut self, module: EcoString, name: EcoString) { + self.current_function = self.get_or_create_node(module, name); + } + + pub fn register_reference(&mut self, module: EcoString, name: EcoString, location: SrcSpan) { + let target = self.get_or_create_node(module.clone(), name.clone()); + _ = self + .reference_locations + .entry((module, name)) + .or_default() + .push(location); + + _ = self.graph.add_edge(self.current_function, target, ()); + } +} diff --git a/compiler-core/src/type_/environment.rs b/compiler-core/src/type_/environment.rs index c5768f27a65..90d13d65063 100644 --- a/compiler-core/src/type_/environment.rs +++ b/compiler-core/src/type_/environment.rs @@ -5,6 +5,7 @@ use crate::{ ast::{PIPE_VARIABLE, Publicity}, build::Target, error::edit_distance, + reference::ReferenceTracker, uid::UniqueIdGenerator, }; @@ -70,7 +71,7 @@ pub struct Environment<'a> { /// Wether we ran into an `echo` or not while analysing the current module. pub echo_found: bool, - pub references: HashMap<(EcoString, EcoString), Vec>, + pub references: ReferenceTracker, } impl<'a> Environment<'a> { @@ -124,7 +125,7 @@ impl<'a> Environment<'a> { names, module_type_aliases: HashMap::new(), echo_found: false, - references: HashMap::new(), + references: ReferenceTracker::new(), } } } @@ -810,13 +811,6 @@ impl Environment<'_> { .and_then(|type_constructors| type_constructors.variants.get(variant_index as usize)) .map(|variant| &variant.name) } - - pub fn register_reference(&mut self, module: EcoString, name: EcoString, location: SrcSpan) { - self.references - .entry((module, name)) - .or_default() - .push(location); - } } #[derive(Debug)] diff --git a/compiler-core/src/type_/expression.rs b/compiler-core/src/type_/expression.rs index 60207875b4c..e6233387b48 100644 --- a/compiler-core/src/type_/expression.rs +++ b/compiler-core/src/type_/expression.rs @@ -1102,7 +1102,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { // We only register the reference here, if we know that this is a module access. // Otherwise we would register module access even if we are actually accessing // the field on a record - self.environment.register_reference( + self.environment.references.register_reference( module_name.clone(), label.clone(), SrcSpan::new(field_start, location.end), @@ -2331,7 +2331,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { constructor, } => match constructor { ModuleValueConstructor::Constant { literal, .. } => { - self.environment.register_reference( + self.environment.references.register_reference( module_name.clone(), label.clone(), location, @@ -3045,6 +3045,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { | ValueConstructorVariant::Record { name, module, .. } | ValueConstructorVariant::ModuleConstant { name, module, .. } => self .environment + .references .register_reference(module.clone(), name.clone(), location), ValueConstructorVariant::LocalVariable { .. } | ValueConstructorVariant::LocalConstant { .. } => {} diff --git a/compiler-core/src/type_/pattern.rs b/compiler-core/src/type_/pattern.rs index 42c5f479e1e..6ba7eabd75f 100644 --- a/compiler-core/src/type_/pattern.rs +++ b/compiler-core/src/type_/pattern.rs @@ -817,7 +817,7 @@ impl<'a, 'b> PatternTyper<'a, 'b> { } } - self.environment.register_reference( + self.environment.references.register_reference( constructor.module.clone(), constructor.name.clone(), name_location, From d5aed34c035e1333489ffd59f147bdd6e858310b Mon Sep 17 00:00:00 2001 From: GearsDatapacks Date: Mon, 10 Mar 2025 13:32:36 +0000 Subject: [PATCH 27/27] Clippy --- compiler-core/src/reference.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler-core/src/reference.rs b/compiler-core/src/reference.rs index 4c8d21f5fd0..47406d9001d 100644 --- a/compiler-core/src/reference.rs +++ b/compiler-core/src/reference.rs @@ -49,8 +49,7 @@ impl ReferenceTracker { pub fn register_reference(&mut self, module: EcoString, name: EcoString, location: SrcSpan) { let target = self.get_or_create_node(module.clone(), name.clone()); - _ = self - .reference_locations + self.reference_locations .entry((module, name)) .or_default() .push(location);