diff --git a/crates/libeditor/Cargo.toml b/crates/libeditor/Cargo.toml index fe688bc201..1d210f3c11 100644 --- a/crates/libeditor/Cargo.toml +++ b/crates/libeditor/Cargo.toml @@ -9,4 +9,5 @@ itertools = "0.7.8" superslice = "0.1.0" libsyntax2 = { path = "../libsyntax2" } +smol_str = { path = "../smol_str" } assert_eq_text = { path = "../assert_eq_text" } diff --git a/crates/libeditor/src/lib.rs b/crates/libeditor/src/lib.rs index 1e88f1471d..e5933cbd65 100644 --- a/crates/libeditor/src/lib.rs +++ b/crates/libeditor/src/lib.rs @@ -1,6 +1,7 @@ extern crate libsyntax2; extern crate superslice; extern crate itertools; +extern crate smol_str; mod extend_selection; mod symbols; diff --git a/crates/libeditor/src/symbols.rs b/crates/libeditor/src/symbols.rs index 5cd781c801..03f2313f71 100644 --- a/crates/libeditor/src/symbols.rs +++ b/crates/libeditor/src/symbols.rs @@ -1,3 +1,4 @@ +use smol_str::SmolStr; use libsyntax2::{ SyntaxKind, SyntaxNodeRef, SyntaxRoot, AstNode, ast::{self, NameOwner}, @@ -11,7 +12,7 @@ use TextRange; #[derive(Debug)] pub struct FileSymbol { pub parent: Option, - pub name: String, + pub name: SmolStr, pub name_range: TextRange, pub node_range: TextRange, pub kind: SyntaxKind, diff --git a/crates/libsyntax2/Cargo.toml b/crates/libsyntax2/Cargo.toml index 4c4040fe59..810952a0f4 100644 --- a/crates/libsyntax2/Cargo.toml +++ b/crates/libsyntax2/Cargo.toml @@ -10,6 +10,7 @@ text_unit = "0.1.2" itertools = "0.7.5" drop_bomb = "0.1.4" parking_lot = "0.6.0" +smol_str = { path = "../smol_str" } [dev-dependencies] assert_eq_text = { path = "../assert_eq_text" } diff --git a/crates/libsyntax2/src/ast/mod.rs b/crates/libsyntax2/src/ast/mod.rs index 56bc099fea..e9362d0487 100644 --- a/crates/libsyntax2/src/ast/mod.rs +++ b/crates/libsyntax2/src/ast/mod.rs @@ -1,6 +1,9 @@ mod generated; use std::sync::Arc; + +use smol_str::SmolStr; + use { SyntaxNode, SyntaxRoot, TreeRoot, SyntaxError, SyntaxKind::*, @@ -64,7 +67,9 @@ impl Function { } impl Name { - pub fn text(&self) -> String { - self.syntax().text() + pub fn text(&self) -> SmolStr { + let ident = self.syntax().first_child() + .unwrap(); + ident.leaf_text().unwrap() } } diff --git a/crates/libsyntax2/src/lib.rs b/crates/libsyntax2/src/lib.rs index ca33618a0a..feef542c4f 100644 --- a/crates/libsyntax2/src/lib.rs +++ b/crates/libsyntax2/src/lib.rs @@ -21,10 +21,11 @@ //#![warn(unreachable_pub)] // rust-lang/rust#47816 extern crate itertools; -extern crate text_unit; extern crate unicode_xid; extern crate drop_bomb; extern crate parking_lot; +extern crate smol_str; +extern crate text_unit; pub mod algo; pub mod ast; @@ -35,7 +36,6 @@ mod grammar; mod parser_impl; mod syntax_kinds; -mod smol_str; mod yellow; /// Utilities for simple uses of the parser. pub mod utils; diff --git a/crates/libsyntax2/src/yellow/green.rs b/crates/libsyntax2/src/yellow/green.rs index f505b26d7a..700f2704f8 100644 --- a/crates/libsyntax2/src/yellow/green.rs +++ b/crates/libsyntax2/src/yellow/green.rs @@ -1,8 +1,8 @@ use std::sync::Arc; -use { - SyntaxKind, TextUnit, - smol_str::SmolStr, -}; + +use smol_str::SmolStr; + +use {SyntaxKind, TextUnit}; #[derive(Clone, Debug)] pub(crate) enum GreenNode { @@ -31,7 +31,7 @@ impl GreenNode { pub fn text_len(&self) -> TextUnit { match self { - GreenNode::Leaf { text, ..} => TextUnit::of_str(text.as_str()), + GreenNode::Leaf { text, .. } => TextUnit::of_str(text.as_str()), GreenNode::Branch(b) => b.text_len(), } } @@ -54,6 +54,13 @@ impl GreenNode { } } } + + pub fn leaf_text(&self) -> Option { + match self { + GreenNode::Leaf { text, .. } => Some(text.clone()), + GreenNode::Branch(_) => None, + } + } } #[derive(Clone, Debug)] diff --git a/crates/libsyntax2/src/yellow/syntax.rs b/crates/libsyntax2/src/yellow/syntax.rs index 00f76e51ce..b264e008ae 100644 --- a/crates/libsyntax2/src/yellow/syntax.rs +++ b/crates/libsyntax2/src/yellow/syntax.rs @@ -1,5 +1,7 @@ use std::{fmt, sync::Arc}; +use smol_str::SmolStr; + use { yellow::{RedNode, TreeRoot, SyntaxRoot, RedPtr}, SyntaxKind::{self, *}, @@ -116,6 +118,10 @@ impl SyntaxNode { self.first_child().is_none() } + pub fn leaf_text(&self) -> Option { + self.red().green().leaf_text() + } + fn red(&self) -> &RedNode { unsafe { self.red.get(&self.root) } } diff --git a/crates/server/src/main_loop/handlers.rs b/crates/server/src/main_loop/handlers.rs index d4ae2a368d..14dcafc387 100644 --- a/crates/server/src/main_loop/handlers.rs +++ b/crates/server/src/main_loop/handlers.rs @@ -50,9 +50,10 @@ pub fn handle_document_symbol( let mut res: Vec = Vec::new(); for symbol in libeditor::file_symbols(&file) { + let name = symbol.name.to_string(); let doc_symbol = DocumentSymbol { - name: symbol.name.clone(), - detail: Some(symbol.name), + name: name.clone(), + detail: Some(name), kind: symbol.kind.conv(), deprecated: None, range: symbol.node_range.conv_with(&line_index), diff --git a/crates/smol_str/Cargo.toml b/crates/smol_str/Cargo.toml new file mode 100644 index 0000000000..83ca12f62f --- /dev/null +++ b/crates/smol_str/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "smol_str" +version = "0.1.0" +authors = ["Aleksey Kladov "] + +[dependencies] diff --git a/crates/libsyntax2/src/smol_str.rs b/crates/smol_str/src/lib.rs similarity index 65% rename from crates/libsyntax2/src/smol_str.rs rename to crates/smol_str/src/lib.rs index abf69dce74..4d5fef5932 100644 --- a/crates/libsyntax2/src/smol_str.rs +++ b/crates/smol_str/src/lib.rs @@ -1,10 +1,59 @@ -use std::{sync::Arc}; +use std::{sync::Arc, ops::Deref}; + +#[derive(Clone, Debug)] +pub struct SmolStr(Repr); + +impl SmolStr { + pub fn new(text: &str) -> SmolStr { + SmolStr(Repr::new(text)) + } + + pub fn as_str(&self) -> &str { + self.0.as_str() + } + + pub fn to_string(&self) -> String { + self.as_str().to_string() + } +} + +impl Deref for SmolStr { + type Target = str; + + fn deref(&self) -> &str { + self.as_str() + } +} + +impl PartialEq for SmolStr { + fn eq(&self, other: &str) -> bool { + self.as_str() == other + } +} + +impl PartialEq for str { + fn eq(&self, other: &SmolStr) -> bool { + other == self + } +} + +impl<'a> PartialEq<&'a str> for SmolStr { + fn eq(&self, other: &&'a str) -> bool { + self == *other + } +} + +impl<'a> PartialEq for &'a str { + fn eq(&self, other: &SmolStr) -> bool { + *self == other + } +} const INLINE_CAP: usize = 22; const WS_TAG: u8 = (INLINE_CAP + 1) as u8; #[derive(Clone, Debug)] -pub(crate) enum SmolStr { +enum Repr { Heap(Arc), Inline { len: u8, @@ -12,13 +61,13 @@ pub(crate) enum SmolStr { }, } -impl SmolStr { - pub fn new(text: &str) -> SmolStr { +impl Repr { + fn new(text: &str) -> Repr { let len = text.len(); if len <= INLINE_CAP { let mut buf = [0; INLINE_CAP]; buf[..len].copy_from_slice(text.as_bytes()); - return SmolStr::Inline { len: len as u8, buf }; + return Repr::Inline { len: len as u8, buf }; } let newlines = text.bytes().take_while(|&b| b == b'\n').count(); @@ -27,23 +76,23 @@ impl SmolStr { let mut buf = [0; INLINE_CAP]; buf[0] = newlines as u8; buf[1] = spaces as u8; - return SmolStr::Inline { len: WS_TAG, buf }; + return Repr::Inline { len: WS_TAG, buf }; } - SmolStr::Heap( + Repr::Heap( text.to_string().into_boxed_str().into() ) } - pub fn as_str(&self) -> &str { + fn as_str(&self) -> &str { match self { - SmolStr::Heap(data) => &*data, - SmolStr::Inline { len, buf } => { + Repr::Heap(data) => &*data, + Repr::Inline { len, buf } => { if *len == WS_TAG { let newlines = buf[0] as usize; let spaces = buf[1] as usize; assert!(newlines <= N_NEWLINES && spaces <= N_SPACES); - return &WS[N_NEWLINES - newlines..N_NEWLINES + spaces] + return &WS[N_NEWLINES - newlines..N_NEWLINES + spaces]; } let len = *len as usize;