diff --git a/crates/mun_codegen/src/ir/body.rs b/crates/mun_codegen/src/ir/body.rs index 1648c19a..8f2251d9 100644 --- a/crates/mun_codegen/src/ir/body.rs +++ b/crates/mun_codegen/src/ir/body.rs @@ -587,6 +587,7 @@ impl<'db, 'ink, 't> BodyIrGenerator<'db, 'ink, 't> { } ValueNs::StructId(_) => self.gen_unit_struct_lit(expr), ValueNs::FunctionId(_) => panic!("unable to generate path expression from a function"), + ValueNs::ConstId(_const_id) => todo!(), } } @@ -624,7 +625,7 @@ impl<'db, 'ink, 't> BodyIrGenerator<'db, 'ink, 't> { .pat_to_local .get(&pat) .expect("unresolved local binding"), - ValueNs::FunctionId(_) | ValueNs::StructId(_) => { + ValueNs::FunctionId(_) | ValueNs::StructId(_) | ValueNs::ConstId(_) => { panic!("no support for module definitions") } } diff --git a/crates/mun_codegen/src/ir/file_group.rs b/crates/mun_codegen/src/ir/file_group.rs index 555257e3..ed3c969d 100644 --- a/crates/mun_codegen/src/ir/file_group.rs +++ b/crates/mun_codegen/src/ir/file_group.rs @@ -73,12 +73,12 @@ pub(crate) fn gen_file_group_ir<'ink>( ); } } - // TODO: Extern types for functions? ModuleDef::Module(_) | ModuleDef::Struct(_) | ModuleDef::PrimitiveType(_) | ModuleDef::TypeAlias(_) - | ModuleDef::Function(_) => (), + | ModuleDef::Function(_) + | ModuleDef::Const(_) => (), } } @@ -140,7 +140,10 @@ pub(crate) fn gen_file_group_ir<'ink>( ModuleDef::Function(f) => { type_table_builder.collect_fn(f); } - ModuleDef::PrimitiveType(_) | ModuleDef::TypeAlias(_) | ModuleDef::Module(_) => (), + ModuleDef::PrimitiveType(_) + | ModuleDef::TypeAlias(_) + | ModuleDef::Module(_) + | ModuleDef::Const(_) => (), } } diff --git a/crates/mun_hir/src/code_model.rs b/crates/mun_hir/src/code_model.rs index caa631a4..908d979e 100644 --- a/crates/mun_hir/src/code_model.rs +++ b/crates/mun_hir/src/code_model.rs @@ -1,3 +1,4 @@ +mod r#const; mod function; mod r#impl; mod module; @@ -9,6 +10,8 @@ mod type_alias; use std::sync::Arc; +use r#const::Const; + pub use self::{ function::{Function, FunctionData}, module::{Module, ModuleDef}, @@ -25,6 +28,7 @@ use crate::{expr::BodySourceMap, HirDatabase, Name}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum DefWithBody { Function(Function), + Const(Const), } impl_froms!(DefWithBody: Function); @@ -32,12 +36,14 @@ impl DefWithBody { pub fn module(self, db: &dyn HirDatabase) -> Module { match self { DefWithBody::Function(f) => f.module(db), + DefWithBody::Const(_) => todo!(), } } pub fn body_source_map(self, db: &dyn HirDatabase) -> Arc { match self { DefWithBody::Function(f) => f.body_source_map(db), + DefWithBody::Const(_) => todo!(), } } } diff --git a/crates/mun_hir/src/code_model/const.rs b/crates/mun_hir/src/code_model/const.rs new file mode 100644 index 00000000..a2d1e0a3 --- /dev/null +++ b/crates/mun_hir/src/code_model/const.rs @@ -0,0 +1,6 @@ +use crate::{ids::ConstId, DiagnosticSink, HirDatabase}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct Const { + pub(crate) id: ConstId, +} diff --git a/crates/mun_hir/src/code_model/module.rs b/crates/mun_hir/src/code_model/module.rs index 6af8ccbf..72980446 100644 --- a/crates/mun_hir/src/code_model/module.rs +++ b/crates/mun_hir/src/code_model/module.rs @@ -1,6 +1,9 @@ use mun_hir_input::{FileId, ModuleId}; -use super::{r#impl::Impl, AssocItem, Function, Package, PrimitiveType, Struct, TypeAlias}; +use super::{ + r#const::Const, r#impl::Impl, AssocItem, DefWithBody, Function, Package, PrimitiveType, Struct, + TypeAlias, +}; use crate::{ids::ItemDefinitionId, DiagnosticSink, HirDatabase}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] @@ -97,6 +100,7 @@ impl Module { ModuleDef::Function(f) => f.diagnostics(db, sink), ModuleDef::Struct(s) => s.diagnostics(db, sink), ModuleDef::TypeAlias(t) => t.diagnostics(db, sink), + ModuleDef::Const(_) => todo!(), _ => (), } } @@ -161,11 +165,22 @@ impl Module { pub enum ModuleDef { Module(Module), Function(Function), + Const(Const), PrimitiveType(PrimitiveType), Struct(Struct), TypeAlias(TypeAlias), } +impl ModuleDef { + pub fn as_def_with_body(self) -> Option { + match self { + ModuleDef::Function(f) => Some(DefWithBody::Function(f)), + ModuleDef::Const(c) => Some(DefWithBody::Const(c)), + _ => None, + } + } +} + impl From for ModuleDef { fn from(t: Function) -> Self { ModuleDef::Function(t) @@ -184,6 +199,12 @@ impl From for ModuleDef { } } +impl From for ModuleDef { + fn from(t: Const) -> Self { + ModuleDef::Const(t) + } +} + impl From for ModuleDef { fn from(t: TypeAlias) -> Self { ModuleDef::TypeAlias(t) @@ -202,6 +223,7 @@ impl From for ModuleDef { ItemDefinitionId::ModuleId(id) => Module { id }.into(), ItemDefinitionId::FunctionId(id) => Function { id }.into(), ItemDefinitionId::StructId(id) => Struct { id }.into(), + ItemDefinitionId::ConstId(id) => Const { id }.into(), ItemDefinitionId::TypeAliasId(id) => TypeAlias { id }.into(), ItemDefinitionId::PrimitiveType(ty) => PrimitiveType { inner: ty }.into(), } diff --git a/crates/mun_hir/src/db.rs b/crates/mun_hir/src/db.rs index d6c6d927..7e9696c0 100644 --- a/crates/mun_hir/src/db.rs +++ b/crates/mun_hir/src/db.rs @@ -43,6 +43,8 @@ pub trait InternDatabase: SourceDatabase { #[salsa::interned] fn intern_struct(&self, loc: ids::StructLoc) -> ids::StructId; #[salsa::interned] + fn intern_const(&self, loc: ids::ConstLoc) -> ids::ConstId; + #[salsa::interned] fn intern_type_alias(&self, loc: ids::TypeAliasLoc) -> ids::TypeAliasId; #[salsa::interned] fn intern_impl(self, loc: ids::ImplLoc) -> ids::ImplId; diff --git a/crates/mun_hir/src/expr.rs b/crates/mun_hir/src/expr.rs index 4a42f83f..f709d328 100644 --- a/crates/mun_hir/src/expr.rs +++ b/crates/mun_hir/src/expr.rs @@ -74,6 +74,7 @@ impl Body { collector = ExprCollector::new(def, src.file_id, db); collector.collect_fn_body(&src.value); } + DefWithBodyId::ConstId(_const_id) => todo!(), } let (body, source_map) = collector.finish(); diff --git a/crates/mun_hir/src/ids.rs b/crates/mun_hir/src/ids.rs index 62c2adac..92dad53a 100644 --- a/crates/mun_hir/src/ids.rs +++ b/crates/mun_hir/src/ids.rs @@ -3,7 +3,7 @@ use std::hash::{Hash, Hasher}; use mun_hir_input::ModuleId; use crate::{ - item_tree::{Function, Impl, ItemTreeId, ItemTreeNode, Struct, TypeAlias}, + item_tree::{Const, Function, Impl, ItemTreeId, ItemTreeNode, Struct, TypeAlias}, primitive_type::PrimitiveType, DefDatabase, }; @@ -123,6 +123,12 @@ pub struct StructId(salsa::InternId); pub(crate) type StructLoc = ItemLoc; impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct); +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] +pub struct ConstId(salsa::InternId); + +pub(crate) type ConstLoc = AssocItemLoc; +impl_intern!(ConstId, ConstLoc, intern_const, lookup_intern_const); + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct TypeAliasId(salsa::InternId); @@ -149,6 +155,7 @@ pub enum ItemDefinitionId { ModuleId(ModuleId), FunctionId(FunctionId), StructId(StructId), + ConstId(ConstId), TypeAliasId(TypeAliasId), PrimitiveType(PrimitiveType), } @@ -171,6 +178,12 @@ impl From for ItemDefinitionId { } } +impl From for ItemDefinitionId { + fn from(id: ConstId) -> Self { + ItemDefinitionId::ConstId(id) + } +} + impl From for ItemDefinitionId { fn from(id: TypeAliasId) -> Self { ItemDefinitionId::TypeAliasId(id) @@ -193,6 +206,7 @@ pub enum AssocItemId { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum DefWithBodyId { FunctionId(FunctionId), + ConstId(ConstId), } impl From for DefWithBodyId { diff --git a/crates/mun_hir/src/item_scope.rs b/crates/mun_hir/src/item_scope.rs index 58613786..c26e6bf9 100644 --- a/crates/mun_hir/src/item_scope.rs +++ b/crates/mun_hir/src/item_scope.rs @@ -234,6 +234,7 @@ impl PerNs<(ItemDefinitionId, Visibility)> { PerNs::types((def, vis)) } } + ItemDefinitionId::ConstId(_) => PerNs::values((def, vis)), ItemDefinitionId::TypeAliasId(_) | ItemDefinitionId::PrimitiveType(_) => { PerNs::types((def, vis)) } diff --git a/crates/mun_hir/src/item_tree.rs b/crates/mun_hir/src/item_tree.rs index c1a4863e..4dacf303 100644 --- a/crates/mun_hir/src/item_tree.rs +++ b/crates/mun_hir/src/item_tree.rs @@ -118,6 +118,7 @@ struct ItemTreeData { fields: Arena, type_aliases: Arena, impls: Arena, + consts: Arena, visibilities: ItemVisibilities, } @@ -230,6 +231,7 @@ mod_items! { TypeAlias in type_aliases -> ast::TypeAliasDef, Import in imports -> ast::Use, Impl in impls -> ast::Impl, + Const in consts -> ast::Const, } macro_rules! impl_index { @@ -336,6 +338,13 @@ impl FunctionFlags { } } +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct Const { + pub name: Name, + pub visibility: RawVisibilityId, + pub ast_id: FileAstId, +} + #[derive(Debug, Clone, Eq, PartialEq)] pub struct Param { pub type_ref: LocalTypeRefId, @@ -530,6 +539,7 @@ mod diagnostics { ) } ModItem::Impl(_) => unreachable!("impls cannot be duplicated"), + ModItem::Const(_item) => todo!(), } } diff --git a/crates/mun_hir/src/item_tree/lower.rs b/crates/mun_hir/src/item_tree/lower.rs index 8a165dd0..5df5de28 100644 --- a/crates/mun_hir/src/item_tree/lower.rs +++ b/crates/mun_hir/src/item_tree/lower.rs @@ -10,9 +10,9 @@ use mun_syntax::ast::{ use smallvec::SmallVec; use super::{ - diagnostics, AssociatedItem, Field, Fields, Function, FunctionFlags, IdRange, Impl, ItemTree, - ItemTreeData, ItemTreeNode, ItemVisibilities, LocalItemTreeId, ModItem, Param, ParamAstId, - RawVisibilityId, Struct, TypeAlias, + diagnostics, AssociatedItem, Const, Field, Fields, Function, FunctionFlags, IdRange, Impl, + ItemTree, ItemTreeData, ItemTreeNode, ItemVisibilities, LocalItemTreeId, ModItem, Param, + ParamAstId, RawVisibilityId, Struct, TypeAlias, }; use crate::{ item_tree::Import, @@ -88,6 +88,7 @@ impl Context { .map_or_else(|| import.path.last_segment(), |alias| alias.as_name()) } } + ModItem::Const(item) => Some(&self.data.consts[item.index].name), ModItem::Impl(_) => None, }; if let Some(name) = name { @@ -122,9 +123,27 @@ impl Context { self.lower_use(&ast).into_iter().map(Into::into).collect(), )), ast::ModuleItemKind::Impl(ast) => self.lower_impl(&ast).map(Into::into), + ast::ModuleItemKind::Const(ast) => self.lower_const(ast).map(Into::into), } } + /// Lowers a const + fn lower_const(&mut self, ast: ast::Const) -> Option> { + let name = ast.name()?.as_name(); + let visibility = lower_visibility(&ast); + + Some( + self.data + .consts + .alloc(Const { + name, + visibility, + ast_id: self.source_ast_id_map.ast_id(&ast), + }) + .into(), + ) + } + /// Lowers a `use` statement fn lower_use(&mut self, use_item: &ast::Use) -> Vec> { let visibility = lower_visibility(use_item); diff --git a/crates/mun_hir/src/item_tree/pretty.rs b/crates/mun_hir/src/item_tree/pretty.rs index cee4c716..c88da010 100644 --- a/crates/mun_hir/src/item_tree/pretty.rs +++ b/crates/mun_hir/src/item_tree/pretty.rs @@ -70,6 +70,7 @@ impl Printer<'_> { ModItem::TypeAlias(it) => self.print_type_alias(it), ModItem::Import(it) => self.print_use(it), ModItem::Impl(it) => self.print_impl(it), + ModItem::Const(_it) => todo!(), } } diff --git a/crates/mun_hir/src/package_defs/collector.rs b/crates/mun_hir/src/package_defs/collector.rs index 3dec5a29..98c38da5 100644 --- a/crates/mun_hir/src/package_defs/collector.rs +++ b/crates/mun_hir/src/package_defs/collector.rs @@ -5,7 +5,8 @@ use rustc_hash::FxHashMap; use super::PackageDefs; use crate::{ ids::{ - FunctionLoc, ImplLoc, Intern, ItemContainerId, ItemDefinitionId, StructLoc, TypeAliasLoc, + ConstLoc, FunctionLoc, ImplLoc, Intern, ItemContainerId, ItemDefinitionId, StructLoc, + TypeAliasLoc, }, item_scope::{ImportType, ItemScope, PerNsGlobImports}, item_tree::{ @@ -525,6 +526,7 @@ impl<'a> ModCollectorContext<'a, '_> { self.collect_impl(id); continue; } + ModItem::Const(id) => self.collect_const(id), }; self.def_collector.package_defs.modules[self.module_id].add_definition(id); @@ -603,6 +605,24 @@ impl<'a> ModCollectorContext<'a, '_> { } } + fn collect_const(&self, id: LocalItemTreeId) -> DefData<'a> { + let func = &self.item_tree[id]; + DefData { + id: ConstLoc { + container: ItemContainerId::ModuleId(ModuleId { + package: self.def_collector.package_id, + local_id: self.module_id, + }), + id: ItemTreeId::new(self.file_id, id), + } + .intern(self.def_collector.db) + .into(), + name: &func.name, + visibility: &self.item_tree[func.visibility], + has_constructor: false, + } + } + /// Collects the definition data from a `TypeAlias` fn collect_type_alias(&self, id: LocalItemTreeId) -> DefData<'a> { let type_alias = &self.item_tree[id]; diff --git a/crates/mun_hir/src/resolve.rs b/crates/mun_hir/src/resolve.rs index e0bd8fcd..a5e69279 100644 --- a/crates/mun_hir/src/resolve.rs +++ b/crates/mun_hir/src/resolve.rs @@ -6,8 +6,8 @@ use crate::{ expr::{scope::LocalScopeId, PatId}, has_module::HasModule, ids::{ - DefWithBodyId, FunctionId, ImplId, ItemContainerId, ItemDefinitionId, Lookup, StructId, - TypeAliasId, + ConstId, DefWithBodyId, FunctionId, ImplId, ItemContainerId, ItemDefinitionId, Lookup, + StructId, TypeAliasId, }, item_scope::BUILTIN_SCOPE, name, @@ -56,6 +56,7 @@ pub enum ValueNs { ImplSelf(ImplId), LocalBinding(PatId), FunctionId(FunctionId), + ConstId(ConstId), StructId(StructId), } @@ -173,6 +174,7 @@ impl Resolver { let (res, vis) = match per_ns.take_values()? { (ItemDefinitionId::FunctionId(id), vis) => (ValueNs::FunctionId(id), vis), (ItemDefinitionId::StructId(id), vis) => (ValueNs::StructId(id), vis), + (ItemDefinitionId::ConstId(id), vis) => (ValueNs::ConstId(id), vis), ( ItemDefinitionId::ModuleId(_) | ItemDefinitionId::TypeAliasId(_) @@ -236,7 +238,9 @@ impl Resolver { TypeNs::PrimitiveType(id) } ( - ItemDefinitionId::ModuleId(_) | ItemDefinitionId::FunctionId(_), + ItemDefinitionId::ModuleId(_) + | ItemDefinitionId::FunctionId(_) + | ItemDefinitionId::ConstId(_), _, ) => return None, }; @@ -277,7 +281,12 @@ impl Resolver { (ItemDefinitionId::StructId(id), vis) => (TypeNs::StructId(id), vis), (ItemDefinitionId::TypeAliasId(id), vis) => (TypeNs::TypeAliasId(id), vis), (ItemDefinitionId::PrimitiveType(id), vis) => (TypeNs::PrimitiveType(id), vis), - (ItemDefinitionId::ModuleId(_) | ItemDefinitionId::FunctionId(_), _) => { + ( + ItemDefinitionId::ModuleId(_) + | ItemDefinitionId::FunctionId(_) + | ItemDefinitionId::ConstId(_), + _, + ) => { return None; } }; @@ -437,6 +446,7 @@ impl HasResolver for DefWithBodyId { fn resolver(self, db: &dyn DefDatabase) -> Resolver { match self { DefWithBodyId::FunctionId(f) => f.resolver(db), + DefWithBodyId::ConstId(_const_id) => todo!(), } } } diff --git a/crates/mun_hir/src/source_id.rs b/crates/mun_hir/src/source_id.rs index 917d9614..b56a12bb 100644 --- a/crates/mun_hir/src/source_id.rs +++ b/crates/mun_hir/src/source_id.rs @@ -66,6 +66,7 @@ macro_rules! register_ast_id_node { register_ast_id_node! { impl AstIdNode for ModuleItem, + Const, Use, FunctionDef, StructDef, diff --git a/crates/mun_hir/src/ty/infer.rs b/crates/mun_hir/src/ty/infer.rs index ee69da8d..02e4a2ef 100644 --- a/crates/mun_hir/src/ty/infer.rs +++ b/crates/mun_hir/src/ty/infer.rs @@ -115,6 +115,7 @@ pub fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc ctx.infer_signature(), + DefWithBodyId::ConstId(_) => todo!(), } ctx.infer_body(); @@ -204,6 +205,7 @@ impl<'a> InferenceResultBuilder<'a> { pub fn module(&self) -> ModuleId { match self.body.owner() { DefWithBodyId::FunctionId(func) => func.module(self.db), + DefWithBodyId::ConstId(_const_id) => todo!(), } } @@ -954,6 +956,7 @@ impl InferenceResultBuilder<'_> { .type_for_def(TypableDef::Struct(s.into()), Namespace::Values); Some(ty) } + ValueNs::ConstId(_const_id) => todo!(), } } else { // If no value was found, try to resolve the path as a type. This will always diff --git a/crates/mun_hir/src/ty/infer/place_expr.rs b/crates/mun_hir/src/ty/infer/place_expr.rs index 76fadaf3..c26bf49e 100644 --- a/crates/mun_hir/src/ty/infer/place_expr.rs +++ b/crates/mun_hir/src/ty/infer/place_expr.rs @@ -16,7 +16,8 @@ impl InferenceResultBuilder<'_> { fn check_place_path(&mut self, resolver: &Resolver, path: &Path) -> bool { match resolver.resolve_path_as_value_fully(self.db, path) { Some((ValueNs::ImplSelf(_) | ValueNs::LocalBinding(_), _)) => true, - Some((ValueNs::FunctionId(_) | ValueNs::StructId(_), _)) | None => false, + Some((ValueNs::FunctionId(_) | ValueNs::StructId(_) | ValueNs::ConstId(_), _)) + | None => false, } } } diff --git a/crates/mun_hir/src/ty/lower.rs b/crates/mun_hir/src/ty/lower.rs index fc910b77..d6d459bd 100644 --- a/crates/mun_hir/src/ty/lower.rs +++ b/crates/mun_hir/src/ty/lower.rs @@ -203,6 +203,7 @@ impl From for Option { ModuleDef::Struct(t) => Some(TypableDef::Struct(t)), ModuleDef::TypeAlias(t) => Some(TypableDef::TypeAlias(t)), ModuleDef::Module(_) => None, + ModuleDef::Const(_) => todo!(), } } } diff --git a/crates/mun_language_server/src/completion/render.rs b/crates/mun_language_server/src/completion/render.rs index dab603f4..56d73c90 100644 --- a/crates/mun_language_server/src/completion/render.rs +++ b/crates/mun_language_server/src/completion/render.rs @@ -57,7 +57,7 @@ impl<'a> Render<'a> { local_name: String, resolution: &ScopeDef, ) -> Option { - use mun_hir::ModuleDef::{Function, Module, PrimitiveType, Struct, TypeAlias}; + use mun_hir::ModuleDef::{Const, Function, Module, PrimitiveType, Struct, TypeAlias}; let kind = match resolution { ScopeDef::ModuleDef(Module(_)) => CompletionItemKind::SymbolKind(SymbolKind::Module), @@ -65,6 +65,7 @@ impl<'a> Render<'a> { return render_fn(self.ctx, Some(local_name), *func) } ScopeDef::ModuleDef(PrimitiveType(_)) => CompletionItemKind::BuiltinType, + ScopeDef::ModuleDef(Const(_)) => CompletionItemKind::SymbolKind(SymbolKind::Const), ScopeDef::ModuleDef(Struct(_)) => CompletionItemKind::SymbolKind(SymbolKind::Struct), ScopeDef::ModuleDef(TypeAlias(_)) => { CompletionItemKind::SymbolKind(SymbolKind::TypeAlias) @@ -100,7 +101,10 @@ impl<'a> Render<'a> { ScopeDef::ImplSelfType(imp) => set_item_relevance(imp.self_ty(self.ctx.db())), ScopeDef::Unknown | ScopeDef::ModuleDef( - ModuleDef::Module(_) | ModuleDef::Function(_) | ModuleDef::TypeAlias(_), + ModuleDef::Module(_) + | ModuleDef::Function(_) + | ModuleDef::TypeAlias(_) + | ModuleDef::Const(_), ) => (), } diff --git a/crates/mun_language_server/src/symbol_kind.rs b/crates/mun_language_server/src/symbol_kind.rs index fde848d6..e9969268 100644 --- a/crates/mun_language_server/src/symbol_kind.rs +++ b/crates/mun_language_server/src/symbol_kind.rs @@ -1,6 +1,7 @@ /// Defines a set of symbols that can live in a document. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum SymbolKind { + Const, Field, Function, Method, diff --git a/crates/mun_language_server/src/to_lsp.rs b/crates/mun_language_server/src/to_lsp.rs index c4d5ff92..39a2e3c9 100644 --- a/crates/mun_language_server/src/to_lsp.rs +++ b/crates/mun_language_server/src/to_lsp.rs @@ -81,6 +81,7 @@ pub(crate) fn symbol_kind(symbol_kind: SymbolKind) -> lsp_types::SymbolKind { SymbolKind::Module => lsp_types::SymbolKind::MODULE, SymbolKind::Method => lsp_types::SymbolKind::METHOD, SymbolKind::Impl => lsp_types::SymbolKind::OBJECT, + SymbolKind::Const => lsp_types::SymbolKind::CONSTANT, } } @@ -160,6 +161,7 @@ pub(crate) fn completion_item_kind( SymbolKind::Struct | SymbolKind::TypeAlias => lsp_types::CompletionItemKind::STRUCT, SymbolKind::Method => lsp_types::CompletionItemKind::METHOD, SymbolKind::Impl => lsp_types::CompletionItemKind::TEXT, + SymbolKind::Const => lsp_types::CompletionItemKind::CONSTANT, }, CompletionItemKind::Attribute => lsp_types::CompletionItemKind::ENUM_MEMBER, } diff --git a/crates/mun_syntax/src/ast/generated.rs b/crates/mun_syntax/src/ast/generated.rs index cfc462fd..df88cee8 100644 --- a/crates/mun_syntax/src/ast/generated.rs +++ b/crates/mun_syntax/src/ast/generated.rs @@ -347,6 +347,32 @@ impl Condition { } } +// Const + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Const { + pub(crate) syntax: SyntaxNode, +} + +impl AstNode for Const { + fn can_cast(kind: SyntaxKind) -> bool { + matches!(kind, CONST) + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Const { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } +} +impl ast::NameOwner for Const {} +impl ast::VisibilityOwner for Const {} +impl Const {} + // Expr #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -859,7 +885,7 @@ impl AstNode for ModuleItem { fn can_cast(kind: SyntaxKind) -> bool { matches!( kind, - USE | FUNCTION_DEF | STRUCT_DEF | TYPE_ALIAS_DEF | IMPL + USE | FUNCTION_DEF | STRUCT_DEF | CONST | TYPE_ALIAS_DEF | IMPL ) } fn cast(syntax: SyntaxNode) -> Option { @@ -878,6 +904,7 @@ pub enum ModuleItemKind { Use(Use), FunctionDef(FunctionDef), StructDef(StructDef), + Const(Const), TypeAliasDef(TypeAliasDef), Impl(Impl), } @@ -896,6 +923,11 @@ impl From for ModuleItem { ModuleItem { syntax: n.syntax } } } +impl From for ModuleItem { + fn from(n: Const) -> ModuleItem { + ModuleItem { syntax: n.syntax } + } +} impl From for ModuleItem { fn from(n: TypeAliasDef) -> ModuleItem { ModuleItem { syntax: n.syntax } @@ -915,6 +947,7 @@ impl ModuleItem { ModuleItemKind::FunctionDef(FunctionDef::cast(self.syntax.clone()).unwrap()) } STRUCT_DEF => ModuleItemKind::StructDef(StructDef::cast(self.syntax.clone()).unwrap()), + CONST => ModuleItemKind::Const(Const::cast(self.syntax.clone()).unwrap()), TYPE_ALIAS_DEF => { ModuleItemKind::TypeAliasDef(TypeAliasDef::cast(self.syntax.clone()).unwrap()) } diff --git a/crates/mun_syntax/src/grammar.ron b/crates/mun_syntax/src/grammar.ron index 6baed487..8bbea838 100644 --- a/crates/mun_syntax/src/grammar.ron +++ b/crates/mun_syntax/src/grammar.ron @@ -94,6 +94,7 @@ Grammar( "never", "pub", "type", + "const", "package", "super", @@ -122,6 +123,7 @@ Grammar( nodes: [ "SOURCE_FILE", + "CONST", "FUNCTION_DEF", "EXTERN", "RET_TYPE", @@ -193,7 +195,7 @@ Grammar( traits: [ "ModuleItemOwner", "FunctionDefOwner" ], ), "ModuleItem": ( - enum: ["Use", "FunctionDef", "StructDef", "TypeAliasDef", "Impl"] + enum: ["Use", "FunctionDef", "StructDef", "Const", "TypeAliasDef", "Impl"] ), "Visibility": (), "FunctionDef": ( @@ -231,6 +233,13 @@ Grammar( "DocCommentsOwner", ] ), + "Const": ( + options: [], + traits: [ + "NameOwner", + "VisibilityOwner" + ] + ), "TypeAliasDef": ( options: ["TypeRef"], traits: [ diff --git a/crates/mun_syntax/src/lib.rs b/crates/mun_syntax/src/lib.rs index d30d6983..506033d3 100644 --- a/crates/mun_syntax/src/lib.rs +++ b/crates/mun_syntax/src/lib.rs @@ -215,7 +215,8 @@ fn api_walkthrough() { ast::ModuleItemKind::StructDef(_) | ast::ModuleItemKind::TypeAliasDef(_) | ast::ModuleItemKind::Use(_) - | ast::ModuleItemKind::Impl(_) => (), + | ast::ModuleItemKind::Impl(_) + | ast::ModuleItemKind::Const(_) => (), } } diff --git a/crates/mun_syntax/src/parsing/grammar.rs b/crates/mun_syntax/src/parsing/grammar.rs index 61d19133..a2c36d5e 100644 --- a/crates/mun_syntax/src/parsing/grammar.rs +++ b/crates/mun_syntax/src/parsing/grammar.rs @@ -12,7 +12,7 @@ use super::{ token_set::TokenSet, SyntaxKind::{ self, ARG_LIST, ARRAY_EXPR, ARRAY_TYPE, BIND_PAT, BIN_EXPR, BLOCK_EXPR, BREAK_EXPR, - CALL_EXPR, CONDITION, EOF, ERROR, EXPR_STMT, EXTERN, FIELD_EXPR, FLOAT_NUMBER, + CALL_EXPR, CONDITION, CONST, EOF, ERROR, EXPR_STMT, EXTERN, FIELD_EXPR, FLOAT_NUMBER, FUNCTION_DEF, GC_KW, IDENT, IF_EXPR, INDEX, INDEX_EXPR, INT_NUMBER, LET_STMT, LITERAL, LOOP_EXPR, MEMORY_TYPE_SPECIFIER, NAME, NAME_REF, NEVER_TYPE, PARAM, PARAM_LIST, PAREN_EXPR, PATH, PATH_EXPR, PATH_SEGMENT, PATH_TYPE, PLACEHOLDER_PAT, PREFIX_EXPR, diff --git a/crates/mun_syntax/src/parsing/grammar/declarations.rs b/crates/mun_syntax/src/parsing/grammar/declarations.rs index be7dd053..d941278c 100644 --- a/crates/mun_syntax/src/parsing/grammar/declarations.rs +++ b/crates/mun_syntax/src/parsing/grammar/declarations.rs @@ -1,12 +1,19 @@ use super::{ adt, error_block, expressions, name, name_recovery, opt_visibility, params, paths, traits, - types, Marker, Parser, TokenSet, EOF, ERROR, EXTERN, FUNCTION_DEF, RENAME, RET_TYPE, USE, - USE_TREE, USE_TREE_LIST, + types, Marker, Parser, TokenSet, CONST, EOF, ERROR, EXTERN, FUNCTION_DEF, RENAME, RET_TYPE, + USE, USE_TREE, USE_TREE_LIST, }; use crate::{parsing::grammar::paths::is_use_path_start, T}; -pub(super) const DECLARATION_RECOVERY_SET: TokenSet = - TokenSet::new(&[T![fn], T![pub], T![struct], T![use], T![;], T![impl]]); +pub(super) const DECLARATION_RECOVERY_SET: TokenSet = TokenSet::new(&[ + T![fn], + T![pub], + T![const], + T![struct], + T![use], + T![;], + T![impl], +]); pub(super) fn mod_contents(p: &mut Parser<'_>) { while !p.at(EOF) { @@ -64,6 +71,28 @@ fn abi(p: &mut Parser<'_>) { abi.complete(p, EXTERN); } +fn konst(p: &mut Parser<'_>, m: Marker) { + p.bump(T![const]); + + if !p.eat(T![_]) { + name(p); + } + + if p.at(T![:]) { + types::ascription(p); + } else { + p.error("missing type for `const`"); + } + + if p.eat(T![=]) { + expressions::expr(p); + } else { + p.error("free constant without body"); + } + + m.complete(p, CONST); +} + fn declarations_without_modifiers(p: &mut Parser<'_>, m: Marker) -> Result<(), Marker> { match p.current() { T![use] => { @@ -78,6 +107,9 @@ fn declarations_without_modifiers(p: &mut Parser<'_>, m: Marker) -> Result<(), M T![impl] => { traits::impl_(p, m); } + T![const] => { + konst(p, m); + } _ => return Err(m), }; Ok(()) diff --git a/crates/mun_syntax/src/syntax_kind/generated.rs b/crates/mun_syntax/src/syntax_kind/generated.rs index 169243de..b2e0fe7c 100644 --- a/crates/mun_syntax/src/syntax_kind/generated.rs +++ b/crates/mun_syntax/src/syntax_kind/generated.rs @@ -93,6 +93,7 @@ pub enum SyntaxKind { NEVER_KW, PUB_KW, TYPE_KW, + CONST_KW, PACKAGE_KW, SUPER_KW, SELF_KW, @@ -109,6 +110,7 @@ pub enum SyntaxKind { GC_KW, VALUE_KW, SOURCE_FILE, + CONST, FUNCTION_DEF, EXTERN, RET_TYPE, @@ -377,6 +379,9 @@ macro_rules! T { (type) => { $crate::SyntaxKind::TYPE_KW }; + (const) => { + $crate::SyntaxKind::CONST_KW + }; (package) => { $crate::SyntaxKind::PACKAGE_KW }; @@ -433,6 +438,7 @@ impl SyntaxKind { | NEVER_KW | PUB_KW | TYPE_KW + | CONST_KW | PACKAGE_KW | SUPER_KW | SELF_KW @@ -575,6 +581,7 @@ impl SyntaxKind { NEVER_KW => &SyntaxInfo { name: "NEVER_KW" }, PUB_KW => &SyntaxInfo { name: "PUB_KW" }, TYPE_KW => &SyntaxInfo { name: "TYPE_KW" }, + CONST_KW => &SyntaxInfo { name: "CONST_KW" }, PACKAGE_KW => &SyntaxInfo { name: "PACKAGE_KW" }, SUPER_KW => &SyntaxInfo { name: "SUPER_KW" }, SELF_KW => &SyntaxInfo { name: "SELF_KW" }, @@ -591,6 +598,7 @@ impl SyntaxKind { GC_KW => &SyntaxInfo { name: "GC_KW" }, VALUE_KW => &SyntaxInfo { name: "VALUE_KW" }, SOURCE_FILE => &SyntaxInfo { name: "SOURCE_FILE" }, + CONST => &SyntaxInfo { name: "CONST" }, FUNCTION_DEF => &SyntaxInfo { name: "FUNCTION_DEF" }, EXTERN => &SyntaxInfo { name: "EXTERN" }, RET_TYPE => &SyntaxInfo { name: "RET_TYPE" }, @@ -674,6 +682,7 @@ impl SyntaxKind { "never" => NEVER_KW, "pub" => PUB_KW, "type" => TYPE_KW, + "const" => CONST_KW, "package" => PACKAGE_KW, "super" => SUPER_KW, "self" => SELF_KW,