aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_analysis/Cargo.toml1
-rw-r--r--crates/ra_analysis/src/db/imp.rs9
-rw-r--r--crates/ra_analysis/src/imp.rs7
-rw-r--r--crates/ra_analysis/src/lib.rs5
-rw-r--r--crates/ra_analysis/src/roots.rs6
-rw-r--r--crates/ra_analysis/tests/tests.rs5
-rw-r--r--crates/ra_editor/Cargo.toml1
-rw-r--r--crates/ra_editor/src/completion.rs8
-rw-r--r--crates/ra_editor/src/folding_ranges.rs6
-rw-r--r--crates/ra_editor/src/lib.rs19
-rw-r--r--crates/ra_editor/src/scope/fn_scope.rs14
-rw-r--r--crates/ra_editor/src/typing.rs195
-rw-r--r--crates/ra_lsp_server/Cargo.toml1
-rw-r--r--crates/ra_lsp_server/src/lib.rs1
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs4
-rw-r--r--crates/ra_lsp_server/src/main_loop/mod.rs12
-rw-r--r--crates/ra_lsp_server/src/main_loop/subscriptions.rs6
-rw-r--r--crates/ra_lsp_server/src/project_model.rs6
-rw-r--r--crates/ra_lsp_server/src/req.rs4
-rw-r--r--crates/ra_lsp_server/src/server_world.rs8
-rw-r--r--crates/ra_syntax/src/ast/generated.rs18
-rw-r--r--crates/ra_syntax/src/ast/mod.rs43
-rw-r--r--crates/ra_syntax/src/grammar.ron1
23 files changed, 258 insertions, 122 deletions
diff --git a/crates/ra_analysis/Cargo.toml b/crates/ra_analysis/Cargo.toml
index a30cdfc9c..a82e1761c 100644
--- a/crates/ra_analysis/Cargo.toml
+++ b/crates/ra_analysis/Cargo.toml
@@ -15,6 +15,7 @@ im = "12.0.0"
15ra_syntax = { path = "../ra_syntax" } 15ra_syntax = { path = "../ra_syntax" }
16ra_editor = { path = "../ra_editor" } 16ra_editor = { path = "../ra_editor" }
17salsa = { path = "../salsa" } 17salsa = { path = "../salsa" }
18rustc-hash = "1.0"
18 19
19[dev-dependencies] 20[dev-dependencies]
20test_utils = { path = "../test_utils" } 21test_utils = { path = "../test_utils" }
diff --git a/crates/ra_analysis/src/db/imp.rs b/crates/ra_analysis/src/db/imp.rs
index f26be1046..36f6cf290 100644
--- a/crates/ra_analysis/src/db/imp.rs
+++ b/crates/ra_analysis/src/db/imp.rs
@@ -2,9 +2,10 @@ use std::{
2 sync::Arc, 2 sync::Arc,
3 any::Any, 3 any::Any,
4 hash::{Hash, Hasher}, 4 hash::{Hash, Hasher},
5 collections::hash_map::{DefaultHasher, HashMap}, 5 collections::hash_map::{DefaultHasher},
6 iter, 6 iter,
7}; 7};
8use rustc_hash::FxHashMap;
8use salsa; 9use salsa;
9use {FileId, imp::FileResolverImp}; 10use {FileId, imp::FileResolverImp};
10use super::{State, Query, QueryCtx}; 11use super::{State, Query, QueryCtx};
@@ -13,7 +14,7 @@ pub(super) type Data = Arc<Any + Send + Sync + 'static>;
13 14
14#[derive(Debug)] 15#[derive(Debug)]
15pub(super) struct Db { 16pub(super) struct Db {
16 names: Arc<HashMap<salsa::QueryTypeId, &'static str>>, 17 names: Arc<FxHashMap<salsa::QueryTypeId, &'static str>>,
17 pub(super) imp: salsa::Db<State, Data>, 18 pub(super) imp: salsa::Db<State, Data>,
18} 19}
19 20
@@ -85,7 +86,7 @@ where
85 86
86pub(super) struct QueryRegistry { 87pub(super) struct QueryRegistry {
87 config: Option<salsa::QueryConfig<State, Data>>, 88 config: Option<salsa::QueryConfig<State, Data>>,
88 names: HashMap<salsa::QueryTypeId, &'static str>, 89 names: FxHashMap<salsa::QueryTypeId, &'static str>,
89} 90}
90 91
91impl QueryRegistry { 92impl QueryRegistry {
@@ -109,7 +110,7 @@ impl QueryRegistry {
109 (Arc::new(res), fingerprint) 110 (Arc::new(res), fingerprint)
110 }) 111 })
111 ); 112 );
112 let mut names = HashMap::new(); 113 let mut names = FxHashMap::default();
113 names.insert(FILE_TEXT, "FILE_TEXT"); 114 names.insert(FILE_TEXT, "FILE_TEXT");
114 names.insert(FILE_SET, "FILE_SET"); 115 names.insert(FILE_SET, "FILE_SET");
115 QueryRegistry { config: Some(config), names } 116 QueryRegistry { config: Some(config), names }
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs
index 517867e86..47bc0032b 100644
--- a/crates/ra_analysis/src/imp.rs
+++ b/crates/ra_analysis/src/imp.rs
@@ -4,11 +4,12 @@ use std::{
4 atomic::{AtomicBool, Ordering::SeqCst}, 4 atomic::{AtomicBool, Ordering::SeqCst},
5 }, 5 },
6 fmt, 6 fmt,
7 collections::{HashSet, VecDeque}, 7 collections::VecDeque,
8 iter, 8 iter,
9}; 9};
10 10
11use relative_path::RelativePath; 11use relative_path::RelativePath;
12use rustc_hash::FxHashSet;
12use ra_editor::{self, FileSymbol, LineIndex, find_node_at_offset, LocalEdit, resolve_local_name}; 13use ra_editor::{self, FileSymbol, LineIndex, find_node_at_offset, LocalEdit, resolve_local_name};
13use ra_syntax::{ 14use ra_syntax::{
14 TextUnit, TextRange, SmolStr, File, AstNode, 15 TextUnit, TextRange, SmolStr, File, AstNode,
@@ -84,7 +85,7 @@ impl AnalysisHostImpl {
84 data.root = Arc::new(data.root.apply_changes(&mut iter::empty(), Some(resolver))); 85 data.root = Arc::new(data.root.apply_changes(&mut iter::empty(), Some(resolver)));
85 } 86 }
86 pub fn set_crate_graph(&mut self, graph: CrateGraph) { 87 pub fn set_crate_graph(&mut self, graph: CrateGraph) {
87 let mut visited = HashSet::new(); 88 let mut visited = FxHashSet::default();
88 for &file_id in graph.crate_roots.values() { 89 for &file_id in graph.crate_roots.values() {
89 if !visited.insert(file_id) { 90 if !visited.insert(file_id) {
90 panic!("duplicate crate root: {:?}", file_id); 91 panic!("duplicate crate root: {:?}", file_id);
@@ -168,7 +169,7 @@ impl AnalysisImpl {
168 let mut res = Vec::new(); 169 let mut res = Vec::new();
169 let mut work = VecDeque::new(); 170 let mut work = VecDeque::new();
170 work.push_back(file_id); 171 work.push_back(file_id);
171 let mut visited = HashSet::new(); 172 let mut visited = FxHashSet::default();
172 while let Some(id) = work.pop_front() { 173 while let Some(id) = work.pop_front() {
173 if let Some(crate_id) = crate_graph.crate_id_for_crate_root(id) { 174 if let Some(crate_id) = crate_graph.crate_id_for_crate_root(id) {
174 res.push(crate_id); 175 res.push(crate_id);
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs
index f6ceb7eb2..849fd93e4 100644
--- a/crates/ra_analysis/src/lib.rs
+++ b/crates/ra_analysis/src/lib.rs
@@ -11,6 +11,7 @@ extern crate relative_path;
11extern crate crossbeam_channel; 11extern crate crossbeam_channel;
12extern crate im; 12extern crate im;
13extern crate salsa; 13extern crate salsa;
14extern crate rustc_hash;
14 15
15mod symbol_index; 16mod symbol_index;
16mod module_map; 17mod module_map;
@@ -23,13 +24,13 @@ mod descriptors;
23 24
24use std::{ 25use std::{
25 sync::Arc, 26 sync::Arc,
26 collections::HashMap,
27 fmt::Debug, 27 fmt::Debug,
28}; 28};
29 29
30use relative_path::{RelativePath, RelativePathBuf}; 30use relative_path::{RelativePath, RelativePathBuf};
31use ra_syntax::{File, TextRange, TextUnit, AtomEdit}; 31use ra_syntax::{File, TextRange, TextUnit, AtomEdit};
32use imp::{AnalysisImpl, AnalysisHostImpl, FileResolverImp}; 32use imp::{AnalysisImpl, AnalysisHostImpl, FileResolverImp};
33use rustc_hash::FxHashMap;
33 34
34pub use ra_editor::{ 35pub use ra_editor::{
35 StructureNode, LineIndex, FileSymbol, 36 StructureNode, LineIndex, FileSymbol,
@@ -46,7 +47,7 @@ pub struct CrateId(pub u32);
46 47
47#[derive(Debug, Clone, Default)] 48#[derive(Debug, Clone, Default)]
48pub struct CrateGraph { 49pub struct CrateGraph {
49 pub crate_roots: HashMap<CrateId, FileId>, 50 pub crate_roots: FxHashMap<CrateId, FileId>,
50} 51}
51 52
52pub trait FileResolver: Debug + Send + Sync + 'static { 53pub trait FileResolver: Debug + Send + Sync + 'static {
diff --git a/crates/ra_analysis/src/roots.rs b/crates/ra_analysis/src/roots.rs
index 1835a9b25..32a8c5bd0 100644
--- a/crates/ra_analysis/src/roots.rs
+++ b/crates/ra_analysis/src/roots.rs
@@ -1,11 +1,11 @@
1use std::{ 1use std::{
2 collections::HashMap,
3 sync::Arc, 2 sync::Arc,
4 panic, 3 panic,
5}; 4};
6 5
7use once_cell::sync::OnceCell; 6use once_cell::sync::OnceCell;
8use rayon::prelude::*; 7use rayon::prelude::*;
8use rustc_hash::FxHashMap;
9use ra_editor::LineIndex; 9use ra_editor::LineIndex;
10use ra_syntax::File; 10use ra_syntax::File;
11 11
@@ -118,7 +118,7 @@ impl FileData {
118#[derive(Debug)] 118#[derive(Debug)]
119pub(crate) struct ReadonlySourceRoot { 119pub(crate) struct ReadonlySourceRoot {
120 symbol_index: Arc<SymbolIndex>, 120 symbol_index: Arc<SymbolIndex>,
121 file_map: HashMap<FileId, FileData>, 121 file_map: FxHashMap<FileId, FileData>,
122 module_tree: Arc<ModuleTreeDescriptor>, 122 module_tree: Arc<ModuleTreeDescriptor>,
123} 123}
124 124
@@ -139,7 +139,7 @@ impl ReadonlySourceRoot {
139 let symbol_index = SymbolIndex::for_files( 139 let symbol_index = SymbolIndex::for_files(
140 modules.par_iter().map(|it| (it.0, it.1.clone())) 140 modules.par_iter().map(|it| (it.0, it.1.clone()))
141 ); 141 );
142 let file_map: HashMap<FileId, FileData> = files 142 let file_map: FxHashMap<FileId, FileData> = files
143 .into_iter() 143 .into_iter()
144 .map(|(id, text)| (id, FileData::new(text))) 144 .map(|(id, text)| (id, FileData::new(text)))
145 .collect(); 145 .collect();
diff --git a/crates/ra_analysis/tests/tests.rs b/crates/ra_analysis/tests/tests.rs
index 334dc5e48..a886cd0ff 100644
--- a/crates/ra_analysis/tests/tests.rs
+++ b/crates/ra_analysis/tests/tests.rs
@@ -1,12 +1,13 @@
1extern crate relative_path; 1extern crate relative_path;
2extern crate ra_analysis; 2extern crate ra_analysis;
3extern crate rustc_hash;
3extern crate test_utils; 4extern crate test_utils;
4 5
5use std::{ 6use std::{
6 sync::Arc, 7 sync::Arc,
7 collections::HashMap,
8}; 8};
9 9
10use rustc_hash::FxHashMap;
10use relative_path::{RelativePath, RelativePathBuf}; 11use relative_path::{RelativePath, RelativePathBuf};
11use ra_analysis::{Analysis, AnalysisHost, FileId, FileResolver, JobHandle, CrateGraph, CrateId}; 12use ra_analysis::{Analysis, AnalysisHost, FileId, FileResolver, JobHandle, CrateGraph, CrateId};
12use test_utils::assert_eq_dbg; 13use test_utils::assert_eq_dbg;
@@ -131,7 +132,7 @@ fn test_resolve_crate_root() {
131 132
132 let crate_graph = CrateGraph { 133 let crate_graph = CrateGraph {
133 crate_roots: { 134 crate_roots: {
134 let mut m = HashMap::new(); 135 let mut m = FxHashMap::default();
135 m.insert(CrateId(1), FileId(1)); 136 m.insert(CrateId(1), FileId(1));
136 m 137 m
137 }, 138 },
diff --git a/crates/ra_editor/Cargo.toml b/crates/ra_editor/Cargo.toml
index 40e3254ff..91cefc8d7 100644
--- a/crates/ra_editor/Cargo.toml
+++ b/crates/ra_editor/Cargo.toml
@@ -8,6 +8,7 @@ publish = false
8itertools = "0.7.8" 8itertools = "0.7.8"
9superslice = "0.1.0" 9superslice = "0.1.0"
10join_to_string = "0.1.1" 10join_to_string = "0.1.1"
11rustc-hash = "1.0"
11 12
12ra_syntax = { path = "../ra_syntax" } 13ra_syntax = { path = "../ra_syntax" }
13 14
diff --git a/crates/ra_editor/src/completion.rs b/crates/ra_editor/src/completion.rs
index 570d72d66..20b8484b3 100644
--- a/crates/ra_editor/src/completion.rs
+++ b/crates/ra_editor/src/completion.rs
@@ -1,4 +1,4 @@
1use std::collections::{HashSet, HashMap}; 1use rustc_hash::{FxHashMap, FxHashSet};
2 2
3use ra_syntax::{ 3use ra_syntax::{
4 File, TextUnit, AstNode, SyntaxNodeRef, SyntaxKind::*, 4 File, TextUnit, AstNode, SyntaxNodeRef, SyntaxKind::*,
@@ -96,7 +96,7 @@ fn complete_name_ref(file: &File, name_ref: ast::NameRef, acc: &mut Vec<Completi
96} 96}
97 97
98fn param_completions(ctx: SyntaxNodeRef, acc: &mut Vec<CompletionItem>) { 98fn param_completions(ctx: SyntaxNodeRef, acc: &mut Vec<CompletionItem>) {
99 let mut params = HashMap::new(); 99 let mut params = FxHashMap::default();
100 for node in ctx.ancestors() { 100 for node in ctx.ancestors() {
101 let _ = visitor_ctx(&mut params) 101 let _ = visitor_ctx(&mut params)
102 .visit::<ast::Root, _>(process) 102 .visit::<ast::Root, _>(process)
@@ -114,7 +114,7 @@ fn param_completions(ctx: SyntaxNodeRef, acc: &mut Vec<CompletionItem>) {
114 }) 114 })
115 }); 115 });
116 116
117 fn process<'a, N: ast::FnDefOwner<'a>>(node: N, params: &mut HashMap<String, (u32, ast::Param<'a>)>) { 117 fn process<'a, N: ast::FnDefOwner<'a>>(node: N, params: &mut FxHashMap<String, (u32, ast::Param<'a>)>) {
118 node.functions() 118 node.functions()
119 .filter_map(|it| it.param_list()) 119 .filter_map(|it| it.param_list())
120 .flat_map(|it| it.params()) 120 .flat_map(|it| it.params())
@@ -232,7 +232,7 @@ fn complete_mod_item_snippets(acc: &mut Vec<CompletionItem>) {
232} 232}
233 233
234fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<CompletionItem>) { 234fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<CompletionItem>) {
235 let mut shadowed = HashSet::new(); 235 let mut shadowed = FxHashSet::default();
236 acc.extend( 236 acc.extend(
237 scopes.scope_chain(name_ref.syntax()) 237 scopes.scope_chain(name_ref.syntax())
238 .flat_map(|scope| scopes.entries(scope).iter()) 238 .flat_map(|scope| scopes.entries(scope).iter())
diff --git a/crates/ra_editor/src/folding_ranges.rs b/crates/ra_editor/src/folding_ranges.rs
index 733512368..3aabd54ae 100644
--- a/crates/ra_editor/src/folding_ranges.rs
+++ b/crates/ra_editor/src/folding_ranges.rs
@@ -1,4 +1,4 @@
1use std::collections::HashSet; 1use rustc_hash::FxHashSet;
2 2
3use ra_syntax::{ 3use ra_syntax::{
4 File, TextRange, SyntaxNodeRef, 4 File, TextRange, SyntaxNodeRef,
@@ -20,7 +20,7 @@ pub struct Fold {
20 20
21pub fn folding_ranges(file: &File) -> Vec<Fold> { 21pub fn folding_ranges(file: &File) -> Vec<Fold> {
22 let mut res = vec![]; 22 let mut res = vec![];
23 let mut visited = HashSet::new(); 23 let mut visited = FxHashSet::default();
24 24
25 for node in file.syntax().descendants() { 25 for node in file.syntax().descendants() {
26 if visited.contains(&node) { 26 if visited.contains(&node) {
@@ -56,7 +56,7 @@ pub fn folding_ranges(file: &File) -> Vec<Fold> {
56fn contiguous_range_for<'a>( 56fn contiguous_range_for<'a>(
57 kind: SyntaxKind, 57 kind: SyntaxKind,
58 node: SyntaxNodeRef<'a>, 58 node: SyntaxNodeRef<'a>,
59 visited: &mut HashSet<SyntaxNodeRef<'a>>, 59 visited: &mut FxHashSet<SyntaxNodeRef<'a>>,
60) -> Option<TextRange> { 60) -> Option<TextRange> {
61 visited.insert(node); 61 visited.insert(node);
62 62
diff --git a/crates/ra_editor/src/lib.rs b/crates/ra_editor/src/lib.rs
index fe0045378..710afc65d 100644
--- a/crates/ra_editor/src/lib.rs
+++ b/crates/ra_editor/src/lib.rs
@@ -2,6 +2,7 @@ extern crate ra_syntax;
2extern crate superslice; 2extern crate superslice;
3extern crate itertools; 3extern crate itertools;
4extern crate join_to_string; 4extern crate join_to_string;
5extern crate rustc_hash;
5#[cfg(test)] 6#[cfg(test)]
6#[macro_use] 7#[macro_use]
7extern crate test_utils as _test_utils; 8extern crate test_utils as _test_utils;
@@ -88,7 +89,6 @@ pub fn highlight(file: &File) -> Vec<HighlightedRange> {
88 let mut res = Vec::new(); 89 let mut res = Vec::new();
89 for node in file.syntax().descendants() { 90 for node in file.syntax().descendants() {
90 let tag = match node.kind() { 91 let tag = match node.kind() {
91 ERROR => "error",
92 COMMENT | DOC_COMMENT => "comment", 92 COMMENT | DOC_COMMENT => "comment",
93 STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => "string", 93 STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => "string",
94 ATTR => "attribute", 94 ATTR => "attribute",
@@ -108,21 +108,10 @@ pub fn highlight(file: &File) -> Vec<HighlightedRange> {
108} 108}
109 109
110pub fn diagnostics(file: &File) -> Vec<Diagnostic> { 110pub fn diagnostics(file: &File) -> Vec<Diagnostic> {
111 let mut res = Vec::new(); 111 file.errors().into_iter().map(|err| Diagnostic {
112
113 for node in file.syntax().descendants() {
114 if node.kind() == ERROR {
115 res.push(Diagnostic {
116 range: node.range(),
117 msg: "Syntax Error".to_string(),
118 });
119 }
120 }
121 res.extend(file.errors().into_iter().map(|err| Diagnostic {
122 range: TextRange::offset_len(err.offset, 1.into()), 112 range: TextRange::offset_len(err.offset, 1.into()),
123 msg: err.msg, 113 msg: "Syntax Error: ".to_string() + &err.msg,
124 })); 114 }).collect()
125 res
126} 115}
127 116
128pub fn syntax_tree(file: &File) -> String { 117pub fn syntax_tree(file: &File) -> String {
diff --git a/crates/ra_editor/src/scope/fn_scope.rs b/crates/ra_editor/src/scope/fn_scope.rs
index 65d85279f..9a48bda02 100644
--- a/crates/ra_editor/src/scope/fn_scope.rs
+++ b/crates/ra_editor/src/scope/fn_scope.rs
@@ -1,7 +1,5 @@
1use std::{ 1use std::fmt;
2 fmt, 2use rustc_hash::FxHashMap;
3 collections::HashMap,
4};
5 3
6use ra_syntax::{ 4use ra_syntax::{
7 SyntaxNodeRef, SyntaxNode, SmolStr, AstNode, 5 SyntaxNodeRef, SyntaxNode, SmolStr, AstNode,
@@ -15,7 +13,7 @@ type ScopeId = usize;
15pub struct FnScopes { 13pub struct FnScopes {
16 pub self_param: Option<SyntaxNode>, 14 pub self_param: Option<SyntaxNode>,
17 scopes: Vec<ScopeData>, 15 scopes: Vec<ScopeData>,
18 scope_for: HashMap<SyntaxNode, ScopeId>, 16 scope_for: FxHashMap<SyntaxNode, ScopeId>,
19} 17}
20 18
21impl FnScopes { 19impl FnScopes {
@@ -25,7 +23,7 @@ impl FnScopes {
25 .and_then(|it| it.self_param()) 23 .and_then(|it| it.self_param())
26 .map(|it| it.syntax().owned()), 24 .map(|it| it.syntax().owned()),
27 scopes: Vec::new(), 25 scopes: Vec::new(),
28 scope_for: HashMap::new() 26 scope_for: FxHashMap::default()
29 }; 27 };
30 let root = scopes.root_scope(); 28 let root = scopes.root_scope();
31 scopes.add_params_bindings(root, fn_def.param_list()); 29 scopes.add_params_bindings(root, fn_def.param_list());
@@ -242,9 +240,9 @@ struct ScopeData {
242} 240}
243 241
244pub fn resolve_local_name<'a>(name_ref: ast::NameRef, scopes: &'a FnScopes) -> Option<&'a ScopeEntry> { 242pub fn resolve_local_name<'a>(name_ref: ast::NameRef, scopes: &'a FnScopes) -> Option<&'a ScopeEntry> {
245 use std::collections::HashSet; 243 use rustc_hash::FxHashSet;
246 244
247 let mut shadowed = HashSet::new(); 245 let mut shadowed = FxHashSet::default();
248 let ret = scopes.scope_chain(name_ref.syntax()) 246 let ret = scopes.scope_chain(name_ref.syntax())
249 .flat_map(|scope| scopes.entries(scope).iter()) 247 .flat_map(|scope| scopes.entries(scope).iter())
250 .filter(|entry| shadowed.insert(entry.name())) 248 .filter(|entry| shadowed.insert(entry.name()))
diff --git a/crates/ra_editor/src/typing.rs b/crates/ra_editor/src/typing.rs
index 3384389d1..1dc658f9b 100644
--- a/crates/ra_editor/src/typing.rs
+++ b/crates/ra_editor/src/typing.rs
@@ -30,6 +30,7 @@ pub fn join_lines(file: &File, range: TextRange) -> LocalEdit {
30 } else { 30 } else {
31 range 31 range
32 }; 32 };
33
33 let node = find_covering_node(file.syntax(), range); 34 let node = find_covering_node(file.syntax(), range);
34 let mut edit = EditBuilder::new(); 35 let mut edit = EditBuilder::new();
35 for node in node.descendants() { 36 for node in node.descendants() {
@@ -57,14 +58,19 @@ pub fn join_lines(file: &File, range: TextRange) -> LocalEdit {
57} 58}
58 59
59pub fn on_enter(file: &File, offset: TextUnit) -> Option<LocalEdit> { 60pub fn on_enter(file: &File, offset: TextUnit) -> Option<LocalEdit> {
60 let comment = find_leaf_at_offset(file.syntax(), offset).left_biased().filter(|it| it.kind() == COMMENT)?; 61 let comment = find_leaf_at_offset(file.syntax(), offset).left_biased().and_then(|it| ast::Comment::cast(it))?;
61 let prefix = comment_preffix(comment)?; 62
62 if offset < comment.range().start() + TextUnit::of_str(prefix) { 63 if let ast::CommentFlavor::Multiline = comment.flavor() {
64 return None;
65 }
66
67 let prefix = comment.prefix();
68 if offset < comment.syntax().range().start() + TextUnit::of_str(prefix) + TextUnit::from(1) {
63 return None; 69 return None;
64 } 70 }
65 71
66 let indent = node_indent(file, comment)?; 72 let indent = node_indent(file, comment.syntax())?;
67 let inserted = format!("\n{}{}", indent, prefix); 73 let inserted = format!("\n{}{} ", indent, prefix);
68 let cursor_position = offset + TextUnit::of_str(&inserted); 74 let cursor_position = offset + TextUnit::of_str(&inserted);
69 let mut edit = EditBuilder::new(); 75 let mut edit = EditBuilder::new();
70 edit.insert(offset, inserted); 76 edit.insert(offset, inserted);
@@ -74,20 +80,6 @@ pub fn on_enter(file: &File, offset: TextUnit) -> Option<LocalEdit> {
74 }) 80 })
75} 81}
76 82
77fn comment_preffix(comment: SyntaxNodeRef) -> Option<&'static str> {
78 let text = comment.leaf_text().unwrap();
79 let res = if text.starts_with("///") {
80 "/// "
81 } else if text.starts_with("//!") {
82 "//! "
83 } else if text.starts_with("//") {
84 "// "
85 } else {
86 return None;
87 };
88 Some(res)
89}
90
91fn node_indent<'a>(file: &'a File, node: SyntaxNodeRef) -> Option<&'a str> { 83fn node_indent<'a>(file: &'a File, node: SyntaxNodeRef) -> Option<&'a str> {
92 let ws = match find_leaf_at_offset(file.syntax(), node.range().start()) { 84 let ws = match find_leaf_at_offset(file.syntax(), node.range().start()) {
93 LeafAtOffset::Between(l, r) => { 85 LeafAtOffset::Between(l, r) => {
@@ -139,41 +131,60 @@ fn remove_newline(
139 node_text: &str, 131 node_text: &str,
140 offset: TextUnit, 132 offset: TextUnit,
141) { 133) {
142 if node.kind() == WHITESPACE && node_text.bytes().filter(|&b| b == b'\n').count() == 1 { 134 if node.kind() != WHITESPACE || node_text.bytes().filter(|&b| b == b'\n').count() != 1 {
143 if join_single_expr_block(edit, node).is_some() { 135 // The node is either the first or the last in the file
144 return 136 let suff = &node_text[TextRange::from_to(
145 } 137 offset - node.range().start() + TextUnit::of_char('\n'),
146 match (node.prev_sibling(), node.next_sibling()) { 138 TextUnit::of_str(node_text),
147 (Some(prev), Some(next)) => { 139 )];
148 let range = TextRange::from_to(prev.range().start(), node.range().end()); 140 let spaces = suff.bytes().take_while(|&b| b == b' ').count();
149 if is_trailing_comma(prev.kind(), next.kind()) { 141
150 edit.delete(range); 142 edit.replace(
151 } else if no_space_required(prev.kind(), next.kind()) { 143 TextRange::offset_len(offset, ((spaces + 1) as u32).into()),
152 edit.delete(node.range()); 144 " ".to_string(),
153 } else if prev.kind() == COMMA && next.kind() == R_CURLY { 145 );
154 edit.replace(range, " ".to_string()); 146 return;
155 } else {
156 edit.replace(
157 node.range(),
158 compute_ws(prev, next).to_string(),
159 );
160 }
161 return;
162 }
163 _ => (),
164 }
165 } 147 }
166 148
167 let suff = &node_text[TextRange::from_to( 149 // Special case that turns something like:
168 offset - node.range().start() + TextUnit::of_char('\n'), 150 //
169 TextUnit::of_str(node_text), 151 // ```
170 )]; 152 // my_function({<|>
171 let spaces = suff.bytes().take_while(|&b| b == b' ').count(); 153 // <some-expr>
154 // })
155 // ```
156 //
157 // into `my_function(<some-expr>)`
158 if join_single_expr_block(edit, node).is_some() {
159 return
160 }
172 161
173 edit.replace( 162 // The node is between two other nodes
174 TextRange::offset_len(offset, ((spaces + 1) as u32).into()), 163 let prev = node.prev_sibling().unwrap();
175 " ".to_string(), 164 let next = node.next_sibling().unwrap();
176 ); 165 if is_trailing_comma(prev.kind(), next.kind()) {
166 // Removes: trailing comma, newline (incl. surrounding whitespace)
167 edit.delete(TextRange::from_to(prev.range().start(), node.range().end()));
168 } else if prev.kind() == COMMA && next.kind() == R_CURLY {
169 // Removes: comma, newline (incl. surrounding whitespace)
170 // Adds: a single whitespace
171 edit.replace(
172 TextRange::from_to(prev.range().start(), node.range().end()),
173 " ".to_string()
174 );
175 } else if let (Some(_), Some(next)) = (ast::Comment::cast(prev), ast::Comment::cast(next)) {
176 // Removes: newline (incl. surrounding whitespace), start of the next comment
177 edit.delete(TextRange::from_to(
178 node.range().start(),
179 next.syntax().range().start() + TextUnit::of_str(next.prefix())
180 ));
181 } else {
182 // Remove newline but add a computed amount of whitespace characters
183 edit.replace(
184 node.range(),
185 compute_ws(prev, next).to_string(),
186 );
187 }
177} 188}
178 189
179fn is_trailing_comma(left: SyntaxKind, right: SyntaxKind) -> bool { 190fn is_trailing_comma(left: SyntaxKind, right: SyntaxKind) -> bool {
@@ -183,13 +194,6 @@ fn is_trailing_comma(left: SyntaxKind, right: SyntaxKind) -> bool {
183 } 194 }
184} 195}
185 196
186fn no_space_required(left: SyntaxKind, right: SyntaxKind) -> bool {
187 match (left, right) {
188 (_, DOT) => true,
189 _ => false
190 }
191}
192
193fn join_single_expr_block( 197fn join_single_expr_block(
194 edit: &mut EditBuilder, 198 edit: &mut EditBuilder,
195 node: SyntaxNodeRef, 199 node: SyntaxNodeRef,
@@ -231,6 +235,7 @@ fn compute_ws(left: SyntaxNodeRef, right: SyntaxNodeRef) -> &'static str {
231 } 235 }
232 match right.kind() { 236 match right.kind() {
233 R_PAREN | R_BRACK => return "", 237 R_PAREN | R_BRACK => return "",
238 DOT => return "",
234 _ => (), 239 _ => (),
235 } 240 }
236 " " 241 " "
@@ -291,6 +296,80 @@ fn foo() {
291}"); 296}");
292 } 297 }
293 298
299 #[test]
300 fn test_join_lines_normal_comments() {
301 check_join_lines(r"
302fn foo() {
303 // Hello<|>
304 // world!
305}
306", r"
307fn foo() {
308 // Hello<|> world!
309}
310");
311 }
312
313 #[test]
314 fn test_join_lines_doc_comments() {
315 check_join_lines(r"
316fn foo() {
317 /// Hello<|>
318 /// world!
319}
320", r"
321fn foo() {
322 /// Hello<|> world!
323}
324");
325 }
326
327 #[test]
328 fn test_join_lines_mod_comments() {
329 check_join_lines(r"
330fn foo() {
331 //! Hello<|>
332 //! world!
333}
334", r"
335fn foo() {
336 //! Hello<|> world!
337}
338");
339 }
340
341 #[test]
342 fn test_join_lines_multiline_comments_1() {
343 check_join_lines(r"
344fn foo() {
345 // Hello<|>
346 /* world! */
347}
348", r"
349fn foo() {
350 // Hello<|> world! */
351}
352");
353 }
354
355 #[test]
356 fn test_join_lines_multiline_comments_2() {
357 check_join_lines(r"
358fn foo() {
359 // The<|>
360 /* quick
361 brown
362 fox! */
363}
364", r"
365fn foo() {
366 // The<|> quick
367 brown
368 fox! */
369}
370");
371 }
372
294 fn check_join_lines_sel(before: &str, after: &str) { 373 fn check_join_lines_sel(before: &str, after: &str) {
295 let (sel, before) = extract_range(before); 374 let (sel, before) = extract_range(before);
296 let file = File::parse(&before); 375 let file = File::parse(&before);
diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml
index 32463e499..1fe6b2ebe 100644
--- a/crates/ra_lsp_server/Cargo.toml
+++ b/crates/ra_lsp_server/Cargo.toml
@@ -21,6 +21,7 @@ im = "12.0.0"
21cargo_metadata = "0.6.0" 21cargo_metadata = "0.6.0"
22text_unit = { version = "0.1.2", features = ["serde"] } 22text_unit = { version = "0.1.2", features = ["serde"] }
23smol_str = { version = "0.1.5", features = ["serde"] } 23smol_str = { version = "0.1.5", features = ["serde"] }
24rustc-hash = "1.0"
24 25
25ra_syntax = { path = "../ra_syntax" } 26ra_syntax = { path = "../ra_syntax" }
26ra_editor = { path = "../ra_editor" } 27ra_editor = { path = "../ra_editor" }
diff --git a/crates/ra_lsp_server/src/lib.rs b/crates/ra_lsp_server/src/lib.rs
index d2f76972f..60652d55e 100644
--- a/crates/ra_lsp_server/src/lib.rs
+++ b/crates/ra_lsp_server/src/lib.rs
@@ -16,6 +16,7 @@ extern crate walkdir;
16extern crate im; 16extern crate im;
17extern crate relative_path; 17extern crate relative_path;
18extern crate cargo_metadata; 18extern crate cargo_metadata;
19extern crate rustc_hash;
19 20
20extern crate gen_lsp_server; 21extern crate gen_lsp_server;
21extern crate ra_editor; 22extern crate ra_editor;
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index 725036cc7..ab8be15e9 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -1,4 +1,4 @@
1use std::collections::{HashMap}; 1use rustc_hash::FxHashMap;
2 2
3use languageserver_types::{ 3use languageserver_types::{
4 Diagnostic, DiagnosticSeverity, DocumentSymbol, 4 Diagnostic, DiagnosticSeverity, DocumentSymbol,
@@ -267,7 +267,7 @@ pub fn handle_runnables(
267 bin: "cargo".to_string(), 267 bin: "cargo".to_string(),
268 args, 268 args,
269 env: { 269 env: {
270 let mut m = HashMap::new(); 270 let mut m = FxHashMap::default();
271 m.insert( 271 m.insert(
272 "RUST_BACKTRACE".to_string(), 272 "RUST_BACKTRACE".to_string(),
273 "short".to_string(), 273 "short".to_string(),
diff --git a/crates/ra_lsp_server/src/main_loop/mod.rs b/crates/ra_lsp_server/src/main_loop/mod.rs
index 53c6f1dff..402615e42 100644
--- a/crates/ra_lsp_server/src/main_loop/mod.rs
+++ b/crates/ra_lsp_server/src/main_loop/mod.rs
@@ -3,7 +3,6 @@ mod subscriptions;
3 3
4use std::{ 4use std::{
5 path::PathBuf, 5 path::PathBuf,
6 collections::{HashMap},
7}; 6};
8 7
9use serde::{Serialize, de::DeserializeOwned}; 8use serde::{Serialize, de::DeserializeOwned};
@@ -15,6 +14,7 @@ use gen_lsp_server::{
15 RawRequest, RawNotification, RawMessage, RawResponse, ErrorCode, 14 RawRequest, RawNotification, RawMessage, RawResponse, ErrorCode,
16 handle_shutdown, 15 handle_shutdown,
17}; 16};
17use rustc_hash::FxHashMap;
18 18
19use { 19use {
20 req, 20 req,
@@ -50,7 +50,7 @@ pub fn main_loop(
50 info!("server initialized, serving requests"); 50 info!("server initialized, serving requests");
51 let mut state = ServerWorldState::new(); 51 let mut state = ServerWorldState::new();
52 52
53 let mut pending_requests = HashMap::new(); 53 let mut pending_requests = FxHashMap::default();
54 let mut subs = Subscriptions::new(); 54 let mut subs = Subscriptions::new();
55 let main_res = main_loop_inner( 55 let main_res = main_loop_inner(
56 internal_mode, 56 internal_mode,
@@ -95,7 +95,7 @@ fn main_loop_inner(
95 fs_worker: Worker<PathBuf, (PathBuf, Vec<FileEvent>)>, 95 fs_worker: Worker<PathBuf, (PathBuf, Vec<FileEvent>)>,
96 ws_worker: Worker<PathBuf, Result<CargoWorkspace>>, 96 ws_worker: Worker<PathBuf, Result<CargoWorkspace>>,
97 state: &mut ServerWorldState, 97 state: &mut ServerWorldState,
98 pending_requests: &mut HashMap<u64, JobHandle>, 98 pending_requests: &mut FxHashMap<u64, JobHandle>,
99 subs: &mut Subscriptions, 99 subs: &mut Subscriptions,
100) -> Result<()> { 100) -> Result<()> {
101 let (libdata_sender, libdata_receiver) = unbounded(); 101 let (libdata_sender, libdata_receiver) = unbounded();
@@ -213,7 +213,7 @@ fn main_loop_inner(
213fn on_task( 213fn on_task(
214 task: Task, 214 task: Task,
215 msg_sender: &Sender<RawMessage>, 215 msg_sender: &Sender<RawMessage>,
216 pending_requests: &mut HashMap<u64, JobHandle>, 216 pending_requests: &mut FxHashMap<u64, JobHandle>,
217) { 217) {
218 match task { 218 match task {
219 Task::Respond(response) => { 219 Task::Respond(response) => {
@@ -229,7 +229,7 @@ fn on_task(
229 229
230fn on_request( 230fn on_request(
231 world: &mut ServerWorldState, 231 world: &mut ServerWorldState,
232 pending_requests: &mut HashMap<u64, JobHandle>, 232 pending_requests: &mut FxHashMap<u64, JobHandle>,
233 pool: &ThreadPool, 233 pool: &ThreadPool,
234 sender: &Sender<Task>, 234 sender: &Sender<Task>,
235 req: RawRequest, 235 req: RawRequest,
@@ -269,7 +269,7 @@ fn on_request(
269fn on_notification( 269fn on_notification(
270 msg_sender: &Sender<RawMessage>, 270 msg_sender: &Sender<RawMessage>,
271 state: &mut ServerWorldState, 271 state: &mut ServerWorldState,
272 pending_requests: &mut HashMap<u64, JobHandle>, 272 pending_requests: &mut FxHashMap<u64, JobHandle>,
273 subs: &mut Subscriptions, 273 subs: &mut Subscriptions,
274 not: RawNotification, 274 not: RawNotification,
275) -> Result<()> { 275) -> Result<()> {
diff --git a/crates/ra_lsp_server/src/main_loop/subscriptions.rs b/crates/ra_lsp_server/src/main_loop/subscriptions.rs
index 27f92cc9a..310153382 100644
--- a/crates/ra_lsp_server/src/main_loop/subscriptions.rs
+++ b/crates/ra_lsp_server/src/main_loop/subscriptions.rs
@@ -1,13 +1,13 @@
1use std::collections::HashSet; 1use rustc_hash::FxHashSet;
2use ra_analysis::FileId; 2use ra_analysis::FileId;
3 3
4pub struct Subscriptions { 4pub struct Subscriptions {
5 subs: HashSet<FileId>, 5 subs: FxHashSet<FileId>,
6} 6}
7 7
8impl Subscriptions { 8impl Subscriptions {
9 pub fn new() -> Subscriptions { 9 pub fn new() -> Subscriptions {
10 Subscriptions { subs: HashSet::new() } 10 Subscriptions { subs: FxHashSet::default() }
11 } 11 }
12 pub fn add_sub(&mut self, file_id: FileId) { 12 pub fn add_sub(&mut self, file_id: FileId) {
13 self.subs.insert(file_id); 13 self.subs.insert(file_id);
diff --git a/crates/ra_lsp_server/src/project_model.rs b/crates/ra_lsp_server/src/project_model.rs
index 5db34e3e5..43e4fd654 100644
--- a/crates/ra_lsp_server/src/project_model.rs
+++ b/crates/ra_lsp_server/src/project_model.rs
@@ -1,7 +1,7 @@
1use std::{ 1use std::{
2 collections::{HashMap, HashSet},
3 path::{Path, PathBuf}, 2 path::{Path, PathBuf},
4}; 3};
4use rustc_hash::{FxHashMap, FxHashSet};
5use cargo_metadata::{metadata_run, CargoOpt}; 5use cargo_metadata::{metadata_run, CargoOpt};
6use ra_syntax::SmolStr; 6use ra_syntax::SmolStr;
7 7
@@ -80,11 +80,11 @@ impl CargoWorkspace {
80 true, 80 true,
81 Some(CargoOpt::AllFeatures) 81 Some(CargoOpt::AllFeatures)
82 ).map_err(|e| format_err!("cargo metadata failed: {}", e))?; 82 ).map_err(|e| format_err!("cargo metadata failed: {}", e))?;
83 let mut pkg_by_id = HashMap::new(); 83 let mut pkg_by_id = FxHashMap::default();
84 let mut packages = Vec::new(); 84 let mut packages = Vec::new();
85 let mut targets = Vec::new(); 85 let mut targets = Vec::new();
86 86
87 let ws_members: HashSet<String> = meta.workspace_members 87 let ws_members: FxHashSet<String> = meta.workspace_members
88 .into_iter() 88 .into_iter()
89 .map(|it| it.raw) 89 .map(|it| it.raw)
90 .collect(); 90 .collect();
diff --git a/crates/ra_lsp_server/src/req.rs b/crates/ra_lsp_server/src/req.rs
index 458c79ea9..f80957589 100644
--- a/crates/ra_lsp_server/src/req.rs
+++ b/crates/ra_lsp_server/src/req.rs
@@ -1,4 +1,4 @@
1use std::collections::HashMap; 1use rustc_hash::FxHashMap;
2use languageserver_types::{TextDocumentIdentifier, Range, Url, Position, Location}; 2use languageserver_types::{TextDocumentIdentifier, Range, Url, Position, Location};
3use url_serde; 3use url_serde;
4 4
@@ -149,7 +149,7 @@ pub struct Runnable {
149 pub label: String, 149 pub label: String,
150 pub bin: String, 150 pub bin: String,
151 pub args: Vec<String>, 151 pub args: Vec<String>,
152 pub env: HashMap<String, String>, 152 pub env: FxHashMap<String, String>,
153} 153}
154 154
155#[derive(Serialize, Debug)] 155#[derive(Serialize, Debug)]
diff --git a/crates/ra_lsp_server/src/server_world.rs b/crates/ra_lsp_server/src/server_world.rs
index 865f7c491..c4cdf83d4 100644
--- a/crates/ra_lsp_server/src/server_world.rs
+++ b/crates/ra_lsp_server/src/server_world.rs
@@ -1,10 +1,10 @@
1use std::{ 1use std::{
2 fs, 2 fs,
3 path::{PathBuf, Path}, 3 path::{PathBuf, Path},
4 collections::HashMap,
5 sync::Arc, 4 sync::Arc,
6}; 5};
7 6
7use rustc_hash::FxHashMap;
8use languageserver_types::Url; 8use languageserver_types::Url;
9use ra_analysis::{FileId, AnalysisHost, Analysis, CrateGraph, CrateId, LibraryData, FileResolver}; 9use ra_analysis::{FileId, AnalysisHost, Analysis, CrateGraph, CrateId, LibraryData, FileResolver};
10 10
@@ -20,7 +20,7 @@ pub struct ServerWorldState {
20 pub workspaces: Arc<Vec<CargoWorkspace>>, 20 pub workspaces: Arc<Vec<CargoWorkspace>>,
21 pub analysis_host: AnalysisHost, 21 pub analysis_host: AnalysisHost,
22 pub path_map: PathMap, 22 pub path_map: PathMap,
23 pub mem_map: HashMap<FileId, Option<String>>, 23 pub mem_map: FxHashMap<FileId, Option<String>>,
24} 24}
25 25
26#[derive(Clone)] 26#[derive(Clone)]
@@ -36,7 +36,7 @@ impl ServerWorldState {
36 workspaces: Arc::new(Vec::new()), 36 workspaces: Arc::new(Vec::new()),
37 analysis_host: AnalysisHost::new(), 37 analysis_host: AnalysisHost::new(),
38 path_map: PathMap::new(), 38 path_map: PathMap::new(),
39 mem_map: HashMap::new(), 39 mem_map: FxHashMap::default(),
40 } 40 }
41 } 41 }
42 pub fn apply_fs_changes(&mut self, events: Vec<FileEvent>) { 42 pub fn apply_fs_changes(&mut self, events: Vec<FileEvent>) {
@@ -121,7 +121,7 @@ impl ServerWorldState {
121 Ok(file_id) 121 Ok(file_id)
122 } 122 }
123 pub fn set_workspaces(&mut self, ws: Vec<CargoWorkspace>) { 123 pub fn set_workspaces(&mut self, ws: Vec<CargoWorkspace>) {
124 let mut crate_roots = HashMap::new(); 124 let mut crate_roots = FxHashMap::default();
125 ws.iter() 125 ws.iter()
126 .flat_map(|ws| { 126 .flat_map(|ws| {
127 ws.packages() 127 ws.packages()
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index f27093291..ef7b5b1a1 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -231,6 +231,24 @@ impl<'a> AstNode<'a> for CastExpr<'a> {
231 231
232impl<'a> CastExpr<'a> {} 232impl<'a> CastExpr<'a> {}
233 233
234// Comment
235#[derive(Debug, Clone, Copy)]
236pub struct Comment<'a> {
237 syntax: SyntaxNodeRef<'a>,
238}
239
240impl<'a> AstNode<'a> for Comment<'a> {
241 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
242 match syntax.kind() {
243 COMMENT => Some(Comment { syntax }),
244 _ => None,
245 }
246 }
247 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
248}
249
250impl<'a> Comment<'a> {}
251
234// Condition 252// Condition
235#[derive(Debug, Clone, Copy)] 253#[derive(Debug, Clone, Copy)]
236pub struct Condition<'a> { 254pub struct Condition<'a> {
diff --git a/crates/ra_syntax/src/ast/mod.rs b/crates/ra_syntax/src/ast/mod.rs
index c1570b868..10dac72e5 100644
--- a/crates/ra_syntax/src/ast/mod.rs
+++ b/crates/ra_syntax/src/ast/mod.rs
@@ -99,6 +99,49 @@ impl<'a> Lifetime<'a> {
99 } 99 }
100} 100}
101 101
102impl<'a> Comment<'a> {
103 pub fn text(&self) -> SmolStr {
104 self.syntax().leaf_text().unwrap().clone()
105 }
106
107 pub fn flavor(&self) -> CommentFlavor {
108 let text = self.text();
109 if text.starts_with("///") {
110 CommentFlavor::Doc
111 } else if text.starts_with("//!") {
112 CommentFlavor::ModuleDoc
113 } else if text.starts_with("//") {
114 CommentFlavor::Line
115 } else {
116 CommentFlavor::Multiline
117 }
118 }
119
120 pub fn prefix(&self) -> &'static str {
121 self.flavor().prefix()
122 }
123}
124
125#[derive(Debug)]
126pub enum CommentFlavor {
127 Line,
128 Doc,
129 ModuleDoc,
130 Multiline
131}
132
133impl CommentFlavor {
134 pub fn prefix(&self) -> &'static str {
135 use self::CommentFlavor::*;
136 match *self {
137 Line => "//",
138 Doc => "///",
139 ModuleDoc => "//!",
140 Multiline => "/*"
141 }
142 }
143}
144
102impl<'a> Name<'a> { 145impl<'a> Name<'a> {
103 pub fn text(&self) -> SmolStr { 146 pub fn text(&self) -> SmolStr {
104 let ident = self.syntax().first_child() 147 let ident = self.syntax().first_child()
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index 4b990fd8d..9da0c2c13 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -537,5 +537,6 @@ Grammar(
537 "PathSegment": ( 537 "PathSegment": (
538 options: [ "NameRef" ] 538 options: [ "NameRef" ]
539 ), 539 ),
540 "Comment": (),
540 }, 541 },
541) 542)