diff --git a/Cargo.lock b/Cargo.lock index fe8d4ac9..f8eb30b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2231,7 +2231,9 @@ dependencies = [ "lld_rs", "mun_abi", "mun_codegen_macros", + "mun_db", "mun_hir", + "mun_hir_input", "mun_libloader", "mun_paths", "mun_runtime", @@ -2266,8 +2268,10 @@ dependencies = [ "lockfile", "log", "mun_codegen", + "mun_db", "mun_diagnostics", "mun_hir", + "mun_hir_input", "mun_paths", "mun_project", "mun_syntax", @@ -2291,6 +2295,10 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "mun_db" +version = "0.6.0-dev" + [[package]] name = "mun_diagnostics" version = "0.6.0-dev" @@ -2310,6 +2318,8 @@ dependencies = [ "insta", "itertools 0.12.1", "la-arena", + "mun_db", + "mun_hir_input", "mun_paths", "mun_syntax", "mun_target", @@ -2322,6 +2332,19 @@ dependencies = [ "text_trees", ] +[[package]] +name = "mun_hir_input" +version = "0.6.0-dev" +dependencies = [ + "insta", + "itertools 0.12.1", + "la-arena", + "mun_paths", + "mun_syntax", + "rustc-hash", + "salsa", +] + [[package]] name = "mun_language_server" version = "0.6.0-dev" @@ -2333,8 +2356,10 @@ dependencies = [ "log", "lsp-server", "lsp-types", + "mun_db", "mun_diagnostics", "mun_hir", + "mun_hir_input", "mun_paths", "mun_project", "mun_syntax", @@ -2481,6 +2506,7 @@ dependencies = [ "itertools 0.12.1", "mun_compiler", "mun_hir", + "mun_hir_input", "mun_paths", "mun_runtime", "tempfile", diff --git a/crates/mun_codegen/Cargo.toml b/crates/mun_codegen/Cargo.toml index 9aa7a606..5047cbee 100644 --- a/crates/mun_codegen/Cargo.toml +++ b/crates/mun_codegen/Cargo.toml @@ -19,7 +19,9 @@ apple-codesign = { workspace = true } array-init = { workspace = true } by_address = { workspace = true } bytemuck = { workspace = true } +mun_db = { version = "0.6.0-dev", path = "../mun_db" } mun_hir = { version = "0.6.0-dev", path = "../mun_hir" } +mun_hir_input = { version = "0.6.0-dev", path = "../mun_hir_input" } inkwell = { workspace = true, features = ["llvm14-0", "target-x86", "target-aarch64"] } itertools = { workspace = true } mun_codegen_macros = { version = "0.6.0-dev", path = "../mun_codegen_macros" } diff --git a/crates/mun_codegen/src/db.rs b/crates/mun_codegen/src/db.rs index 83659fc1..7b9fa3f3 100644 --- a/crates/mun_codegen/src/db.rs +++ b/crates/mun_codegen/src/db.rs @@ -14,9 +14,7 @@ use crate::{AssemblyIr, ModuleGroupId, ModulePartition, TargetAssembly}; /// generation cache is pretty granular there is still a benefit to not having /// to recompile assemblies if not required. #[salsa::query_group(CodeGenDatabaseStorage)] -pub trait CodeGenDatabase: - mun_hir::HirDatabase + mun_hir::Upcast -{ +pub trait CodeGenDatabase: mun_hir::HirDatabase + mun_db::Upcast { /// Set the optimization level used to generate assemblies #[salsa::input] fn optimization_level(&self) -> inkwell::OptimizationLevel; diff --git a/crates/mun_codegen/src/mock.rs b/crates/mun_codegen/src/mock.rs index 95277ac2..ddf4ac72 100644 --- a/crates/mun_codegen/src/mock.rs +++ b/crates/mun_codegen/src/mock.rs @@ -1,6 +1,7 @@ use std::sync::Arc; -use mun_hir::{FileId, HirDatabase, SourceDatabase, SourceRoot, SourceRootId}; +use mun_hir::HirDatabase; +use mun_hir_input::{FileId, PackageSet, SourceDatabase, SourceRoot, SourceRootId}; use mun_paths::RelativePathBuf; use mun_target::spec::Target; use parking_lot::Mutex; @@ -13,7 +14,7 @@ use crate::{ /// A mock implementation of the IR database. It can be used to set up a simple /// test case. #[salsa::database( - mun_hir::SourceDatabaseStorage, + mun_hir_input::SourceDatabaseStorage, mun_hir::AstDatabaseStorage, mun_hir::InternDatabaseStorage, mun_hir::DefDatabaseStorage, @@ -34,31 +35,31 @@ impl salsa::Database for MockDatabase { } } -impl mun_hir::Upcast for MockDatabase { +impl mun_db::Upcast for MockDatabase { fn upcast(&self) -> &(dyn mun_hir::AstDatabase + 'static) { self } } -impl mun_hir::Upcast for MockDatabase { - fn upcast(&self) -> &(dyn mun_hir::SourceDatabase + 'static) { +impl mun_db::Upcast for MockDatabase { + fn upcast(&self) -> &(dyn SourceDatabase + 'static) { self } } -impl mun_hir::Upcast for MockDatabase { +impl mun_db::Upcast for MockDatabase { fn upcast(&self) -> &(dyn mun_hir::DefDatabase + 'static) { self } } -impl mun_hir::Upcast for MockDatabase { +impl mun_db::Upcast for MockDatabase { fn upcast(&self) -> &(dyn mun_hir::HirDatabase + 'static) { self } } -impl mun_hir::Upcast for MockDatabase { +impl mun_db::Upcast for MockDatabase { fn upcast(&self) -> &(dyn CodeGenDatabase + 'static) { self } @@ -93,7 +94,7 @@ impl MockDatabase { db.set_source_root(source_root_id, Arc::new(source_root)); - let mut packages = mun_hir::PackageSet::default(); + let mut packages = PackageSet::default(); packages.add_package(source_root_id); db.set_packages(Arc::new(packages)); diff --git a/crates/mun_codegen/src/module_group.rs b/crates/mun_codegen/src/module_group.rs index 25b301bc..507fb679 100644 --- a/crates/mun_codegen/src/module_group.rs +++ b/crates/mun_codegen/src/module_group.rs @@ -7,6 +7,7 @@ use std::{ }; use mun_hir::{HasVisibility, HirDatabase}; +use mun_hir_input::FileId; use rustc_hash::{FxHashMap, FxHashSet}; /// A `ModuleGroup` describes a grouping of modules @@ -118,10 +119,7 @@ impl ModuleGroup { } /// Returns the `mun_hir::FileId`s that are included in this module group. - pub fn files<'s>( - &'s self, - db: &'s dyn HirDatabase, - ) -> impl Iterator + 's { + pub fn files<'s>(&'s self, db: &'s dyn HirDatabase) -> impl Iterator + 's { self.ordered_modules .iter() .filter_map(move |module| module.file_id(db)) diff --git a/crates/mun_codegen/src/module_partition.rs b/crates/mun_codegen/src/module_partition.rs index 768d7c74..62405236 100644 --- a/crates/mun_codegen/src/module_partition.rs +++ b/crates/mun_codegen/src/module_partition.rs @@ -1,5 +1,6 @@ use std::{ops::Index, sync::Arc}; +use mun_hir_input::FileId; use rustc_hash::FxHashMap; use crate::{CodeGenDatabase, ModuleGroup}; @@ -14,7 +15,7 @@ pub struct ModuleGroupId(usize); pub struct ModulePartition { groups: Vec, module_to_group: FxHashMap, - file_to_group: FxHashMap, + file_to_group: FxHashMap, } impl ModulePartition { @@ -49,7 +50,7 @@ impl ModulePartition { } /// Returns the group to which the specified module belongs. - pub fn group_for_file(&self, file: mun_hir::FileId) -> Option { + pub fn group_for_file(&self, file: FileId) -> Option { self.file_to_group.get(&file).copied() } diff --git a/crates/mun_codegen/src/test.rs b/crates/mun_codegen/src/test.rs index 35571fcf..9cc86c59 100644 --- a/crates/mun_codegen/src/test.rs +++ b/crates/mun_codegen/src/test.rs @@ -1,9 +1,9 @@ use std::cell::RefCell; use inkwell::{context::Context, OptimizationLevel}; -use mun_hir::{ - diagnostics::DiagnosticSink, with_fixture::WithFixture, HirDatabase, SourceDatabase, Upcast, -}; +use mun_db::Upcast; +use mun_hir::{diagnostics::DiagnosticSink, HirDatabase}; +use mun_hir_input::{SourceDatabase, WithFixture}; use mun_target::spec::Target; use crate::{ diff --git a/crates/mun_compiler/Cargo.toml b/crates/mun_compiler/Cargo.toml index eb1baf79..3b1dd20d 100644 --- a/crates/mun_compiler/Cargo.toml +++ b/crates/mun_compiler/Cargo.toml @@ -15,6 +15,8 @@ license.workspace = true [dependencies] mun_codegen = { version = "0.6.0-dev", path = "../mun_codegen" } mun_syntax = { version = "0.6.0-dev", path = "../mun_syntax" } +mun_db = { version = "0.6.0-dev", path = "../mun_db" } +mun_hir_input = { version = "0.6.0-dev", path = "../mun_hir_input" } mun_hir = { version = "0.6.0-dev", path = "../mun_hir" } mun_paths = { version = "0.6.0-dev", path = "../mun_paths" } mun_target = { version = "0.6.0-dev", path = "../mun_target" } diff --git a/crates/mun_compiler/src/db.rs b/crates/mun_compiler/src/db.rs index 3cff1a78..53104acb 100644 --- a/crates/mun_compiler/src/db.rs +++ b/crates/mun_compiler/src/db.rs @@ -1,11 +1,13 @@ use mun_codegen::{CodeGenDatabase, CodeGenDatabaseStorage}; -use mun_hir::{salsa, HirDatabase, Upcast}; +use mun_db::Upcast; +use mun_hir::{salsa, HirDatabase}; +use mun_hir_input::SourceDatabase; use crate::Config; /// A compiler database is a salsa database that enables increment compilation. #[salsa::database( - mun_hir::SourceDatabaseStorage, + mun_hir_input::SourceDatabaseStorage, mun_hir::InternDatabaseStorage, mun_hir::AstDatabaseStorage, mun_hir::DefDatabaseStorage, @@ -22,8 +24,8 @@ impl Upcast for CompilerDatabase { } } -impl Upcast for CompilerDatabase { - fn upcast(&self) -> &(dyn mun_hir::SourceDatabase + 'static) { +impl Upcast for CompilerDatabase { + fn upcast(&self) -> &(dyn SourceDatabase + 'static) { self } } diff --git a/crates/mun_compiler/src/diagnostics_snippets.rs b/crates/mun_compiler/src/diagnostics_snippets.rs index eb27a05a..587ffda5 100644 --- a/crates/mun_compiler/src/diagnostics_snippets.rs +++ b/crates/mun_compiler/src/diagnostics_snippets.rs @@ -2,7 +2,8 @@ use std::{collections::HashMap, sync::Arc}; use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation}; use mun_diagnostics::DiagnosticForWith; -use mun_hir::{line_index::LineIndex, FileId, HirDatabase}; +use mun_hir::HirDatabase; +use mun_hir_input::{FileId, LineIndex}; use mun_paths::RelativePathBuf; use mun_syntax::SyntaxError; diff --git a/crates/mun_compiler/src/driver.rs b/crates/mun_compiler/src/driver.rs index 8417d0ac..ec9bb3b8 100644 --- a/crates/mun_compiler/src/driver.rs +++ b/crates/mun_compiler/src/driver.rs @@ -2,10 +2,8 @@ //! compilation by retaining state from previous compilation. use mun_codegen::{AssemblyIr, CodeGenDatabase, ModuleGroup, TargetAssembly}; -use mun_hir::{ - AstDatabase, DiagnosticSink, FileId, Module, PackageSet, SourceDatabase, SourceRoot, - SourceRootId, Upcast, -}; +use mun_hir::{AstDatabase, DiagnosticSink, Module}; +use mun_hir_input::{FileId, PackageSet, SourceDatabase, SourceRoot, SourceRootId}; use mun_paths::RelativePathBuf; use crate::{ @@ -25,6 +23,7 @@ use std::{ time::Duration, }; +use mun_db::Upcast; use mun_project::{Package, LOCKFILE_NAME}; use walkdir::WalkDir; diff --git a/crates/mun_compiler/src/lib.rs b/crates/mun_compiler/src/lib.rs index 7bcd5222..69fbce53 100644 --- a/crates/mun_compiler/src/lib.rs +++ b/crates/mun_compiler/src/lib.rs @@ -14,7 +14,7 @@ use std::{ pub use annotate_snippets::AnnotationType; pub use mun_codegen::OptimizationLevel; -pub use mun_hir::FileId; +pub use mun_hir_input::FileId; pub use mun_paths::{RelativePath, RelativePathBuf}; use mun_project::Package; pub use mun_target::spec::Target; diff --git a/crates/mun_db/Cargo.toml b/crates/mun_db/Cargo.toml new file mode 100644 index 00000000..3970a8d0 --- /dev/null +++ b/crates/mun_db/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "mun_db" +description = "Salsa database utilities for everything mun related." +version.workspace = true +authors.workspace = true +edition.workspace = true +documentation.workspace = true +readme.workspace = true +homepage.workspace = true +repository.workspace = true +license.workspace = true +categories.workspace = true + +[dependencies] diff --git a/crates/mun_db/src/lib.rs b/crates/mun_db/src/lib.rs new file mode 100644 index 00000000..3e1038c5 --- /dev/null +++ b/crates/mun_db/src/lib.rs @@ -0,0 +1,6 @@ +//! This crate provides utilitiy functions to be used alongside salsa databases +//! used by mun. + +pub trait Upcast { + fn upcast(&self) -> &T; +} diff --git a/crates/mun_hir/Cargo.toml b/crates/mun_hir/Cargo.toml index e9449c6c..c8e6a388 100644 --- a/crates/mun_hir/Cargo.toml +++ b/crates/mun_hir/Cargo.toml @@ -17,6 +17,8 @@ la-arena = { workspace = true } mun_syntax = { version = "0.6.0-dev", path = "../mun_syntax" } mun_target = { version = "0.6.0-dev", path = "../mun_target" } mun_paths = { version = "0.6.0-dev", path="../mun_paths" } +mun_db = { version = "0.6.0-dev", path="../mun_db" } +mun_hir_input = { version = "0.6.0-dev", path="../mun_hir_input" } drop_bomb = { workspace = true } either = { workspace = true } ena = { workspace = true } diff --git a/crates/mun_hir/src/code_model/function.rs b/crates/mun_hir/src/code_model/function.rs index f58dd223..8035f1be 100644 --- a/crates/mun_hir/src/code_model/function.rs +++ b/crates/mun_hir/src/code_model/function.rs @@ -1,5 +1,6 @@ use std::{iter::once, sync::Arc}; +use mun_hir_input::FileId; use mun_syntax::{ast, ast::TypeAscriptionOwner}; use super::Module; @@ -12,7 +13,7 @@ use crate::{ resolve::HasResolver, type_ref::{LocalTypeRefId, TypeRefMap, TypeRefSourceMap}, visibility::RawVisibility, - Body, DefDatabase, DiagnosticSink, FileId, HasSource, HasVisibility, HirDatabase, InFile, + Body, DefDatabase, DiagnosticSink, HasSource, HasVisibility, HirDatabase, InFile, InferenceResult, Name, Pat, Ty, Visibility, }; @@ -117,8 +118,7 @@ impl Function { .path_to_root(db) .into_iter() .filter_map(|module| module.name(db)) - .chain(once(self.name(db))) - .map(|name| name.to_string()), + .chain(once(self.name(db).to_string())), String::from("::"), ) .collect() diff --git a/crates/mun_hir/src/code_model/impl.rs b/crates/mun_hir/src/code_model/impl.rs index bf5c43dd..5c3b328a 100644 --- a/crates/mun_hir/src/code_model/impl.rs +++ b/crates/mun_hir/src/code_model/impl.rs @@ -1,11 +1,13 @@ use std::sync::Arc; +use mun_hir_input::FileId; + use crate::{ has_module::HasModule, ids::{AssocItemId, FunctionLoc, ImplId, Intern, ItemContainerId, Lookup}, item_tree::{AssociatedItem, ItemTreeId}, type_ref::{LocalTypeRefId, TypeRefMap, TypeRefMapBuilder, TypeRefSourceMap}, - DefDatabase, FileId, Function, HirDatabase, ItemLoc, Module, Package, Ty, + DefDatabase, Function, HirDatabase, ItemLoc, Module, Package, Ty, }; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] diff --git a/crates/mun_hir/src/code_model/module.rs b/crates/mun_hir/src/code_model/module.rs index f2f31e91..a5873757 100644 --- a/crates/mun_hir/src/code_model/module.rs +++ b/crates/mun_hir/src/code_model/module.rs @@ -1,9 +1,7 @@ +use mun_hir_input::{FileId, ModuleId}; + use super::{r#impl::Impl, AssocItem, Function, Package, Struct, TypeAlias}; -use crate::{ - ids::{ItemDefinitionId, ModuleId}, - primitive_type::PrimitiveType, - DiagnosticSink, FileId, HirDatabase, Name, -}; +use crate::{ids::ItemDefinitionId, primitive_type::PrimitiveType, DiagnosticSink, HirDatabase}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] pub struct Module { @@ -45,7 +43,7 @@ impl Module { } /// Returns the name of this module or None if this is the root module - pub fn name(self, db: &dyn HirDatabase) -> Option { + pub fn name(self, db: &dyn HirDatabase) -> Option { let module_tree = db.module_tree(self.id.package); let parent = module_tree[self.id.local_id].parent?; module_tree[parent] @@ -144,8 +142,7 @@ impl Module { itertools::Itertools::intersperse( self.path_to_root(db) .iter() - .filter_map(|&module| module.name(db)) - .map(|name| name.to_string()), + .filter_map(|&module| module.name(db)), String::from("::"), ) .collect() diff --git a/crates/mun_hir/src/code_model/package.rs b/crates/mun_hir/src/code_model/package.rs index b78b3007..4a0f9b58 100644 --- a/crates/mun_hir/src/code_model/package.rs +++ b/crates/mun_hir/src/code_model/package.rs @@ -1,5 +1,7 @@ +use mun_hir_input::{ModuleId, PackageId}; + use super::Module; -use crate::{HirDatabase, ModuleId, PackageId}; +use crate::HirDatabase; /// A `Package` describes a single package. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] diff --git a/crates/mun_hir/src/code_model/struct.rs b/crates/mun_hir/src/code_model/struct.rs index 960b4d18..eb34466d 100644 --- a/crates/mun_hir/src/code_model/struct.rs +++ b/crates/mun_hir/src/code_model/struct.rs @@ -2,6 +2,7 @@ use std::{fmt, iter::once, sync::Arc}; pub use ast::StructMemoryKind; use la_arena::{Arena, Idx}; +use mun_hir_input::FileId; use mun_syntax::{ ast, ast::{NameOwner, TypeAscriptionOwner, VisibilityOwner}, @@ -17,7 +18,7 @@ use crate::{ ty::lower::LowerTyMap, type_ref::{LocalTypeRefId, TypeRefMap, TypeRefSourceMap}, visibility::RawVisibility, - DefDatabase, DiagnosticSink, FileId, HasVisibility, HirDatabase, Name, Ty, Visibility, + DefDatabase, DiagnosticSink, HasVisibility, HirDatabase, Name, Ty, Visibility, }; pub(crate) mod validator; @@ -92,8 +93,7 @@ impl Struct { .path_to_root(db) .into_iter() .filter_map(|module| module.name(db)) - .chain(once(self.name(db))) - .map(|name| name.to_string()), + .chain(once(self.name(db).to_string())), String::from("::"), ) .collect() diff --git a/crates/mun_hir/src/code_model/struct/validator.rs b/crates/mun_hir/src/code_model/struct/validator.rs index 742acf3d..59a642eb 100644 --- a/crates/mun_hir/src/code_model/struct/validator.rs +++ b/crates/mun_hir/src/code_model/struct/validator.rs @@ -1,7 +1,9 @@ +use mun_hir_input::FileId; + use super::Struct; use crate::{ diagnostics::ExportedPrivate, resolve::HasResolver, visibility::RawVisibility, DiagnosticSink, - FileId, HasVisibility, HirDatabase, Ty, Visibility, + HasVisibility, HirDatabase, Ty, Visibility, }; #[cfg(test)] diff --git a/crates/mun_hir/src/code_model/type_alias.rs b/crates/mun_hir/src/code_model/type_alias.rs index 2422e0f2..6b60f3fa 100644 --- a/crates/mun_hir/src/code_model/type_alias.rs +++ b/crates/mun_hir/src/code_model/type_alias.rs @@ -1,5 +1,7 @@ use std::sync::Arc; +use mun_hir_input::FileId; + use super::Module; use crate::{ expr::validator::TypeAliasValidator, @@ -9,7 +11,7 @@ use crate::{ ty::lower::LowerTyMap, type_ref::{LocalTypeRefId, TypeRefMap, TypeRefSourceMap}, visibility::RawVisibility, - DefDatabase, DiagnosticSink, FileId, HasVisibility, HirDatabase, Name, Ty, TyKind, Visibility, + DefDatabase, DiagnosticSink, HasVisibility, HirDatabase, Name, Ty, TyKind, Visibility, }; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] diff --git a/crates/mun_hir/src/db.rs b/crates/mun_hir/src/db.rs index e0866180..9812d002 100644 --- a/crates/mun_hir/src/db.rs +++ b/crates/mun_hir/src/db.rs @@ -2,7 +2,8 @@ use std::sync::Arc; -use mun_paths::RelativePathBuf; +use mun_db::Upcast; +use mun_hir_input::{FileId, PackageId, SourceDatabase}; use mun_syntax::{ast, Parse, SourceFile}; use mun_target::{abi, spec::Target}; @@ -11,56 +12,14 @@ use crate::{ expr::BodySourceMap, ids, ids::{DefWithBodyId, FunctionId, ImplId}, - input::{SourceRoot, SourceRootId}, item_tree::{self, ItemTree}, - line_index::LineIndex, method_resolution::InherentImpls, - module_tree::ModuleTree, name_resolution::Namespace, package_defs::PackageDefs, ty::{lower::LowerTyMap, CallableDef, FnSig, InferenceResult, Ty, TypableDef}, - visibility, AstIdMap, Body, ExprScopes, FileId, PackageId, PackageSet, Struct, TypeAlias, - Visibility, + visibility, AstIdMap, Body, ExprScopes, Struct, TypeAlias, Visibility, }; -// TODO(bas): In the future maybe move this to a seperate crate (mun_db?) -pub trait Upcast { - fn upcast(&self) -> &T; -} - -/// Database which stores all significant input facts: source code and project -/// model. -#[salsa::query_group(SourceDatabaseStorage)] -#[allow(clippy::trait_duplication_in_bounds)] -pub trait SourceDatabase: salsa::Database { - /// Text of the file. - #[salsa::input] - fn file_text(&self, file_id: FileId) -> Arc; - - /// Source root of a file - #[salsa::input] - fn file_source_root(&self, file_id: FileId) -> SourceRootId; - - /// Returns the relative path of a file - fn file_relative_path(&self, file_id: FileId) -> RelativePathBuf; - - /// Contents of the source root - #[salsa::input] - fn source_root(&self, id: SourceRootId) -> Arc; - - /// For a package, returns its hierarchy of modules. - #[salsa::invoke(ModuleTree::module_tree_query)] - fn module_tree(&self, package: PackageId) -> Arc; - - /// Returns the line index of a file - #[salsa::invoke(line_index_query)] - fn line_index(&self, file_id: FileId) -> Arc; - - /// Returns the set of packages - #[salsa::input] - fn packages(&self) -> Arc; -} - /// The `AstDatabase` provides queries that transform text from the /// `SourceDatabase` into an Abstract Syntax Tree (AST). #[salsa::query_group(AstDatabaseStorage)] @@ -167,20 +126,9 @@ fn parse_query(db: &dyn AstDatabase, file_id: FileId) -> Parse { SourceFile::parse(&text) } -fn line_index_query(db: &dyn SourceDatabase, file_id: FileId) -> Arc { - let text = db.file_text(file_id); - Arc::new(LineIndex::new(text.as_ref())) -} - fn target_data_layout(db: &dyn HirDatabase) -> Arc { let target = db.target(); let data_layout = abi::TargetDataLayout::parse(&target) .expect("unable to create TargetDataLayout from target"); Arc::new(data_layout) } - -fn file_relative_path(db: &dyn SourceDatabase, file_id: FileId) -> RelativePathBuf { - let source_root_id = db.file_source_root(file_id); - let source_root = db.source_root(source_root_id); - source_root.relative_path(file_id).to_relative_path_buf() -} diff --git a/crates/mun_hir/src/diagnostics.rs b/crates/mun_hir/src/diagnostics.rs index d241a092..2de9fc79 100644 --- a/crates/mun_hir/src/diagnostics.rs +++ b/crates/mun_hir/src/diagnostics.rs @@ -1,8 +1,9 @@ use std::{any::Any, fmt}; +use mun_hir_input::FileId; use mun_syntax::{ast, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, TextRange}; -use crate::{code_model::StructKind, in_file::InFile, FileId, HirDatabase, IntTy, Name, Ty}; +use crate::{code_model::StructKind, in_file::InFile, HirDatabase, IntTy, Name, Ty}; /// Diagnostic defines `mun_hir` API for errors and warnings. /// diff --git a/crates/mun_hir/src/display.rs b/crates/mun_hir/src/display.rs index 3323410e..15472b94 100644 --- a/crates/mun_hir/src/display.rs +++ b/crates/mun_hir/src/display.rs @@ -1,10 +1,12 @@ use std::fmt; +use mun_hir_input::ModuleId; + use crate::{ code_model::AssocItem, db::HirDatabase, type_ref::{LocalTypeRefId, TypeRef, TypeRefMap}, - Function, HasVisibility, ModuleId, Visibility, + Function, HasVisibility, Visibility, }; pub struct HirFormatter<'a, 'b> { diff --git a/crates/mun_hir/src/expr.rs b/crates/mun_hir/src/expr.rs index 3304cbbd..bf2ae654 100644 --- a/crates/mun_hir/src/expr.rs +++ b/crates/mun_hir/src/expr.rs @@ -2,6 +2,7 @@ use std::{borrow::Cow, ops::Index, str::FromStr, sync::Arc}; use either::Either; use la_arena::{Arena, ArenaMap, Idx}; +use mun_hir_input::FileId; pub use mun_syntax::ast::PrefixOp as UnaryOp; use mun_syntax::{ ast, @@ -19,7 +20,7 @@ use crate::{ name::{name, AsName}, primitive_type::{PrimitiveFloat, PrimitiveInt}, type_ref::{LocalTypeRefId, TypeRef, TypeRefMap, TypeRefMapBuilder, TypeRefSourceMap}, - DefDatabase, FileId, HirDatabase, Name, Path, + DefDatabase, HirDatabase, Name, Path, }; pub(crate) mod scope; diff --git a/crates/mun_hir/src/has_module.rs b/crates/mun_hir/src/has_module.rs index ba4e50c5..a27042d4 100644 --- a/crates/mun_hir/src/has_module.rs +++ b/crates/mun_hir/src/has_module.rs @@ -1,10 +1,12 @@ +use mun_hir_input::ModuleId; + use crate::{ ids::{ AssocItemId, AssocItemLoc, FunctionId, ImplId, ItemContainerId, Lookup, StructId, TypeAliasId, }, item_tree::ItemTreeNode, - DefDatabase, ModuleId, + DefDatabase, }; /// A trait to lookup the module associated with an item. diff --git a/crates/mun_hir/src/ids.rs b/crates/mun_hir/src/ids.rs index 242efb38..d5863368 100644 --- a/crates/mun_hir/src/ids.rs +++ b/crates/mun_hir/src/ids.rs @@ -1,10 +1,11 @@ use std::hash::{Hash, Hasher}; +use mun_hir_input::ModuleId; + use crate::{ item_tree::{Function, Impl, ItemTreeId, ItemTreeNode, Struct, TypeAlias}, - module_tree::LocalModuleId, primitive_type::PrimitiveType, - DefDatabase, PackageId, + DefDatabase, }; #[derive(Clone, Debug)] @@ -86,13 +87,6 @@ macro_rules! impl_intern { }; } -/// Represents an id of a module inside a package. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] -pub struct ModuleId { - pub package: PackageId, - pub local_id: LocalModuleId, -} - /// Represents an id of an item inside a item container such as a module or a /// `impl` block. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] diff --git a/crates/mun_hir/src/in_file.rs b/crates/mun_hir/src/in_file.rs index 3ab1e3c1..4a196e0e 100644 --- a/crates/mun_hir/src/in_file.rs +++ b/crates/mun_hir/src/in_file.rs @@ -1,6 +1,7 @@ +use mun_hir_input::FileId; use mun_syntax::SyntaxNode; -use crate::{AstDatabase, FileId}; +use crate::AstDatabase; /// `InFile` stores a value of `T` inside a particular file/syntax tree. /// diff --git a/crates/mun_hir/src/item_scope.rs b/crates/mun_hir/src/item_scope.rs index 731d31e6..58613786 100644 --- a/crates/mun_hir/src/item_scope.rs +++ b/crates/mun_hir/src/item_scope.rs @@ -1,11 +1,11 @@ use std::collections::hash_map::Entry; +use mun_hir_input::PackageModuleId; use once_cell::sync::Lazy; use rustc_hash::{FxHashMap, FxHashSet}; use crate::{ ids::{ImplId, ItemDefinitionId}, - module_tree::LocalModuleId, primitive_type::PrimitiveType, visibility::Visibility, Name, PerNs, @@ -30,8 +30,8 @@ pub(crate) enum ImportType { /// ``` #[derive(Debug, Default)] pub struct PerNsGlobImports { - types: FxHashSet<(LocalModuleId, Name)>, - values: FxHashSet<(LocalModuleId, Name)>, + types: FxHashSet<(PackageModuleId, Name)>, + values: FxHashSet<(PackageModuleId, Name)>, } /// Holds all items that are visible from an item as well as by which name and @@ -133,7 +133,7 @@ impl ItemScope { pub(crate) fn add_resolution_from_import( &mut self, glob_imports: &mut PerNsGlobImports, - lookup: (LocalModuleId, Name), + lookup: (PackageModuleId, Name), def: PerNs<(ItemDefinitionId, Visibility)>, def_import_type: ImportType, ) -> AddResolutionFromImportResult { diff --git a/crates/mun_hir/src/item_tree.rs b/crates/mun_hir/src/item_tree.rs index 072882f6..b29e8e36 100644 --- a/crates/mun_hir/src/item_tree.rs +++ b/crates/mun_hir/src/item_tree.rs @@ -14,6 +14,7 @@ use std::{ }; use la_arena::{Arena, Idx}; +use mun_hir_input::FileId; use mun_syntax::ast; use crate::{ @@ -21,7 +22,7 @@ use crate::{ source_id::{AstIdNode, FileAstId}, type_ref::{LocalTypeRefId, TypeRefMap}, visibility::RawVisibility, - DefDatabase, FileId, InFile, Name, Path, + DefDatabase, InFile, Name, Path, }; #[derive(Copy, Clone, Eq, PartialEq)] diff --git a/crates/mun_hir/src/item_tree/lower.rs b/crates/mun_hir/src/item_tree/lower.rs index 7f88008b..8a165dd0 100644 --- a/crates/mun_hir/src/item_tree/lower.rs +++ b/crates/mun_hir/src/item_tree/lower.rs @@ -3,6 +3,7 @@ use std::{collections::HashMap, convert::TryInto, marker::PhantomData, sync::Arc}; use la_arena::{Idx, RawIdx}; +use mun_hir_input::FileId; use mun_syntax::ast::{ self, ExternOwner, ModuleItemOwner, NameOwner, StructKind, TypeAscriptionOwner, }; @@ -19,7 +20,7 @@ use crate::{ source_id::AstIdMap, type_ref::{TypeRefMap, TypeRefMapBuilder}, visibility::RawVisibility, - DefDatabase, FileId, Name, Path, + DefDatabase, Name, Path, }; struct ModItems(SmallVec<[ModItem; 1]>); diff --git a/crates/mun_hir/src/item_tree/tests.rs b/crates/mun_hir/src/item_tree/tests.rs index 467709ed..7f0357cf 100644 --- a/crates/mun_hir/src/item_tree/tests.rs +++ b/crates/mun_hir/src/item_tree/tests.rs @@ -1,6 +1,9 @@ use std::fmt; -use crate::{mock::MockDatabase, with_fixture::WithFixture, DefDatabase, DiagnosticSink, Upcast}; +use mun_db::Upcast; +use mun_hir_input::WithFixture; + +use crate::{mock::MockDatabase, DefDatabase, DiagnosticSink}; fn print_item_tree(text: &str) -> Result { let (db, file_id) = MockDatabase::with_single_file(text); diff --git a/crates/mun_hir/src/lib.rs b/crates/mun_hir/src/lib.rs index 1f161573..9ef0cc6e 100644 --- a/crates/mun_hir/src/lib.rs +++ b/crates/mun_hir/src/lib.rs @@ -6,6 +6,8 @@ #![allow(dead_code)] +pub use mun_db::Upcast; +pub use mun_hir_input::ModuleId; pub use salsa; pub use self::code_model::{ @@ -15,8 +17,7 @@ pub use self::code_model::{ pub use crate::{ db::{ AstDatabase, AstDatabaseStorage, DefDatabase, DefDatabaseStorage, HirDatabase, - HirDatabaseStorage, InternDatabase, InternDatabaseStorage, SourceDatabase, - SourceDatabaseStorage, Upcast, + HirDatabaseStorage, InternDatabase, InternDatabaseStorage, }, diagnostics::{Diagnostic, DiagnosticSink}, display::HirDisplay, @@ -24,12 +25,10 @@ pub use crate::{ ArithOp, BinaryOp, Body, CmpOp, Expr, ExprId, ExprScopes, Literal, LogicOp, Ordering, Pat, PatId, RecordLitField, Statement, UnaryOp, }, - ids::{ItemLoc, ModuleId}, + ids::ItemLoc, in_file::InFile, - input::{FileId, SourceRoot, SourceRootId}, name::Name, name_resolution::PerNs, - package_set::{PackageId, PackageSet}, path::{Path, PathKind}, primitive_type::{FloatBitness, IntBitness, Signedness}, resolve::{resolver_for_expr, resolver_for_scope, Resolver, TypeNs, ValueNs}, @@ -50,10 +49,7 @@ mod display; mod expr; mod ids; mod in_file; -mod input; mod item_tree; -pub mod line_index; -mod module_tree; mod name; mod name_resolution; mod path; @@ -64,18 +60,15 @@ mod ty; mod type_ref; mod utils; -pub mod fixture; mod has_module; mod item_scope; mod method_resolution; #[cfg(test)] mod mock; mod package_defs; -mod package_set; mod pretty; pub mod semantics; mod source_analyzer; #[cfg(test)] mod tests; mod visibility; -pub mod with_fixture; diff --git a/crates/mun_hir/src/method_resolution.rs b/crates/mun_hir/src/method_resolution.rs index 39b6e05a..7a293d28 100644 --- a/crates/mun_hir/src/method_resolution.rs +++ b/crates/mun_hir/src/method_resolution.rs @@ -4,6 +4,7 @@ use std::{ sync::Arc, }; +use mun_hir_input::{ModuleId, PackageId, PackageModuleId}; use mun_syntax::{AstNode, AstPtr, SyntaxNodePtr}; use rustc_hash::FxHashMap; @@ -12,10 +13,9 @@ use crate::{ diagnostics::{DuplicateDefinition, ImplForForeignType, InvalidSelfTyImpl}, has_module::HasModule, ids::{AssocItemId, FunctionId, ImplId, Lookup, StructId}, - module_tree::LocalModuleId, package_defs::PackageDefs, ty::lower::LowerDiagnostic, - DefDatabase, DiagnosticSink, HasSource, InFile, ModuleId, Name, PackageId, Ty, TyKind, + DefDatabase, DiagnosticSink, HasSource, InFile, Name, Ty, TyKind, }; #[derive(Clone, Debug, PartialEq, Eq)] @@ -141,7 +141,7 @@ impl InherentImpls { pub(crate) fn add_module_diagnostics( &self, db: &dyn HirDatabase, - module_id: LocalModuleId, + module_id: PackageModuleId, sink: &mut DiagnosticSink<'_>, ) { self.diagnostics @@ -393,13 +393,14 @@ pub(crate) fn lookup_method( #[cfg(test)] mod tests { + use mun_hir_input::{SourceDatabase, WithFixture}; + use crate::{ code_model::AssocItem, display::HirDisplay, method_resolution::{lookup_method, MethodResolutionCtx}, mock::MockDatabase, - with_fixture::WithFixture, - DiagnosticSink, HirDatabase, Module, ModuleDef, Name, Package, SourceDatabase, Ty, + DiagnosticSink, HirDatabase, Module, ModuleDef, Name, Package, Ty, }; #[test] diff --git a/crates/mun_hir/src/mock.rs b/crates/mun_hir/src/mock.rs index 7939bb6d..dc0417af 100644 --- a/crates/mun_hir/src/mock.rs +++ b/crates/mun_hir/src/mock.rs @@ -1,17 +1,19 @@ #![cfg(test)] +use mun_db::Upcast; +use mun_hir_input::SourceDatabase; use mun_target::spec::Target; use parking_lot::Mutex; use crate::{ - db::{AstDatabase, HirDatabase, SourceDatabase, Upcast}, + db::{AstDatabase, HirDatabase}, DefDatabase, }; /// A mock implementation of the IR database. It can be used to set up a simple /// test case. #[salsa::database( - crate::SourceDatabaseStorage, + mun_hir_input::SourceDatabaseStorage, crate::AstDatabaseStorage, crate::InternDatabaseStorage, crate::DefDatabaseStorage, diff --git a/crates/mun_hir/src/name_resolution/path_resolution.rs b/crates/mun_hir/src/name_resolution/path_resolution.rs index a532ede7..e24f7874 100644 --- a/crates/mun_hir/src/name_resolution/path_resolution.rs +++ b/crates/mun_hir/src/name_resolution/path_resolution.rs @@ -1,11 +1,10 @@ use std::iter::successors; +use mun_hir_input::{ModuleId, PackageId, PackageModuleId}; + use crate::{ - ids::{ItemDefinitionId, ModuleId}, - item_scope::BUILTIN_SCOPE, - module_tree::LocalModuleId, - package_defs::PackageDefs, - DefDatabase, Name, PackageId, Path, PathKind, PerNs, Visibility, + ids::ItemDefinitionId, item_scope::BUILTIN_SCOPE, package_defs::PackageDefs, DefDatabase, Name, + Path, PathKind, PerNs, Visibility, }; /// Indicates whether or not any newly resolved import statements will actually @@ -56,7 +55,7 @@ impl PackageDefs { pub(crate) fn resolve_path_in_module( &self, db: &dyn DefDatabase, - module: LocalModuleId, + module: PackageModuleId, path: &Path, ) -> (PerNs<(ItemDefinitionId, Visibility)>, Option) { let res = self.resolve_path_with_fixedpoint(db, module, path); @@ -67,7 +66,7 @@ impl PackageDefs { fn resolve_name_in_module( &self, _db: &dyn DefDatabase, - module: LocalModuleId, + module: PackageModuleId, name: &Name, ) -> PerNs<(ItemDefinitionId, Visibility)> { self[module] @@ -82,7 +81,7 @@ impl PackageDefs { pub(crate) fn resolve_path_with_fixedpoint( &self, db: &dyn DefDatabase, - original_module: LocalModuleId, + original_module: PackageModuleId, path: &Path, ) -> ResolvePathResult { let mut segments = path.segments.iter().enumerate(); diff --git a/crates/mun_hir/src/package_defs.rs b/crates/mun_hir/src/package_defs.rs index eebab12d..5b4ab7f2 100644 --- a/crates/mun_hir/src/package_defs.rs +++ b/crates/mun_hir/src/package_defs.rs @@ -5,18 +5,15 @@ mod tests; use std::{ops::Index, sync::Arc}; use la_arena::ArenaMap; +use mun_hir_input::{ModuleTree, PackageId, PackageModuleId}; -use crate::{ - item_scope::ItemScope, - module_tree::{LocalModuleId, ModuleTree}, - DefDatabase, DiagnosticSink, PackageId, -}; +use crate::{item_scope::ItemScope, DefDatabase, DiagnosticSink}; /// Contains all top-level definitions for a package. #[derive(Debug, PartialEq, Eq)] pub struct PackageDefs { pub id: PackageId, - pub modules: ArenaMap, + pub modules: ArenaMap, pub module_tree: Arc, diagnostics: Vec, } @@ -35,7 +32,7 @@ impl PackageDefs { pub fn add_diagnostics( &self, db: &dyn DefDatabase, - module: LocalModuleId, + module: PackageModuleId, sink: &mut DiagnosticSink<'_>, ) { for diagnostic in self.diagnostics.iter() { @@ -44,20 +41,20 @@ impl PackageDefs { } } -impl Index for PackageDefs { +impl Index for PackageDefs { type Output = ItemScope; - fn index(&self, index: LocalModuleId) -> &Self::Output { + fn index(&self, index: PackageModuleId) -> &Self::Output { &self.modules[index] } } mod diagnostics { + use mun_hir_input::PackageModuleId; use mun_syntax::{ast, ast::Use, AstPtr}; use crate::{ diagnostics::{ImportDuplicateDefinition, UnresolvedImport}, - module_tree::LocalModuleId, source_id::AstId, AstDatabase, DefDatabase, DiagnosticSink, InFile, Path, }; @@ -75,7 +72,7 @@ mod diagnostics { #[derive(Debug, PartialEq, Eq)] pub(super) struct DefDiagnostic { /// The module that contains the diagnostic - in_module: LocalModuleId, + in_module: PackageModuleId, /// The type of diagnostic kind: DiagnosticKind, @@ -85,7 +82,7 @@ mod diagnostics { /// Constructs a new `DefDiagnostic` which indicates that an import /// could not be resolved. pub(super) fn unresolved_import( - container: LocalModuleId, + container: PackageModuleId, ast: AstId, index: usize, ) -> Self { @@ -98,7 +95,7 @@ mod diagnostics { /// Constructs a new `DefDiagnostic` which indicates that an import /// names a duplication. pub(super) fn duplicate_import( - container: LocalModuleId, + container: PackageModuleId, ast: AstId, index: usize, ) -> Self { @@ -111,7 +108,7 @@ mod diagnostics { pub(super) fn add_to( &self, db: &dyn DefDatabase, - target_module: LocalModuleId, + target_module: PackageModuleId, sink: &mut DiagnosticSink<'_>, ) { fn use_tree_ptr_from_ast( diff --git a/crates/mun_hir/src/package_defs/collector.rs b/crates/mun_hir/src/package_defs/collector.rs index a72ffe34..aa09efaa 100644 --- a/crates/mun_hir/src/package_defs/collector.rs +++ b/crates/mun_hir/src/package_defs/collector.rs @@ -1,4 +1,5 @@ use la_arena::ArenaMap; +use mun_hir_input::{FileId, ModuleId, PackageId, PackageModuleId}; use rustc_hash::FxHashMap; use super::PackageDefs; @@ -11,12 +12,11 @@ use crate::{ self, Fields, Function, Impl, ItemTree, ItemTreeId, LocalItemTreeId, ModItem, Struct, TypeAlias, }, - module_tree::LocalModuleId, name_resolution::ReachedFixedPoint, package_defs::diagnostics::DefDiagnostic, path::ImportAlias, visibility::RawVisibility, - DefDatabase, FileId, InFile, ModuleId, Name, PackageId, Path, PerNs, Visibility, + DefDatabase, InFile, Name, Path, PerNs, Visibility, }; /// Result of resolving an import statement @@ -90,7 +90,7 @@ impl Import { #[derive(Clone, Debug, Eq, PartialEq)] struct ImportDirective { /// The module that defines the import statement - module_id: LocalModuleId, + module_id: PackageModuleId, /// Information about the import statement. import: Import, @@ -127,8 +127,10 @@ struct DefCollector<'db> { resolved_imports: Vec, /// A mapping from local module to wildcard imports of other modules - glob_imports: - FxHashMap)>>, + glob_imports: FxHashMap< + PackageModuleId, + Vec<(PackageModuleId, Visibility, ItemTreeId)>, + >, /// A list of all items that have been imported via a wildcard from_glob_import: PerNsGlobImports, @@ -142,8 +144,8 @@ impl<'db> DefCollector<'db> { /// `ItemScope`. fn collect_modules_recursive( collector: &mut DefCollector<'_>, - module_id: LocalModuleId, - parent: Option<(Name, LocalModuleId)>, + module_id: PackageModuleId, + parent: Option<(String, PackageModuleId)>, ) { // Insert an empty item scope for this module, this will be filled in. collector @@ -169,7 +171,7 @@ impl<'db> DefCollector<'db> { // Insert this module into the scope of the parent if let Some((name, parent)) = parent { collector.package_defs.modules[parent].add_resolution( - name, + Name::new(name), PerNs::from_definition( ModuleId { package: collector.package_id, @@ -247,7 +249,11 @@ impl<'db> DefCollector<'db> { } /// Given an import, try to resolve it. - fn resolve_import(&self, module_id: LocalModuleId, import: &Import) -> PartiallyResolvedImport { + fn resolve_import( + &self, + module_id: PackageModuleId, + import: &Import, + ) -> PartiallyResolvedImport { let res = self .package_defs .resolve_path_with_fixedpoint(self.db, module_id, &import.path); @@ -280,8 +286,9 @@ impl<'db> DefCollector<'db> { let resolution = directive.status.namespaces(); // Get the visibility of the import statement - let import_visibility = self.package_defs.module_tree.resolve_visibility( + let import_visibility = Visibility::resolve( self.db, + &self.package_defs.module_tree, import_module_id, &directive.import.visibility, ); @@ -360,7 +367,7 @@ impl<'db> DefCollector<'db> { /// Updates the current state with the resolutions of an import statement. fn update( &mut self, - import_module_id: LocalModuleId, + import_module_id: PackageModuleId, import_visibility: Visibility, import_type: ImportType, import_source: ItemTreeId, @@ -380,7 +387,7 @@ impl<'db> DefCollector<'db> { /// Also recursively updates any wildcard imports. fn update_recursive( &mut self, - import_module_id: LocalModuleId, + import_module_id: PackageModuleId, import_visibility: Visibility, import_type: ImportType, import_source: ItemTreeId, @@ -496,7 +503,7 @@ impl<'db> DefCollector<'db> { /// Collects all items from a module struct ModCollectorContext<'a, 'db> { def_collector: &'a mut DefCollector<'db>, - module_id: LocalModuleId, + module_id: PackageModuleId, file_id: FileId, item_tree: &'a ItemTree, } @@ -524,11 +531,12 @@ impl<'a> ModCollectorContext<'a, '_> { }; self.def_collector.package_defs.modules[self.module_id].add_definition(id); - let visibility = self - .def_collector - .package_defs - .module_tree - .resolve_visibility(self.def_collector.db, self.module_id, visibility); + let visibility = Visibility::resolve( + self.def_collector.db, + &self.def_collector.package_defs.module_tree, + self.module_id, + visibility, + ); self.def_collector.package_defs.modules[self.module_id].add_resolution( name.clone(), PerNs::from_definition(id, visibility, has_constructor), diff --git a/crates/mun_hir/src/package_defs/tests.rs b/crates/mun_hir/src/package_defs/tests.rs index 82540d7f..540bba30 100644 --- a/crates/mun_hir/src/package_defs/tests.rs +++ b/crates/mun_hir/src/package_defs/tests.rs @@ -1,9 +1,9 @@ +use mun_hir_input::WithFixture; use rustc_hash::FxHashSet; use crate::{ db::DefDatabase, ids::ItemDefinitionId, mock::MockDatabase, package_defs::PackageDefs, - with_fixture::WithFixture, DiagnosticSink, Function, HirDatabase, Module, Package, Struct, - TypeAlias, + DiagnosticSink, Function, HirDatabase, Module, Package, Struct, TypeAlias, }; #[test] diff --git a/crates/mun_hir/src/resolve.rs b/crates/mun_hir/src/resolve.rs index 29b6d19c..d8e22128 100644 --- a/crates/mun_hir/src/resolve.rs +++ b/crates/mun_hir/src/resolve.rs @@ -1,14 +1,15 @@ use std::sync::Arc; +use mun_hir_input::{ModuleId, PackageModuleId}; + use crate::{ expr::{scope::LocalScopeId, PatId}, has_module::HasModule, ids::{ - DefWithBodyId, FunctionId, ImplId, ItemContainerId, ItemDefinitionId, Lookup, ModuleId, - StructId, TypeAliasId, + DefWithBodyId, FunctionId, ImplId, ItemContainerId, ItemDefinitionId, Lookup, StructId, + TypeAliasId, }, item_scope::BUILTIN_SCOPE, - module_tree::LocalModuleId, name, package_defs::PackageDefs, primitive_type::PrimitiveType, @@ -34,7 +35,7 @@ pub(crate) enum Scope { #[derive(Debug, Clone)] pub(crate) struct ModuleItemMap { package_defs: Arc, - module_id: LocalModuleId, + module_id: PackageModuleId, } #[derive(Debug, Clone)] @@ -90,7 +91,7 @@ impl Resolver { pub(crate) fn push_module_scope( self, package_defs: Arc, - module_id: LocalModuleId, + module_id: PackageModuleId, ) -> Resolver { self.push_scope(Scope::Module(ModuleItemMap { package_defs, @@ -138,7 +139,7 @@ impl Resolver { // } /// Returns the `Module` scope of the resolver - fn module_scope(&self) -> Option<(&PackageDefs, LocalModuleId)> { + fn module_scope(&self) -> Option<(&PackageDefs, PackageModuleId)> { self.scopes.iter().rev().find_map(|scope| { if let Scope::Module(m) = scope { Some((&*m.package_defs, m.module_id)) @@ -155,9 +156,7 @@ impl Resolver { visibility: &RawVisibility, ) -> Option { self.module_scope().map(|(package_defs, module)| { - package_defs - .module_tree - .resolve_visibility(db, module, visibility) + Visibility::resolve(db, &package_defs.module_tree, module, visibility) }) } diff --git a/crates/mun_hir/src/semantics.rs b/crates/mun_hir/src/semantics.rs index b253f30d..d3e26b36 100644 --- a/crates/mun_hir/src/semantics.rs +++ b/crates/mun_hir/src/semantics.rs @@ -14,6 +14,7 @@ mod source_to_def; use std::cell::RefCell; +use mun_hir_input::FileId; use mun_syntax::{ast, AstNode, SyntaxNode, TextSize}; use rustc_hash::FxHashMap; use smallvec::SmallVec; @@ -23,7 +24,7 @@ use crate::{ resolve::{self, HasResolver}, semantics::source_to_def::{SourceToDefCache, SourceToDefContainer, SourceToDefContext}, source_analyzer::SourceAnalyzer, - FileId, HirDatabase, InFile, ModuleDef, Name, PatId, PerNs, Resolver, Ty, Visibility, + HirDatabase, InFile, ModuleDef, Name, PatId, PerNs, Resolver, Ty, Visibility, }; /// The primary API to get semantic information, like types, from syntax trees. diff --git a/crates/mun_hir/src/semantics/source_to_def.rs b/crates/mun_hir/src/semantics/source_to_def.rs index 9fc61a0f..407e67f6 100644 --- a/crates/mun_hir/src/semantics/source_to_def.rs +++ b/crates/mun_hir/src/semantics/source_to_def.rs @@ -1,3 +1,4 @@ +use mun_hir_input::{FileId, ModuleId}; use mun_syntax::{ast, match_ast, AstNode, SyntaxNode}; use rustc_hash::FxHashMap; @@ -5,7 +6,7 @@ use crate::{ code_model::src::HasSource, ids::{DefWithBodyId, FunctionId, ItemDefinitionId, Lookup, StructId, TypeAliasId}, item_scope::ItemScope, - DefDatabase, FileId, HirDatabase, InFile, ModuleId, + DefDatabase, HirDatabase, InFile, }; pub(super) type SourceToDefCache = FxHashMap; diff --git a/crates/mun_hir/src/source_analyzer.rs b/crates/mun_hir/src/source_analyzer.rs index a223ab80..571abd76 100644 --- a/crates/mun_hir/src/source_analyzer.rs +++ b/crates/mun_hir/src/source_analyzer.rs @@ -1,12 +1,13 @@ use std::sync::Arc; +use mun_hir_input::FileId; use mun_syntax::{ast, AstNode, SyntaxNode, TextRange, TextSize}; use crate::{ expr::{scope::LocalScopeId, BodySourceMap}, ids::DefWithBodyId, - resolver_for_scope, Body, ExprId, ExprScopes, FileId, HirDatabase, InFile, InferenceResult, - Resolver, Ty, + resolver_for_scope, Body, ExprId, ExprScopes, HirDatabase, InFile, InferenceResult, Resolver, + Ty, }; /// A `SourceAnalyzer` is a wrapper which exposes the HIR API in terms of the diff --git a/crates/mun_hir/src/source_id.rs b/crates/mun_hir/src/source_id.rs index 0ddbb2bf..917d9614 100644 --- a/crates/mun_hir/src/source_id.rs +++ b/crates/mun_hir/src/source_id.rs @@ -5,9 +5,10 @@ use std::{ }; use la_arena::{Arena, Idx}; +use mun_hir_input::FileId; use mun_syntax::{ast, AstNode, AstPtr, SyntaxNode, SyntaxNodePtr, WalkEvent}; -use crate::{db::AstDatabase, in_file::InFile, FileId}; +use crate::{db::AstDatabase, in_file::InFile}; type ErasedFileAstId = Idx; diff --git a/crates/mun_hir/src/tests.rs b/crates/mun_hir/src/tests.rs index 53cb327e..8375456c 100644 --- a/crates/mun_hir/src/tests.rs +++ b/crates/mun_hir/src/tests.rs @@ -1,11 +1,8 @@ use std::sync::Arc; -use crate::{ - db::{DefDatabase, SourceDatabase}, - mock::MockDatabase, - with_fixture::WithFixture, - PackageId, -}; +use mun_hir_input::{PackageId, SourceDatabase, WithFixture}; + +use crate::{db::DefDatabase, mock::MockDatabase}; /// This function tests that the `ModuleData` of a module does not change if the /// contents of a function is changed. diff --git a/crates/mun_hir/src/ty/lower.rs b/crates/mun_hir/src/ty/lower.rs index 89f6d3d4..9f19f236 100644 --- a/crates/mun_hir/src/ty/lower.rs +++ b/crates/mun_hir/src/ty/lower.rs @@ -3,6 +3,7 @@ use std::{ops::Index, sync::Arc}; use la_arena::ArenaMap; +use mun_hir_input::FileId; pub(crate) use self::diagnostics::LowerDiagnostic; use crate::{ @@ -14,7 +15,7 @@ use crate::{ resolve::{HasResolver, Resolver, TypeNs}, ty::{FnSig, Substitution, Ty, TyKind}, type_ref::{LocalTypeRefId, TypeRef, TypeRefMap, TypeRefSourceMap}, - FileId, Function, HasVisibility, HirDatabase, ModuleDef, Path, Struct, TypeAlias, Visibility, + Function, HasVisibility, HirDatabase, ModuleDef, Path, Struct, TypeAlias, Visibility, }; /// A struct which holds resolved type references to `Ty`s. @@ -330,10 +331,12 @@ pub(crate) fn lower_impl_query(db: &dyn HirDatabase, impl_id: ImplId) -> Arc(a: &mut Arc<[T]>) -> &mut [T] { #[cfg(test)] pub mod tests { - use crate::{ - diagnostics::DiagnosticSink, mock::MockDatabase, with_fixture::WithFixture, AstDatabase, - Package, - }; + use mun_hir_input::WithFixture; + + use crate::{diagnostics::DiagnosticSink, mock::MockDatabase, AstDatabase, Package}; pub fn diagnostics(content: &str) -> String { let (db, _file_id) = MockDatabase::with_single_file(content); diff --git a/crates/mun_hir/src/visibility.rs b/crates/mun_hir/src/visibility.rs index 79a1a7fa..b19fbfd4 100644 --- a/crates/mun_hir/src/visibility.rs +++ b/crates/mun_hir/src/visibility.rs @@ -1,13 +1,9 @@ use std::iter::successors; +use mun_hir_input::{ModuleId, ModuleTree, PackageModuleId}; use mun_syntax::ast; -use crate::{ - ids::{FunctionId, ModuleId}, - module_tree::{LocalModuleId, ModuleTree}, - resolve::HasResolver, - DefDatabase, HirDatabase, Module, Resolver, -}; +use crate::{ids::FunctionId, resolve::HasResolver, DefDatabase, HirDatabase, Module, Resolver}; /// Visibility of an item, not yet resolved to an actual module. #[derive(Debug, Clone, PartialEq, Eq)] @@ -70,7 +66,7 @@ impl Visibility { pub(crate) fn is_visible_from_module_tree( self, module_tree: &ModuleTree, - from_module: LocalModuleId, + from_module: PackageModuleId, ) -> bool { let to_module = match self { Visibility::Module(m) => m, @@ -103,6 +99,37 @@ impl Visibility { Visibility::Public => true, } } + + /// Converts a `RawVisibility` which describes the visibility of an item + /// relative to a module into a `Visibility` which describes the + /// absolute visibility within the module tree. + pub(crate) fn resolve( + _db: &dyn DefDatabase, + module_tree: &ModuleTree, + original_module: PackageModuleId, + visibility: &RawVisibility, + ) -> Visibility { + match visibility { + RawVisibility::This => Visibility::Module(ModuleId { + package: module_tree.package, + local_id: original_module, + }), + RawVisibility::Super => { + let parent_module_id = module_tree[original_module] + .parent + .unwrap_or(original_module); + Visibility::Module(ModuleId { + package: module_tree.package, + local_id: parent_module_id, + }) + } + RawVisibility::Package => Visibility::Module(ModuleId { + package: module_tree.package, + local_id: module_tree.root, + }), + RawVisibility::Public => Visibility::Public, + } + } } pub trait HasVisibility { diff --git a/crates/mun_hir_input/Cargo.toml b/crates/mun_hir_input/Cargo.toml new file mode 100644 index 00000000..a4042e9e --- /dev/null +++ b/crates/mun_hir_input/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "mun_hir_input" +description = "Database implementation for everything mun source related." +version.workspace = true +authors.workspace = true +edition.workspace = true +documentation.workspace = true +readme.workspace = true +homepage.workspace = true +repository.workspace = true +license.workspace = true +categories.workspace = true + +[dependencies] +itertools = { workspace = true } +mun_paths = { version = "0.6.0-dev", path = "../mun_paths" } +mun_syntax = { version = "0.6.0-dev", path = "../mun_syntax" } +rustc-hash = { workspace = true } +la-arena = { workspace = true } +salsa = { workspace = true } + +[dev-dependencies] +insta = { workspace = true } diff --git a/crates/mun_hir_input/src/db.rs b/crates/mun_hir_input/src/db.rs new file mode 100644 index 00000000..7585e465 --- /dev/null +++ b/crates/mun_hir_input/src/db.rs @@ -0,0 +1,50 @@ +use std::sync::Arc; + +use mun_paths::RelativePathBuf; + +use crate::{FileId, LineIndex, ModuleTree, PackageId, PackageSet, SourceRoot, SourceRootId}; + +/// Database which stores all significant input facts: source code and project +/// model. +#[salsa::query_group(SourceDatabaseStorage)] +#[allow(clippy::trait_duplication_in_bounds)] +pub trait SourceDatabase: salsa::Database { + /// Text of the file. + #[salsa::input] + fn file_text(&self, file_id: FileId) -> Arc; + + /// Source root of a file + #[salsa::input] + fn file_source_root(&self, file_id: FileId) -> SourceRootId; + + /// Returns the set of packages + #[salsa::input] + fn packages(&self) -> Arc; + + /// Contents of the source root + #[salsa::input] + fn source_root(&self, id: SourceRootId) -> Arc; + + /// Returns the relative path of a file + fn file_relative_path(&self, file_id: FileId) -> RelativePathBuf; + + /// For a package, returns its hierarchy of modules. + #[salsa::invoke(ModuleTree::module_tree_query)] + fn module_tree(&self, package: PackageId) -> Arc; + + /// Returns the line index of a file + #[salsa::invoke(line_index_query)] + fn line_index(&self, file_id: FileId) -> Arc; +} + +/// Computes the relative path of a specific [`FileId`] within a [`SourceRoot`]. +fn file_relative_path(db: &dyn SourceDatabase, file_id: FileId) -> RelativePathBuf { + let source_root_id = db.file_source_root(file_id); + let source_root = db.source_root(source_root_id); + source_root.relative_path(file_id).to_relative_path_buf() +} +/// Computes a new `LineIndex` for the specified [`FileId`]. +fn line_index_query(db: &dyn SourceDatabase, file_id: FileId) -> Arc { + let text = db.file_text(file_id); + Arc::new(LineIndex::new(text.as_ref())) +} diff --git a/crates/mun_hir/src/fixture.rs b/crates/mun_hir_input/src/fixture/mod.rs similarity index 97% rename from crates/mun_hir/src/fixture.rs rename to crates/mun_hir_input/src/fixture/mod.rs index 7dfff5c1..32ceb1b6 100644 --- a/crates/mun_hir/src/fixture.rs +++ b/crates/mun_hir_input/src/fixture/mod.rs @@ -1,6 +1,10 @@ use itertools::Itertools; use mun_paths::RelativePathBuf; +mod with_fixture; + +pub use with_fixture::WithFixture; + const DEFAULT_FILE_NAME: &str = "mod.mun"; const META_LINE: &str = "//-"; @@ -116,7 +120,7 @@ impl Fixture { /// // code /// } /// ``` -pub fn trim_raw_string_literal(text: impl AsRef) -> String { +fn trim_raw_string_literal(text: impl AsRef) -> String { let mut text = text.as_ref(); if text.starts_with('\n') { text = &text[1..]; diff --git a/crates/mun_hir/src/with_fixture.rs b/crates/mun_hir_input/src/fixture/with_fixture.rs similarity index 100% rename from crates/mun_hir/src/with_fixture.rs rename to crates/mun_hir_input/src/fixture/with_fixture.rs diff --git a/crates/mun_hir_input/src/lib.rs b/crates/mun_hir_input/src/lib.rs new file mode 100644 index 00000000..79369c55 --- /dev/null +++ b/crates/mun_hir_input/src/lib.rs @@ -0,0 +1,36 @@ +//! This crate represents all the input of a mun project. + +mod db; +mod fixture; +mod line_index; +mod module_tree; +mod package_set; +mod source_root; + +pub use db::{SourceDatabase, SourceDatabaseStorage}; +pub use fixture::{Fixture, WithFixture}; +pub use line_index::{LineCol, LineIndex}; +pub use module_tree::{ModuleData, ModuleTree, PackageModuleId}; +pub use package_set::{PackageData, PackageId, PackageSet}; +pub use source_root::{SourceRoot, SourceRootId}; + +/// [`FileId`] is an integer which uniquely identifies a file. File paths are +/// messy and system-dependent, so most of the code should work directly with +/// [`FileId`], without inspecting the path. +/// +/// [`FileId`]s are logically grouped by a [`SourceRoot`]. +/// +/// The mapping between [`FileId`] and path and [`SourceRoot`] is constant. A +/// file rename is represented as a pair of deletion/creation. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct FileId(pub u32); + +/// A identifier that unique identifies a single module with the project. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] +pub struct ModuleId { + /// The id of the package that contains the module. + pub package: PackageId, + + /// The id of the module inside the package. + pub local_id: PackageModuleId, +} diff --git a/crates/mun_hir/src/line_index.rs b/crates/mun_hir_input/src/line_index.rs similarity index 97% rename from crates/mun_hir/src/line_index.rs rename to crates/mun_hir_input/src/line_index.rs index 621b8b4e..8818d8c8 100644 --- a/crates/mun_hir/src/line_index.rs +++ b/crates/mun_hir_input/src/line_index.rs @@ -1,13 +1,15 @@ use mun_syntax::TextSize; use rustc_hash::FxHashMap; +/// A [`LineIndex`] enables efficient mapping between offsets and line/column +/// positions in a text. #[derive(Clone, Debug, PartialEq, Eq)] pub struct LineIndex { /// Offsets from the beginning of each line newlines: Vec, /// List of non-ASCII characters on each line - pub(crate) utf16_lines: FxHashMap>, + utf16_lines: FxHashMap>, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] @@ -20,7 +22,7 @@ pub struct LineCol { } #[derive(Clone, Debug, Hash, PartialEq, Eq)] -pub(crate) struct Utf16Char { +struct Utf16Char { /// Start offset of a character inside a line, zero-based pub(crate) start: TextSize, @@ -45,6 +47,7 @@ impl Utf16Char { } impl LineIndex { + /// Constructs a new [`LineIndex`] from the given text. pub fn new(text: &str) -> LineIndex { let mut utf16_lines = FxHashMap::default(); let mut utf16_chars = Vec::new(); diff --git a/crates/mun_hir/src/module_tree.rs b/crates/mun_hir_input/src/module_tree.rs similarity index 70% rename from crates/mun_hir/src/module_tree.rs rename to crates/mun_hir_input/src/module_tree.rs index f24bf10d..6aee5af4 100644 --- a/crates/mun_hir/src/module_tree.rs +++ b/crates/mun_hir_input/src/module_tree.rs @@ -5,47 +5,45 @@ use la_arena::{Arena, Idx}; use mun_paths::RelativePath; use rustc_hash::FxHashMap; -use crate::{ - ids::ModuleId, module_tree::diagnostics::ModuleTreeDiagnostic, visibility::RawVisibility, - DefDatabase, FileId, Name, PackageId, SourceDatabase, Visibility, -}; +use self::diagnostics::ModuleTreeDiagnostic; +use crate::{FileId, PackageId, SourceDatabase}; /// Represents the tree of modules of a package. /// -/// The `ModuleTree` is built by looking at all the source files of the source +/// The [`ModuleTree`] is built by looking at all the source files of the source /// root of a package and creating a tree based on their relative paths. See the -/// [`ModuleTree::module_tree_query`] method. When constructing the `ModuleTree` -/// extra empty modules may be added for missing files. For instance for the -/// relative path `foo/bar/baz.mun`, besides the module `foo::bar::baz` the -/// modules `foo`, `foo::bar` get created along the way. +/// [`ModuleTree::module_tree_query`] method. When constructing the +/// [`ModuleTree`] extra empty modules may be added for missing files. For +/// instance for the relative path `foo/bar/baz.mun`, besides the module +/// `foo::bar::baz` the modules `foo`, `foo::bar` get created along the way. /// -/// A `ModuleTree` represent the inner connections between files. It can be used -/// to query the shortest path for use declarations +/// A [`ModuleTree`] represent the inner connections between files. It can be +/// used to query the shortest path for use declarations #[derive(Debug, PartialEq, Eq)] pub struct ModuleTree { - pub root: LocalModuleId, + pub root: PackageModuleId, pub modules: Arena, pub package: PackageId, - pub diagnostics: Vec, + pub diagnostics: Vec, } /// A module in the tree of modules #[derive(Default, Debug, PartialEq, Eq)] pub struct ModuleData { - pub parent: Option, - pub children: FxHashMap, + pub parent: Option, + pub children: FxHashMap, pub file: Option, } /// The ID of a module within a specific package -pub(crate) type LocalModuleId = Idx; +pub type PackageModuleId = Idx; // Using a `LocalModuleId` you can access the `ModuleTree` to get the // `ModuleData` -impl std::ops::Index for ModuleTree { +impl std::ops::Index for ModuleTree { type Output = ModuleData; - fn index(&self, id: LocalModuleId) -> &ModuleData { + fn index(&self, id: PackageModuleId) -> &ModuleData { &self.modules[id] } } @@ -76,10 +74,7 @@ impl ModuleTree { // Iterate over all segments of the relative path and construct modules on the // way let mut module_id = root; - for path_segment in path_to_module_path(relative_path) - .into_iter() - .map(Name::new) - { + for path_segment in path_to_module_path(relative_path) { module_id = if let Some(id) = modules[module_id].children.get(&path_segment) { *id } else { @@ -89,7 +84,7 @@ impl ModuleTree { file: None, }); - if !is_valid_module_name(path_segment.to_string()) { + if !is_valid_module_name(&path_segment) { diagnostics.push(ModuleTreeDiagnostic::InvalidModuleName(child_module_id)); } @@ -118,37 +113,8 @@ impl ModuleTree { }) } - /// Converts a `RawVisibility` which describes the visibility of an item - /// relative to a module into a `Visibility` which describes the - /// absolute visibility within the module tree. - pub(crate) fn resolve_visibility( - &self, - _db: &dyn DefDatabase, - original_module: LocalModuleId, - visibility: &RawVisibility, - ) -> Visibility { - match visibility { - RawVisibility::This => Visibility::Module(ModuleId { - package: self.package, - local_id: original_module, - }), - RawVisibility::Super => { - let parent_module_id = self[original_module].parent.unwrap_or(original_module); - Visibility::Module(ModuleId { - package: self.package, - local_id: parent_module_id, - }) - } - RawVisibility::Package => Visibility::Module(ModuleId { - package: self.package, - local_id: self.root, - }), - RawVisibility::Public => Visibility::Public, - } - } - /// Returns the module that is defined by the specified `file` - pub fn module_for_file(&self, file: FileId) -> Option { + pub fn module_for_file(&self, file: FileId) -> Option { self.modules.iter().find_map(|(idx, data)| { if data.file == Some(file) { Some(idx) @@ -191,20 +157,20 @@ fn is_valid_module_name(name: impl AsRef) -> bool { } mod diagnostics { - use super::LocalModuleId; + use super::PackageModuleId; use crate::FileId; #[derive(Debug, PartialEq, Eq)] pub enum ModuleTreeDiagnostic { - DuplicateModuleFile(LocalModuleId, Vec), - InvalidModuleName(LocalModuleId), + DuplicateModuleFile(PackageModuleId, Vec), + InvalidModuleName(PackageModuleId), } } #[cfg(test)] mod test { use super::*; - use crate::{mock::MockDatabase, with_fixture::WithFixture}; + use crate::{SourceDatabaseStorage, WithFixture}; #[test] fn valid_module_name() { @@ -241,6 +207,16 @@ mod test { ); } + /// A mock implementation of the IR database. It can be used to set up a + /// simple test case. + #[salsa::database(SourceDatabaseStorage)] + #[derive(Default)] + struct MockDatabase { + storage: salsa::Storage, + } + + impl salsa::Database for MockDatabase {} + #[test] fn module_tree() { let mock_db = MockDatabase::with_files( diff --git a/crates/mun_hir/src/package_set.rs b/crates/mun_hir_input/src/package_set.rs similarity index 58% rename from crates/mun_hir/src/package_set.rs rename to crates/mun_hir_input/src/package_set.rs index 384b4c96..6264dc25 100644 --- a/crates/mun_hir/src/package_set.rs +++ b/crates/mun_hir_input/src/package_set.rs @@ -4,26 +4,38 @@ use rustc_hash::FxHashMap; use crate::SourceRootId; -/// Information regarding a package -#[derive(Debug, Clone)] -pub struct PackageData { - /// The source root that holds the source files - pub source_root: SourceRootId, -} - /// Represents the id of a single package, all packages have a unique id, the /// main package and all dependent packages. +/// +/// The [`PackageId`] is used to uniquely identify a package in the project. To +/// gain access to the data of a package, the [`PackageSet`] is used. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct PackageId(pub u32); -/// Represents information about a set of packages in a compilation +/// Top-level information for a single package in the project. +/// +/// Packages are usually represented by a [`PackageId`]. The [`PackageSet`] +/// stores a mapping from [`PackageId`] to [`PackageData`]. +#[derive(Debug, Clone)] +pub struct PackageData { + /// The source root which groups together all the source files of a package. + pub source_root: SourceRootId, +} + +/// Contains information about all the packages in the project. #[derive(Debug, Clone, Default)] pub struct PackageSet { arena: FxHashMap, } impl PackageSet { - /// Adds a new package to the package set + /// Returns an empty package set + pub fn new() -> Self { + Self::default() + } + + /// Adds a new package to the package set with the source files located add + /// the specified root. Returns the `PackageId` associated with the package. pub fn add_package(&mut self, source_root: SourceRootId) -> PackageId { let data = PackageData { source_root }; let package_id = PackageId(self.arena.len() as u32); diff --git a/crates/mun_hir/src/input.rs b/crates/mun_hir_input/src/source_root.rs similarity index 66% rename from crates/mun_hir/src/input.rs rename to crates/mun_hir_input/src/source_root.rs index 5359562b..f1069b51 100644 --- a/crates/mun_hir/src/input.rs +++ b/crates/mun_hir_input/src/source_root.rs @@ -1,16 +1,10 @@ use mun_paths::{RelativePath, RelativePathBuf}; use rustc_hash::FxHashMap; -/// `FileId` is an integer which uniquely identifies a file. File paths are -/// messy and system-dependent, so most of the code should work directly with -/// `FileId`, without inspecting the path. The mapping between `FileId` and path -/// and `SourceRoot` is constant. A file rename is represented as a pair of -/// deletion/creation. -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct FileId(pub u32); +use crate::FileId; -/// Files are grouped into source roots. A source root is a directory on the -/// file systems which is watched for changes. Typically it corresponds to a +/// Files are grouped into [`SourceRoot`]. A source root is a directory on the +/// file systems which is watched for changes. Typically, it corresponds to a /// single library. /// /// Paths to files are always relative to a source root, the compiler does not @@ -19,9 +13,8 @@ pub struct FileId(pub u32); /// /// Multiple source roots can be present if the language server is monitoring /// multiple directories. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct SourceRootId(pub u32); - +/// +/// [`SourceRoot`]s are identified by a unique [`SourceRootId`]. #[derive(Default, Clone, Debug, PartialEq, Eq)] pub struct SourceRoot { files: FxHashMap, @@ -42,3 +35,9 @@ impl SourceRoot { self.files.keys().copied() } } + +/// A unique identifier of a [`SourceRoot`]. +/// +/// When referring to a [`SourceRoot`] it is preferable to use this identifier. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct SourceRootId(pub u32); diff --git a/crates/mun_language_server/Cargo.toml b/crates/mun_language_server/Cargo.toml index 902b1bf2..fb35fe19 100644 --- a/crates/mun_language_server/Cargo.toml +++ b/crates/mun_language_server/Cargo.toml @@ -13,6 +13,8 @@ repository.workspace = true license.workspace = true [dependencies] +mun_db = { version = "0.6.0-dev", path="../mun_db" } +mun_hir_input = { version = "0.6.0-dev", path="../mun_hir_input" } mun_hir = { version = "0.6.0-dev", path="../mun_hir" } mun_vfs = { version = "0.6.0-dev", path = "../mun_vfs" } mun_project = { version = "0.6.0-dev", path = "../mun_project" } diff --git a/crates/mun_language_server/src/analysis.rs b/crates/mun_language_server/src/analysis.rs index aa13bfd3..e835aef4 100644 --- a/crates/mun_language_server/src/analysis.rs +++ b/crates/mun_language_server/src/analysis.rs @@ -1,6 +1,7 @@ use std::sync::Arc; -use mun_hir::{line_index::LineIndex, AstDatabase, SourceDatabase}; +use mun_hir::AstDatabase; +use mun_hir_input::{FileId, LineIndex, PackageId, SourceDatabase}; use mun_syntax::SourceFile; use salsa::{ParallelDatabase, Snapshot}; @@ -53,20 +54,17 @@ pub struct AnalysisSnapshot { impl AnalysisSnapshot { /// Returns the syntax tree of the file. - pub fn parse(&self, file_id: mun_hir::FileId) -> Cancelable { + pub fn parse(&self, file_id: FileId) -> Cancelable { self.with_db(|db| db.parse(file_id).tree()) } /// Computes the set of diagnostics for the given file. - pub fn diagnostics(&self, file_id: mun_hir::FileId) -> Cancelable> { + pub fn diagnostics(&self, file_id: FileId) -> Cancelable> { self.with_db(|db| diagnostics::diagnostics(db, file_id)) } /// Returns all the source files of the given package - pub fn package_source_files( - &self, - package_id: mun_hir::PackageId, - ) -> Cancelable> { + pub fn package_source_files(&self, package_id: PackageId) -> Cancelable> { self.with_db(|db| { let packages = db.packages(); let source_root = db.source_root(packages[package_id].source_root); @@ -75,14 +73,14 @@ impl AnalysisSnapshot { } /// Returns the line index for the specified file - pub fn file_line_index(&self, file_id: mun_hir::FileId) -> Cancelable> { + pub fn file_line_index(&self, file_id: FileId) -> Cancelable> { self.with_db(|db| db.line_index(file_id)) } /// Returns a tree structure of the symbols of a file. pub fn file_structure( &self, - file_id: mun_hir::FileId, + file_id: FileId, ) -> Cancelable> { self.with_db(|db| file_structure::file_structure(&db.parse(file_id).tree())) } diff --git a/crates/mun_language_server/src/change.rs b/crates/mun_language_server/src/change.rs index f48a722b..e3974dd1 100644 --- a/crates/mun_language_server/src/change.rs +++ b/crates/mun_language_server/src/change.rs @@ -1,15 +1,15 @@ use std::sync::Arc; -use mun_hir::SourceDatabase; +use mun_hir_input::{FileId, PackageSet, SourceDatabase, SourceRoot, SourceRootId}; use crate::db::AnalysisDatabase; /// Represents an atomic change to the state of the `Analysis` #[derive(Default)] pub struct AnalysisChange { - packages: Option, - roots: Option>, - files_changed: Vec<(mun_hir::FileId, Option>)>, + packages: Option, + roots: Option>, + files_changed: Vec<(FileId, Option>)>, } impl AnalysisChange { @@ -19,17 +19,17 @@ impl AnalysisChange { } /// Sets the packages - pub fn set_packages(&mut self, packages: mun_hir::PackageSet) { + pub fn set_packages(&mut self, packages: PackageSet) { self.packages = Some(packages); } /// Records the addition of a new root - pub fn set_roots(&mut self, roots: Vec) { + pub fn set_roots(&mut self, roots: Vec) { self.roots = Some(roots); } /// Records the change of content of a specific file - pub fn change_file(&mut self, file_id: mun_hir::FileId, new_text: Option>) { + pub fn change_file(&mut self, file_id: FileId, new_text: Option>) { self.files_changed.push((file_id, new_text)); } } @@ -45,7 +45,7 @@ impl AnalysisDatabase { // Modify the source roots if let Some(roots) = change.roots { for (idx, root) in roots.into_iter().enumerate() { - let root_id = mun_hir::SourceRootId(idx as u32); + let root_id = SourceRootId(idx as u32); for file_id in root.files() { self.set_file_source_root(file_id, root_id); } diff --git a/crates/mun_language_server/src/change_fixture.rs b/crates/mun_language_server/src/change_fixture.rs index 0a642692..e5c2a36f 100644 --- a/crates/mun_language_server/src/change_fixture.rs +++ b/crates/mun_language_server/src/change_fixture.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use mun_hir::fixture::Fixture; +use mun_hir_input::{FileId, Fixture, PackageSet, SourceRoot, SourceRootId}; use mun_syntax::{TextRange, TextSize}; use crate::change::AnalysisChange; @@ -11,8 +11,8 @@ pub const CURSOR_MARKER: &str = "$0"; /// an entire [`AnalysisDatabase`] with. It can also optionally contain a cursor /// indicated by `$0`. pub struct ChangeFixture { - pub file_position: Option<(mun_hir::FileId, RangeOrOffset)>, - pub files: Vec, + pub file_position: Option<(FileId, RangeOrOffset)>, + pub files: Vec, pub change: AnalysisChange, } @@ -21,10 +21,10 @@ impl ChangeFixture { let fixture = Fixture::parse(fixture); let mut change = AnalysisChange::default(); - let mut source_root = mun_hir::SourceRoot::default(); - let mut package_set = mun_hir::PackageSet::default(); + let mut source_root = SourceRoot::default(); + let mut package_set = PackageSet::default(); - let mut file_id = mun_hir::FileId(0); + let mut file_id = FileId(0); let mut file_position = None; let mut files = Vec::new(); @@ -47,7 +47,7 @@ impl ChangeFixture { file_id.0 += 1; } - package_set.add_package(mun_hir::SourceRootId(0)); + package_set.add_package(SourceRootId(0)); change.set_roots(vec![source_root]); change.set_packages(package_set); diff --git a/crates/mun_language_server/src/completion/dot.rs b/crates/mun_language_server/src/completion/dot.rs index 2fe9df64..26017b9c 100644 --- a/crates/mun_language_server/src/completion/dot.rs +++ b/crates/mun_language_server/src/completion/dot.rs @@ -1,4 +1,4 @@ -use mun_hir::Upcast; +use mun_db::Upcast; use super::{CompletionContext, Completions}; diff --git a/crates/mun_language_server/src/db.rs b/crates/mun_language_server/src/db.rs index c5bfae11..96fac4c1 100644 --- a/crates/mun_language_server/src/db.rs +++ b/crates/mun_language_server/src/db.rs @@ -2,7 +2,8 @@ use std::panic; -use mun_hir::{HirDatabase, Upcast}; +use mun_db::Upcast; +use mun_hir::HirDatabase; use mun_target::spec::Target; use salsa::{Database, Durability, Snapshot}; @@ -21,7 +22,7 @@ use crate::cancelation::Canceled; /// With this struct we can reuse a lot of functionality from the compiler which /// should provide a better user experience. #[salsa::database( - mun_hir::SourceDatabaseStorage, + mun_hir_input::SourceDatabaseStorage, mun_hir::DefDatabaseStorage, mun_hir::HirDatabaseStorage, mun_hir::AstDatabaseStorage, @@ -70,8 +71,8 @@ impl Upcast for AnalysisDatabase { } } -impl Upcast for AnalysisDatabase { - fn upcast(&self) -> &(dyn mun_hir::SourceDatabase + 'static) { +impl Upcast for AnalysisDatabase { + fn upcast(&self) -> &(dyn mun_hir_input::SourceDatabase + 'static) { self } } diff --git a/crates/mun_language_server/src/diagnostics.rs b/crates/mun_language_server/src/diagnostics.rs index 432570de..2c37b2fc 100644 --- a/crates/mun_language_server/src/diagnostics.rs +++ b/crates/mun_language_server/src/diagnostics.rs @@ -1,7 +1,8 @@ use std::cell::RefCell; use mun_diagnostics::DiagnosticForWith; -use mun_hir::{AstDatabase, InFile, ModuleId, PackageId, SourceDatabase}; +use mun_hir::{AstDatabase, InFile, Module}; +use mun_hir_input::{FileId, ModuleId, PackageId, SourceDatabase}; use mun_syntax::{Location, TextRange}; use crate::db::AnalysisDatabase; @@ -30,7 +31,7 @@ fn location_to_range(location: Location) -> TextRange { } /// Computes all the diagnostics for the specified file. -pub(crate) fn diagnostics(db: &AnalysisDatabase, file_id: mun_hir::FileId) -> Vec { +pub(crate) fn diagnostics(db: &AnalysisDatabase, file_id: FileId) -> Vec { let mut result = Vec::new(); // Add all syntax errors @@ -69,7 +70,7 @@ pub(crate) fn diagnostics(db: &AnalysisDatabase, file_id: mun_hir::FileId) -> Ve package: package_id, local_id, }; - mun_hir::Module::from(module_id).diagnostics(db, &mut sink); + Module::from(module_id).diagnostics(db, &mut sink); } drop(sink); diff --git a/crates/mun_language_server/src/from_lsp.rs b/crates/mun_language_server/src/from_lsp.rs index 50ec7fd8..c327c046 100644 --- a/crates/mun_language_server/src/from_lsp.rs +++ b/crates/mun_language_server/src/from_lsp.rs @@ -4,7 +4,7 @@ use std::convert::TryFrom; use lsp_types::Url; -use mun_hir::line_index::LineIndex; +use mun_hir_input::{FileId, LineCol, LineIndex}; use mun_paths::AbsPathBuf; use mun_syntax::{TextRange, TextSize}; @@ -23,20 +23,20 @@ pub(crate) fn abs_path(uri: &Url) -> anyhow::Result { pub(crate) fn file_id( snapshot: &LanguageServerSnapshot, url: &lsp_types::Url, -) -> anyhow::Result { +) -> anyhow::Result { abs_path(url).and_then(|path| { snapshot .vfs .read() .file_id(&path) .ok_or_else(|| anyhow::anyhow!("url does not refer to a file: {}", url)) - .map(|id| mun_hir::FileId(id.0)) + .map(|id| FileId(id.0)) }) } /// Converts the specified offset to our own `TextSize` structure pub(crate) fn offset(line_index: &LineIndex, position: lsp_types::Position) -> TextSize { - let line_col = mun_hir::line_index::LineCol { + let line_col = LineCol { line: position.line, col_utf16: position.character, }; diff --git a/crates/mun_language_server/src/lib.rs b/crates/mun_language_server/src/lib.rs index fb149045..2e151ce8 100644 --- a/crates/mun_language_server/src/lib.rs +++ b/crates/mun_language_server/src/lib.rs @@ -2,6 +2,7 @@ use std::convert::TryFrom; pub use config::{Config, FilesWatcher}; pub use main_loop::main_loop; +use mun_hir_input::FileId; use mun_paths::AbsPathBuf; use mun_project::ProjectManifest; use mun_syntax::{TextRange, TextSize}; @@ -31,14 +32,14 @@ mod to_lsp; /// Represents a position in a file #[derive(Clone, Copy, Debug)] pub struct FilePosition { - pub file_id: mun_hir::FileId, + pub file_id: FileId, pub offset: TextSize, } /// Represents a range of text in a file. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct FileRange { - pub file_id: mun_hir::FileId, + pub file_id: FileId, pub range: TextRange, } diff --git a/crates/mun_language_server/src/lsp_utils.rs b/crates/mun_language_server/src/lsp_utils.rs index 357fea5b..0bf48e5a 100644 --- a/crates/mun_language_server/src/lsp_utils.rs +++ b/crates/mun_language_server/src/lsp_utils.rs @@ -1,4 +1,4 @@ -use mun_hir::line_index::LineIndex; +use mun_hir_input::LineIndex; use crate::from_lsp; diff --git a/crates/mun_language_server/src/state.rs b/crates/mun_language_server/src/state.rs index 9784a192..c2af9413 100644 --- a/crates/mun_language_server/src/state.rs +++ b/crates/mun_language_server/src/state.rs @@ -6,6 +6,7 @@ use lsp_types::{ notification::{Notification, PublishDiagnostics}, PublishDiagnosticsParams, }; +use mun_hir_input::{FileId, PackageId, PackageSet}; use mun_paths::AbsPathBuf; use mun_vfs::VirtualFileSystem; use parking_lot::RwLock; @@ -113,7 +114,7 @@ impl LanguageServerState { // state let mut analysis = Analysis::default(); let mut change = AnalysisChange::new(); - change.set_packages(mun_hir::PackageSet::default()); + change.set_packages(PackageSet::default()); change.set_roots(Vec::default()); analysis.apply_change(change); @@ -247,7 +248,7 @@ impl LanguageServerState { fn handle_diagnostics(state: LanguageServerSnapshot, sender: Sender) -> anyhow::Result<()> { // Iterate over all files for (idx, _package) in state.packages.iter().enumerate() { - let package_id = mun_hir::PackageId(idx as u32); + let package_id = PackageId(idx as u32); // Get all the files let files = state.analysis.package_source_files(package_id)?; @@ -356,7 +357,7 @@ impl LanguageServerState { let text = String::from_utf8(bytes).ok().map(Arc::from); // Notify the database about this change - analysis_change.change_file(mun_hir::FileId(file.file_id.0), text); + analysis_change.change_file(FileId(file.file_id.0), text); } // If an entry was created or deleted we have to recreate all source roots diff --git a/crates/mun_language_server/src/state/workspace.rs b/crates/mun_language_server/src/state/workspace.rs index a1574e08..7e8fc11d 100644 --- a/crates/mun_language_server/src/state/workspace.rs +++ b/crates/mun_language_server/src/state/workspace.rs @@ -3,6 +3,7 @@ use std::{ sync::Arc, }; +use mun_hir_input::{FileId, PackageSet, SourceRoot, SourceRootId}; use mun_paths::{AbsPathBuf, RelativePath}; use super::LanguageServerState; @@ -94,9 +95,9 @@ impl LanguageServerState { self.vfs_monitor.set_config(monitor_config); // Create the set of packages - let mut package_set = mun_hir::PackageSet::default(); + let mut package_set = PackageSet::default(); for (idx, _package) in packages.iter().enumerate() { - package_set.add_package(mun_hir::SourceRootId(idx as u32)); + package_set.add_package(SourceRootId(idx as u32)); } change.set_packages(package_set); @@ -109,9 +110,9 @@ impl LanguageServerState { } /// Recomputes all the source roots based on the `packages` - pub(crate) fn recompute_source_roots(&self) -> Vec { + pub(crate) fn recompute_source_roots(&self) -> Vec { // Iterate over all sources and see to which package they belong - let mut source_roots = vec![mun_hir::SourceRoot::default(); self.packages.len()]; + let mut source_roots = vec![SourceRoot::default(); self.packages.len()]; // Source directories let source_dirs = self @@ -138,7 +139,7 @@ impl LanguageServerState { .map(|relative| (index, relative)) }) { - source_roots[idx].insert_file(mun_hir::FileId(file_id.0), relative_path); + source_roots[idx].insert_file(FileId(file_id.0), relative_path); } } diff --git a/crates/mun_language_server/src/to_lsp.rs b/crates/mun_language_server/src/to_lsp.rs index 1e88cbe6..576fe3be 100644 --- a/crates/mun_language_server/src/to_lsp.rs +++ b/crates/mun_language_server/src/to_lsp.rs @@ -4,6 +4,7 @@ use std::{ }; use lsp_types::Url; +use mun_hir_input::{FileId, LineIndex}; use mun_syntax::{TextRange, TextSize}; use crate::{ @@ -54,20 +55,14 @@ fn url_from_path_with_drive_lowercasing(path: impl AsRef) -> anyhow::Resul } } -pub(crate) fn range( - range: TextRange, - line_index: &mun_hir::line_index::LineIndex, -) -> lsp_types::Range { +pub(crate) fn range(range: TextRange, line_index: &LineIndex) -> lsp_types::Range { lsp_types::Range { start: position(range.start(), line_index), end: position(range.end(), line_index), } } -pub(crate) fn position( - range: TextSize, - line_index: &mun_hir::line_index::LineIndex, -) -> lsp_types::Position { +pub(crate) fn position(range: TextSize, line_index: &LineIndex) -> lsp_types::Position { let line_col = line_index.line_col(range); lsp_types::Position { line: line_col.line, @@ -88,10 +83,7 @@ pub(crate) fn symbol_kind(symbol_kind: SymbolKind) -> lsp_types::SymbolKind { } /// Returns the `Url` associated with the specified `FileId`. -pub(crate) fn url( - snapshot: &LanguageServerSnapshot, - file_id: mun_hir::FileId, -) -> anyhow::Result { +pub(crate) fn url(snapshot: &LanguageServerSnapshot, file_id: FileId) -> anyhow::Result { let vfs = snapshot.vfs.read(); let path = vfs.file_path(mun_vfs::FileId(file_id.0)); let url = url_from_path_with_drive_lowercasing(path)?; diff --git a/crates/mun_language_server/tests/support.rs b/crates/mun_language_server/tests/support.rs index 027ed803..5bcd86f9 100644 --- a/crates/mun_language_server/tests/support.rs +++ b/crates/mun_language_server/tests/support.rs @@ -11,7 +11,7 @@ use lsp_types::{ notification::Exit, request::Shutdown, ProgressParams, ProgressParamsValue, Url, WorkDoneProgress, }; -use mun_hir::fixture::Fixture; +use mun_hir_input::Fixture; use mun_language_server::{main_loop, Config, FilesWatcher}; use mun_paths::AbsPathBuf; use mun_project::ProjectManifest; diff --git a/crates/mun_test/Cargo.toml b/crates/mun_test/Cargo.toml index 9208198a..0685fd8e 100644 --- a/crates/mun_test/Cargo.toml +++ b/crates/mun_test/Cargo.toml @@ -13,6 +13,7 @@ repository.workspace = true license.workspace = true [dependencies] +mun_hir_input = { version = "0.6.0-dev", path = "../mun_hir_input" } mun_compiler = { version = "0.6.0-dev", path = "../mun_compiler" } mun_runtime = { version = "0.6.0-dev", path = "../mun_runtime" } mun_hir = { version = "0.6.0-dev", path = "../mun_hir" } diff --git a/crates/mun_test/src/driver.rs b/crates/mun_test/src/driver.rs index c1f18d49..786bc495 100644 --- a/crates/mun_test/src/driver.rs +++ b/crates/mun_test/src/driver.rs @@ -5,6 +5,7 @@ use std::{ }; use mun_compiler::{Config, DisplayColor, Driver, PathOrInline, RelativePathBuf}; +use mun_hir_input::Fixture; use mun_runtime::{InitError, Runtime, RuntimeBuilder}; /// Implements a compiler that generates and temporarily stores a `*.munlib` @@ -35,7 +36,7 @@ impl CompileTestDriver { // Write the contents of the fixture to a temporary directory let temp_source_dir = tempfile::TempDir::new().unwrap(); - for entry in mun_hir::fixture::Fixture::parse(text) { + for entry in Fixture::parse(text) { let path = entry.relative_path.to_path(temp_source_dir.path()); std::fs::create_dir_all(path.parent().unwrap()).unwrap(); std::fs::write(&path, entry.text).unwrap();