Skip to content

Commit

Permalink
Cache reference information
Browse files Browse the repository at this point in the history
  • Loading branch information
GearsDatapacks committed Mar 4, 2025
1 parent f6effbb commit 237dbeb
Show file tree
Hide file tree
Showing 18 changed files with 864 additions and 109 deletions.
684 changes: 638 additions & 46 deletions compiler-core/generated/schema_capnp.rs

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions compiler-core/schema.capnp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
20 changes: 10 additions & 10 deletions compiler-core/src/analyse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand All @@ -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},
Expand Down Expand Up @@ -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()) {
Expand Down
8 changes: 0 additions & 8 deletions compiler-core/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -51,7 +50,6 @@ pub struct Module<Info, Statements> {
pub type_info: Info,
pub definitions: Vec<Statements>,
pub names: Names,
pub references: References,
}

impl TypedModule {
Expand All @@ -68,12 +66,6 @@ impl TypedModule {
}
}

#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct References {
pub imported_modules: HashSet<EcoString>,
pub value_references: HashMap<(EcoString, EcoString), Vec<SrcSpan>>,
}

/// The `@target(erlang)` and `@target(javascript)` attributes can be used to
/// mark a definition as only being for a specific target.
///
Expand Down
1 change: 1 addition & 0 deletions compiler-core/src/build/package_loader/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
21 changes: 14 additions & 7 deletions compiler-core/src/language_server/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,8 @@ where
&params,
module_name,
name,
&this.compiler.modules,
this.compiler.project_compiler.get_importable_modules(),
&this.compiler.sources,
Named::Function,
),
Located::Expression(TypedExpr::ModuleSelect {
Expand All @@ -782,7 +783,8 @@ where
&params,
module_name,
label,
&this.compiler.modules,
this.compiler.project_compiler.get_importable_modules(),
&this.compiler.sources,
Named::Function,
),
Located::ModuleStatement(
Expand All @@ -795,7 +797,8 @@ where
&params,
&module.name,
name,
&this.compiler.modules,
this.compiler.project_compiler.get_importable_modules(),
&this.compiler.sources,
Named::Function,
),
Located::Expression(TypedExpr::Var {
Expand All @@ -814,7 +817,8 @@ where
&params,
module_name,
name,
&this.compiler.modules,
this.compiler.project_compiler.get_importable_modules(),
&this.compiler.sources,
Named::CustomTypeVariant,
),
Located::Expression(TypedExpr::ModuleSelect {
Expand All @@ -826,15 +830,17 @@ where
&params,
module_name,
label,
&this.compiler.modules,
this.compiler.project_compiler.get_importable_modules(),
&this.compiler.sources,
Named::CustomTypeVariant,
),
Located::VariantConstructorDefinition(RecordConstructor { name, .. }) => {
rename_module_value(
&params,
&module.name,
name,
&this.compiler.modules,
this.compiler.project_compiler.get_importable_modules(),
&this.compiler.sources,
Named::CustomTypeVariant,
)
}
Expand All @@ -845,7 +851,8 @@ where
&params,
&constructor.module,
&constructor.name,
&this.compiler.modules,
this.compiler.project_compiler.get_importable_modules(),
&this.compiler.sources,
Named::CustomTypeVariant,
),
_ => None,
Expand Down
25 changes: 14 additions & 11 deletions compiler-core/src/language_server/rename.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<TextEdit>) -> WorkspaceEdit {
let mut changes = HashMap::new();
Expand Down Expand Up @@ -69,7 +69,8 @@ pub fn rename_module_value(
params: &RenameParams,
module_name: &EcoString,
name: &EcoString,
modules: &HashMap<EcoString, Module>,
modules: &im::HashMap<EcoString, ModuleInterface>,
sources: &HashMap<EcoString, ModuleSourceInformation>,
name_kind: Named,
) -> Option<WorkspaceEdit> {
if name::check_name_case(
Expand All @@ -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,
Expand All @@ -108,29 +112,28 @@ 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()))
else {
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;
};

Expand Down
40 changes: 35 additions & 5 deletions compiler-core/src/metadata/module_decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {{
Expand Down Expand Up @@ -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()?)?,
})
}

Expand All @@ -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<References> {
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<HashSet<EcoString>> {
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<HashMap<(EcoString, EcoString), Vec<SrcSpan>>> {
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<'_>,
Expand Down
27 changes: 27 additions & 0 deletions compiler-core/src/metadata/module_encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 237dbeb

Please sign in to comment.