From b7aa4898e0841ab8199643f89a0caa967b698ca8 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 13 Aug 2020 16:26:29 +0200 Subject: Rename ra_hir_expand -> hir_expand --- crates/hir_expand/src/name.rs | 230 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 crates/hir_expand/src/name.rs (limited to 'crates/hir_expand/src/name.rs') diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs new file mode 100644 index 000000000..49841c7a1 --- /dev/null +++ b/crates/hir_expand/src/name.rs @@ -0,0 +1,230 @@ +//! FIXME: write short doc here + +use std::fmt; + +use syntax::{ast, SmolStr}; + +/// `Name` is a wrapper around string, which is used in hir for both references +/// and declarations. In theory, names should also carry hygiene info, but we are +/// not there yet! +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct Name(Repr); + +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +enum Repr { + Text(SmolStr), + TupleField(usize), +} + +impl fmt::Display for Name { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match &self.0 { + Repr::Text(text) => fmt::Display::fmt(&text, f), + Repr::TupleField(idx) => fmt::Display::fmt(&idx, f), + } + } +} + +impl Name { + /// Note: this is private to make creating name from random string hard. + /// Hopefully, this should allow us to integrate hygiene cleaner in the + /// future, and to switch to interned representation of names. + const fn new_text(text: SmolStr) -> Name { + Name(Repr::Text(text)) + } + + pub fn new_tuple_field(idx: usize) -> Name { + Name(Repr::TupleField(idx)) + } + + pub fn new_lifetime(lt: &syntax::SyntaxToken) -> Name { + assert!(lt.kind() == syntax::SyntaxKind::LIFETIME); + Name(Repr::Text(lt.text().clone())) + } + + /// Shortcut to create inline plain text name + const fn new_inline_ascii(text: &[u8]) -> Name { + Name::new_text(SmolStr::new_inline_from_ascii(text.len(), text)) + } + + /// Resolve a name from the text of token. + fn resolve(raw_text: &SmolStr) -> Name { + let raw_start = "r#"; + if raw_text.as_str().starts_with(raw_start) { + Name::new_text(SmolStr::new(&raw_text[raw_start.len()..])) + } else { + Name::new_text(raw_text.clone()) + } + } + + pub fn missing() -> Name { + Name::new_text("[missing name]".into()) + } + + pub fn as_tuple_index(&self) -> Option { + match self.0 { + Repr::TupleField(idx) => Some(idx), + _ => None, + } + } +} + +pub trait AsName { + fn as_name(&self) -> Name; +} + +impl AsName for ast::NameRef { + fn as_name(&self) -> Name { + match self.as_tuple_field() { + Some(idx) => Name::new_tuple_field(idx), + None => Name::resolve(self.text()), + } + } +} + +impl AsName for ast::Name { + fn as_name(&self) -> Name { + Name::resolve(self.text()) + } +} + +impl AsName for ast::NameOrNameRef { + fn as_name(&self) -> Name { + match self { + ast::NameOrNameRef::Name(it) => it.as_name(), + ast::NameOrNameRef::NameRef(it) => it.as_name(), + } + } +} + +impl AsName for tt::Ident { + fn as_name(&self) -> Name { + Name::resolve(&self.text) + } +} + +impl AsName for ast::FieldKind { + fn as_name(&self) -> Name { + match self { + ast::FieldKind::Name(nr) => nr.as_name(), + ast::FieldKind::Index(idx) => { + let idx = idx.text().parse::().unwrap_or(0); + Name::new_tuple_field(idx) + } + } + } +} + +impl AsName for base_db::Dependency { + fn as_name(&self) -> Name { + Name::new_text(SmolStr::new(&*self.name)) + } +} + +pub mod known { + macro_rules! known_names { + ($($ident:ident),* $(,)?) => { + $( + #[allow(bad_style)] + pub const $ident: super::Name = + super::Name::new_inline_ascii(stringify!($ident).as_bytes()); + )* + }; + } + + known_names!( + // Primitives + isize, + i8, + i16, + i32, + i64, + i128, + usize, + u8, + u16, + u32, + u64, + u128, + f32, + f64, + bool, + char, + str, + // Special names + macro_rules, + doc, + // Components of known path (value or mod name) + std, + core, + alloc, + iter, + ops, + future, + result, + boxed, + // Components of known path (type name) + IntoIterator, + Item, + Try, + Ok, + Future, + Result, + Output, + Target, + Box, + RangeFrom, + RangeFull, + RangeInclusive, + RangeToInclusive, + RangeTo, + Range, + Neg, + Not, + Index, + // Builtin macros + file, + column, + compile_error, + line, + assert, + stringify, + concat, + include, + include_bytes, + include_str, + format_args, + format_args_nl, + env, + option_env, + // Builtin derives + Copy, + Clone, + Default, + Debug, + Hash, + Ord, + PartialOrd, + Eq, + PartialEq, + ); + + // self/Self cannot be used as an identifier + pub const SELF_PARAM: super::Name = super::Name::new_inline_ascii(b"self"); + pub const SELF_TYPE: super::Name = super::Name::new_inline_ascii(b"Self"); + + #[macro_export] + macro_rules! name { + (self) => { + $crate::name::known::SELF_PARAM + }; + (Self) => { + $crate::name::known::SELF_TYPE + }; + ($ident:ident) => { + $crate::name::known::$ident + }; + } +} + +pub use crate::name; -- cgit v1.2.3