diff --git a/crates/gen_lsp_server/src/lib.rs b/crates/gen_lsp_server/src/lib.rs index 645728a573f..e45a6b5e27c 100644 --- a/crates/gen_lsp_server/src/lib.rs +++ b/crates/gen_lsp_server/src/lib.rs @@ -59,7 +59,6 @@ //! } //! ``` - #[macro_use] extern crate failure; #[macro_use] @@ -74,16 +73,16 @@ extern crate languageserver_types; mod msg; mod stdio; -use crossbeam_channel::{Sender, Receiver}; +use crossbeam_channel::{Receiver, Sender}; use languageserver_types::{ - ServerCapabilities, InitializeResult, InitializeParams, + notification::{Exit, Initialized}, request::{Initialize, Shutdown}, - notification::{Initialized, Exit}, + InitializeParams, InitializeResult, ServerCapabilities, }; pub type Result = ::std::result::Result; pub use { - msg::{RawMessage, RawRequest, RawResponse, RawResponseError, RawNotification, ErrorCode}, + msg::{ErrorCode, RawMessage, RawNotification, RawRequest, RawResponse, RawResponseError}, stdio::{stdio_transport, Threads}, }; @@ -97,11 +96,7 @@ pub fn run_server( caps: ServerCapabilities, receiver: Receiver, sender: Sender, - server: impl FnOnce( - InitializeParams, - &Receiver, - &Sender, - ) -> Result<()>, + server: impl FnOnce(InitializeParams, &Receiver, &Sender) -> Result<()>, ) -> Result<()> { info!("lsp server initializes"); let params = initialize(&receiver, &sender, caps)?; @@ -109,12 +104,10 @@ pub fn run_server( server(params, &receiver, &sender)?; info!("lsp server waiting for exit notification"); match receiver.recv() { - Some(RawMessage::Notification(n)) => { - n.cast::().map_err(|n| format_err!( - "unexpected notification during shutdown: {:?}", n - ))? - } - m => bail!("unexpected message during shutdown: {:?}", m) + Some(RawMessage::Notification(n)) => n + .cast::() + .map_err(|n| format_err!("unexpected notification during shutdown: {:?}", n))?, + m => bail!("unexpected message during shutdown: {:?}", m), } info!("lsp server shutdown complete"); Ok(()) @@ -141,17 +134,15 @@ fn initialize( Some(RawMessage::Request(req)) => match req.cast::() { Err(req) => bail!("expected initialize request, got {:?}", req), Ok(req) => req, - } - msg => - bail!("expected initialize request, got {:?}", msg), + }, + msg => bail!("expected initialize request, got {:?}", msg), }; let resp = RawResponse::ok::(id, &InitializeResult { capabilities: caps }); sender.send(RawMessage::Response(resp)); match receiver.recv() { Some(RawMessage::Notification(n)) => { - n.cast::().map_err(|_| format_err!( - "expected initialized notification" - ))?; + n.cast::() + .map_err(|_| format_err!("expected initialized notification"))?; } _ => bail!("expected initialized notification"), } diff --git a/crates/gen_lsp_server/src/msg.rs b/crates/gen_lsp_server/src/msg.rs index 7fcac6f6d38..e0d0aeab55c 100644 --- a/crates/gen_lsp_server/src/msg.rs +++ b/crates/gen_lsp_server/src/msg.rs @@ -1,11 +1,8 @@ use std::io::{BufRead, Write}; -use serde_json::{Value, from_str, to_string, from_value, to_value}; -use serde::{Serialize, de::DeserializeOwned}; -use languageserver_types::{ - request::Request, - notification::Notification, -}; +use languageserver_types::{notification::Notification, request::Request}; +use serde::{de::DeserializeOwned, Serialize}; +use serde_json::{from_str, from_value, to_string, to_value, Value}; use Result; @@ -81,7 +78,10 @@ impl RawMessage { #[serde(flatten)] msg: RawMessage, } - let text = to_string(&JsonRpc { jsonrpc: "2.0", msg: self })?; + let text = to_string(&JsonRpc { + jsonrpc: "2.0", + msg: self, + })?; write_msg_text(w, &text)?; Ok(()) } @@ -115,8 +115,9 @@ impl RawRequest { impl RawResponse { pub fn ok(id: u64, result: &R::Result) -> RawResponse - where R: Request, - R::Result: Serialize, + where + R: Request, + R::Result: Serialize, { RawResponse { id, @@ -125,7 +126,11 @@ impl RawResponse { } } pub fn err(id: u64, code: i32, message: String) -> RawResponse { - let error = RawResponseError { code, message, data: None }; + let error = RawResponseError { + code, + message, + data: None, + }; RawResponse { id, result: None, @@ -174,7 +179,9 @@ fn read_msg_text(inp: &mut impl BufRead) -> Result> { } let mut parts = buf.splitn(2, ": "); let header_name = parts.next().unwrap(); - let header_value = parts.next().ok_or_else(|| format_err!("malformed header: {:?}", buf))?; + let header_value = parts + .next() + .ok_or_else(|| format_err!("malformed header: {:?}", buf))?; if header_name == "Content-Length" { size = Some(header_value.parse::()?); } diff --git a/crates/gen_lsp_server/src/stdio.rs b/crates/gen_lsp_server/src/stdio.rs index 81397bb2a0a..3d8a1712abe 100644 --- a/crates/gen_lsp_server/src/stdio.rs +++ b/crates/gen_lsp_server/src/stdio.rs @@ -1,11 +1,9 @@ use std::{ + io::{stdin, stdout}, thread, - io::{ - stdout, stdin, - }, }; -use crossbeam_channel::{Receiver, Sender, bounded}; +use crossbeam_channel::{bounded, Receiver, Sender}; use {RawMessage, Result}; diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs index c6957723399..042dde1aca9 100644 --- a/crates/ra_analysis/src/db.rs +++ b/crates/ra_analysis/src/db.rs @@ -1,16 +1,17 @@ +use crate::{ + module_map::{ModuleDescriptorQuery, ModuleTreeQuery, ModulesDatabase}, + symbol_index::SymbolIndex, + FileId, FileResolverImp, +}; +use ra_editor::LineIndex; +use ra_syntax::File; +use rustc_hash::FxHashSet; +use salsa; + use std::{ fmt, - sync::Arc, hash::{Hash, Hasher}, -}; -use salsa; -use rustc_hash::FxHashSet; -use ra_syntax::File; -use ra_editor::{LineIndex}; -use crate::{ - symbol_index::SymbolIndex, - module_map::{ModulesDatabase, ModuleTreeQuery, ModuleDescriptorQuery}, - FileId, FileResolverImp, + sync::Arc, }; #[derive(Default)] diff --git a/crates/ra_analysis/src/descriptors.rs b/crates/ra_analysis/src/descriptors.rs index 8d9f38ca592..6f26f9935dd 100644 --- a/crates/ra_analysis/src/descriptors.rs +++ b/crates/ra_analysis/src/descriptors.rs @@ -1,41 +1,34 @@ -use std::{ - collections::BTreeMap, +use crate::{imp::FileResolverImp, FileId}; +use ra_syntax::{ + ast::{self, AstNode, NameOwner}, + text_utils::is_subrange, + SmolStr, }; use relative_path::RelativePathBuf; -use ra_syntax::{ - SmolStr, - ast::{self, NameOwner, AstNode}, - text_utils::is_subrange -}; -use crate::{ - FileId, - imp::FileResolverImp, -}; + +use std::collections::BTreeMap; #[derive(Debug, PartialEq, Eq, Hash)] pub struct ModuleDescriptor { - pub submodules: Vec + pub submodules: Vec, } impl ModuleDescriptor { pub fn new(root: ast::Root) -> ModuleDescriptor { - let submodules = modules(root) - .map(|(name, _)| Submodule { name }) - .collect(); + let submodules = modules(root).map(|(name, _)| Submodule { name }).collect(); - ModuleDescriptor { submodules } } + ModuleDescriptor { submodules } + } } -fn modules<'a>(root: ast::Root<'a>) -> impl Iterator)> { - root - .modules() - .filter_map(|module| { - let name = module.name()?.text(); - if !module.has_semi() { - return None; - } - Some((name, module)) - }) +fn modules<'a>(root: ast::Root<'a>) -> impl Iterator)> { + root.modules().filter_map(|module| { + let name = module.name()?.text(); + if !module.has_semi() { + return None; + } + Some((name, module)) + }) } #[derive(Clone, Hash, PartialEq, Eq, Debug)] @@ -56,7 +49,7 @@ struct Node(usize); struct NodeData { file_id: FileId, links: Vec, - parents: Vec + parents: Vec, } #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] @@ -69,7 +62,6 @@ struct LinkData { problem: Option, } - #[derive(Clone, Debug, Hash, PartialEq, Eq)] pub enum Problem { UnresolvedModule { @@ -78,16 +70,18 @@ pub enum Problem { NotDirOwner { move_to: RelativePathBuf, candidate: RelativePathBuf, - } + }, } impl ModuleTreeDescriptor { pub(crate) fn new<'a>( - files: impl Iterator + Clone, + files: impl Iterator + Clone, file_resolver: &FileResolverImp, ) -> ModuleTreeDescriptor { let mut file_id2node = BTreeMap::new(); - let mut nodes: Vec = files.clone().enumerate() + let mut nodes: Vec = files + .clone() + .enumerate() .map(|(idx, (file_id, _))| { file_id2node.insert(file_id, Node(idx)); NodeData { @@ -120,20 +114,19 @@ impl ModuleTreeDescriptor { points_to, problem, }) - } } ModuleTreeDescriptor { - nodes, links, file_id2node + nodes, + links, + file_id2node, } } pub(crate) fn parent_modules(&self, file_id: FileId) -> Vec { let node = self.file_id2node[&file_id]; - self.node(node) - .parents - .clone() + self.node(node).parents.clone() } pub(crate) fn child_module_by_name(&self, file_id: FileId, name: &str) -> Vec { let node = self.file_id2node[&file_id]; @@ -141,10 +134,18 @@ impl ModuleTreeDescriptor { .links .iter() .filter(|it| it.name(self) == name) - .flat_map(|link| link.points_to(self).iter().map(|&node| self.node(node).file_id)) + .flat_map(|link| { + link.points_to(self) + .iter() + .map(|&node| self.node(node).file_id) + }) .collect() } - pub(crate) fn problems<'a, 'b>(&'b self, file_id: FileId, root: ast::Root<'a>) -> Vec<(ast::Name<'a>, &'b Problem)> { + pub(crate) fn problems<'a, 'b>( + &'b self, + file_id: FileId, + root: ast::Root<'a>, + ) -> Vec<(ast::Name<'a>, &'b Problem)> { let node = self.file_id2node[&file_id]; self.node(node) .links @@ -176,7 +177,11 @@ impl Link { fn points_to(self, tree: &ModuleTreeDescriptor) -> &[Node] { &tree.link(self).points_to } - pub(crate) fn bind_source<'a>(self, tree: &ModuleTreeDescriptor, root: ast::Root<'a>) -> ast::Module<'a> { + pub(crate) fn bind_source<'a>( + self, + tree: &ModuleTreeDescriptor, + root: ast::Root<'a>, + ) -> ast::Module<'a> { modules(root) .filter(|(name, _)| name == &tree.link(self).name) .next() @@ -185,22 +190,21 @@ impl Link { } } - fn resolve_submodule( file_id: FileId, name: &SmolStr, - file_resolver: &FileResolverImp + file_resolver: &FileResolverImp, ) -> (Vec, Option) { let mod_name = file_resolver.file_stem(file_id); - let is_dir_owner = - mod_name == "mod" || mod_name == "lib" || mod_name == "main"; + let is_dir_owner = mod_name == "mod" || mod_name == "lib" || mod_name == "main"; let file_mod = RelativePathBuf::from(format!("../{}.rs", name)); let dir_mod = RelativePathBuf::from(format!("../{}/mod.rs", name)); let points_to: Vec; let problem: Option; if is_dir_owner { - points_to = [&file_mod, &dir_mod].iter() + points_to = [&file_mod, &dir_mod] + .iter() .filter_map(|path| file_resolver.resolve(file_id, path)) .collect(); problem = if points_to.is_empty() { @@ -223,7 +227,7 @@ fn resolve_submodule( #[derive(Debug, Clone)] pub struct FnDescriptor { pub name: String, - pub label : String, + pub label: String, pub ret_type: Option, pub params: Vec, } @@ -233,9 +237,11 @@ impl FnDescriptor { let name = node.name()?.text().to_string(); // Strip the body out for the label. - let label : String = if let Some(body) = node.body() { + let label: String = if let Some(body) = node.body() { let body_range = body.syntax().range(); - let label : String = node.syntax().children() + let label: String = node + .syntax() + .children() .filter(|child| !is_subrange(body_range, child.range())) .map(|node| node.text().to_string()) .collect(); @@ -251,7 +257,7 @@ impl FnDescriptor { name, ret_type, params, - label + label, }) } @@ -264,9 +270,11 @@ impl FnDescriptor { // Maybe use param.pat here? See if we can just extract the name? //res.extend(param_list.params().map(|p| p.syntax().text().to_string())); - res.extend(param_list.params() - .filter_map(|p| p.pat()) - .map(|pat| pat.syntax().text().to_string()) + res.extend( + param_list + .params() + .filter_map(|p| p.pat()) + .map(|pat| pat.syntax().text().to_string()), ); } res diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index 5efcaeca04a..f1403cb5d78 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs @@ -1,32 +1,31 @@ use std::{ - sync::{ - Arc, - }, - hash::{Hash, Hasher}, - fmt, collections::VecDeque, + fmt, + hash::{Hash, Hasher}, iter, + sync::Arc, }; +use ra_editor::{self, find_node_at_offset, resolve_local_name, FileSymbol, LineIndex, LocalEdit}; +use ra_syntax::{ + ast::{self, ArgListOwner, Expr, NameOwner}, + AstNode, File, SmolStr, + SyntaxKind::*, + SyntaxNodeRef, TextRange, TextUnit, +}; use relative_path::RelativePath; use rustc_hash::FxHashSet; -use ra_editor::{self, FileSymbol, LineIndex, find_node_at_offset, LocalEdit, resolve_local_name}; -use ra_syntax::{ - TextUnit, TextRange, SmolStr, File, AstNode, SyntaxNodeRef, - SyntaxKind::*, - ast::{self, NameOwner, ArgListOwner, Expr}, -}; use crate::{ - FileId, FileResolver, Query, Diagnostic, SourceChange, SourceFileEdit, Position, FileSystemEdit, - JobToken, CrateGraph, CrateId, - roots::{SourceRoot, ReadonlySourceRoot, WritableSourceRoot}, descriptors::{FnDescriptor, ModuleTreeDescriptor, Problem}, + roots::{ReadonlySourceRoot, SourceRoot, WritableSourceRoot}, + CrateGraph, CrateId, Diagnostic, FileId, FileResolver, FileSystemEdit, JobToken, Position, + Query, SourceChange, SourceFileEdit, }; #[derive(Clone, Debug)] pub(crate) struct FileResolverImp { - inner: Arc + inner: Arc, } impl PartialEq for FileResolverImp { @@ -35,8 +34,7 @@ impl PartialEq for FileResolverImp { } } -impl Eq for FileResolverImp { -} +impl Eq for FileResolverImp {} impl Hash for FileResolverImp { fn hash(&self, hasher: &mut H) { @@ -67,17 +65,23 @@ impl Default for FileResolverImp { fn file_stem(&self, _file_: FileId) -> String { panic!("file resolver not set") } - fn resolve(&self, _file_id: FileId, _path: &::relative_path::RelativePath) -> Option { + fn resolve( + &self, + _file_id: FileId, + _path: &::relative_path::RelativePath, + ) -> Option { panic!("file resolver not set") } } - FileResolverImp { inner: Arc::new(DummyResolver) } + FileResolverImp { + inner: Arc::new(DummyResolver), + } } } #[derive(Debug)] pub(crate) struct AnalysisHostImpl { - data: WorldData + data: WorldData, } impl AnalysisHostImpl { @@ -91,13 +95,13 @@ impl AnalysisHostImpl { data: self.data.clone(), } } - pub fn change_files(&mut self, changes: &mut dyn Iterator)>) { - self.data_mut() - .root.apply_changes(changes, None); + pub fn change_files(&mut self, changes: &mut dyn Iterator)>) { + self.data_mut().root.apply_changes(changes, None); } pub fn set_file_resolver(&mut self, resolver: FileResolverImp) { self.data_mut() - .root.apply_changes(&mut iter::empty(), Some(resolver)); + .root + .apply_changes(&mut iter::empty(), Some(resolver)); } pub fn set_crate_graph(&mut self, graph: CrateGraph) { let mut visited = FxHashSet::default(); @@ -131,7 +135,12 @@ impl AnalysisImpl { if self.data.root.contains(file_id) { return &self.data.root; } - &**self.data.libs.iter().find(|it| it.contains(file_id)).unwrap() + &**self + .data + .libs + .iter() + .find(|it| it.contains(file_id)) + .unwrap() } pub fn file_syntax(&self, file_id: FileId) -> File { self.root(file_id).syntax(file_id) @@ -142,18 +151,17 @@ impl AnalysisImpl { pub fn world_symbols(&self, query: Query, token: &JobToken) -> Vec<(FileId, FileSymbol)> { let mut buf = Vec::new(); if query.libs { - self.data.libs.iter() - .for_each(|it| it.symbols(&mut buf)); + self.data.libs.iter().for_each(|it| it.symbols(&mut buf)); } else { self.data.root.symbols(&mut buf); } query.search(&buf, token) - } pub fn parent_module(&self, file_id: FileId) -> Vec<(FileId, FileSymbol)> { let root = self.root(file_id); let module_tree = root.module_tree(); - module_tree.parent_modules(file_id) + module_tree + .parent_modules(file_id) .iter() .map(|link| { let file_id = link.owner(&module_tree); @@ -203,15 +211,17 @@ impl AnalysisImpl { let file = root.syntax(file_id); let syntax = file.syntax(); if let Some(name_ref) = find_node_at_offset::(syntax, offset) { - // First try to resolve the symbol locally if let Some((name, range)) = resolve_local_name(&file, offset, name_ref) { let mut vec = vec![]; - vec.push((file_id, FileSymbol { - name, - node_range: range, - kind : NAME - })); + vec.push(( + file_id, + FileSymbol { + name, + node_range: range, + kind: NAME, + }, + )); return vec; } else { @@ -224,17 +234,21 @@ impl AnalysisImpl { if module.has_semi() { let file_ids = self.resolve_module(&*module_tree, file_id, module); - let res = file_ids.into_iter().map(|id| { - let name = module.name() - .map(|n| n.text()) - .unwrap_or_else(|| SmolStr::new("")); - let symbol = FileSymbol { - name, - node_range: TextRange::offset_len(0.into(), 0.into()), - kind: MODULE, - }; - (id, symbol) - }).collect(); + let res = file_ids + .into_iter() + .map(|id| { + let name = module + .name() + .map(|n| n.text()) + .unwrap_or_else(|| SmolStr::new("")); + let symbol = FileSymbol { + name, + node_range: TextRange::offset_len(0.into(), 0.into()), + kind: MODULE, + }; + (id, symbol) + }) + .collect(); return res; } @@ -245,12 +259,16 @@ impl AnalysisImpl { pub fn diagnostics(&self, file_id: FileId) -> Vec { let root = self.root(file_id); - let module_tree = root.module_tree(); + let module_tree = root.module_tree(); let syntax = root.syntax(file_id); let mut res = ra_editor::diagnostics(&syntax) .into_iter() - .map(|d| Diagnostic { range: d.range, message: d.msg, fix: None }) + .map(|d| Diagnostic { + range: d.range, + message: d.msg, + fix: None, + }) .collect::>(); for (name_node, problem) in module_tree.problems(file_id, syntax.ast()) { @@ -273,8 +291,14 @@ impl AnalysisImpl { } } Problem::NotDirOwner { move_to, candidate } => { - let move_file = FileSystemEdit::MoveFile { file: file_id, path: move_to.clone() }; - let create_file = FileSystemEdit::CreateFile { anchor: file_id, path: move_to.join(candidate) }; + let move_file = FileSystemEdit::MoveFile { + file: file_id, + path: move_to.clone(), + }; + let create_file = FileSystemEdit::CreateFile { + anchor: file_id, + path: move_to.join(candidate), + }; let fix = SourceChange { label: "move file and create module".to_string(), source_file_edits: Vec::new(), @@ -297,23 +321,34 @@ impl AnalysisImpl { let file = self.file_syntax(file_id); let offset = range.start(); let actions = vec![ - ("flip comma", ra_editor::flip_comma(&file, offset).map(|f| f())), - ("add `#[derive]`", ra_editor::add_derive(&file, offset).map(|f| f())), + ( + "flip comma", + ra_editor::flip_comma(&file, offset).map(|f| f()), + ), + ( + "add `#[derive]`", + ra_editor::add_derive(&file, offset).map(|f| f()), + ), ("add impl", ra_editor::add_impl(&file, offset).map(|f| f())), - ("introduce variable", ra_editor::introduce_variable(&file, range).map(|f| f())), + ( + "introduce variable", + ra_editor::introduce_variable(&file, range).map(|f| f()), + ), ]; - actions.into_iter() + actions + .into_iter() .filter_map(|(name, local_edit)| { - Some(SourceChange::from_local_edit( - file_id, name, local_edit?, - )) + Some(SourceChange::from_local_edit(file_id, name, local_edit?)) }) .collect() } - pub fn resolve_callable(&self, file_id: FileId, offset: TextUnit, token: &JobToken) - -> Option<(FnDescriptor, Option)> { - + pub fn resolve_callable( + &self, + file_id: FileId, + offset: TextUnit, + token: &JobToken, + ) -> Option<(FnDescriptor, Option)> { let root = self.root(file_id); let file = root.syntax(file_id); let syntax = file.syntax(); @@ -332,9 +367,7 @@ impl AnalysisImpl { let mut current_parameter = None; let num_params = descriptor.params.len(); - let has_self = fn_def.param_list() - .and_then(|l| l.self_param()) - .is_some(); + let has_self = fn_def.param_list().and_then(|l| l.self_param()).is_some(); if num_params == 1 { if !has_self { @@ -350,8 +383,11 @@ impl AnalysisImpl { let start = arg_list.syntax().range().start(); let range_search = TextRange::from_to(start, offset); - let mut commas: usize = arg_list.syntax().text() - .slice(range_search).to_string() + let mut commas: usize = arg_list + .syntax() + .text() + .slice(range_search) + .to_string() .matches(",") .count(); @@ -381,7 +417,12 @@ impl AnalysisImpl { self.world_symbols(query, token) } - fn resolve_module(&self, module_tree: &ModuleTreeDescriptor, file_id: FileId, module: ast::Module) -> Vec { + fn resolve_module( + &self, + module_tree: &ModuleTreeDescriptor, + file_id: FileId, + module: ast::Module, + ) -> Vec { let name = match module.name() { Some(name) => name.text(), None => return Vec::new(), @@ -407,15 +448,17 @@ impl SourceChange { label: label.to_string(), source_file_edits: vec![file_edit], file_system_edits: vec![], - cursor_position: edit.cursor_position - .map(|offset| Position { offset, file_id }) + cursor_position: edit + .cursor_position + .map(|offset| Position { offset, file_id }), } } } impl CrateGraph { fn crate_id_for_crate_root(&self, file_id: FileId) -> Option { - let (&crate_id, _) = self.crate_roots + let (&crate_id, _) = self + .crate_roots .iter() .find(|(_crate_id, &root_id)| root_id == file_id)?; Some(crate_id) @@ -424,7 +467,7 @@ impl CrateGraph { enum FnCallNode<'a> { CallExpr(ast::CallExpr<'a>), - MethodCallExpr(ast::MethodCallExpr<'a>) + MethodCallExpr(ast::MethodCallExpr<'a>), } impl<'a> FnCallNode<'a> { @@ -440,27 +483,23 @@ impl<'a> FnCallNode<'a> { pub fn name_ref(&self) -> Option { match *self { - FnCallNode::CallExpr(call_expr) => { - Some(match call_expr.expr()? { - Expr::PathExpr(path_expr) => { - path_expr.path()?.segment()?.name_ref()? - }, - _ => return None - }) - }, + FnCallNode::CallExpr(call_expr) => Some(match call_expr.expr()? { + Expr::PathExpr(path_expr) => path_expr.path()?.segment()?.name_ref()?, + _ => return None, + }), - FnCallNode::MethodCallExpr(call_expr) => { - call_expr.syntax().children() - .filter_map(ast::NameRef::cast) - .nth(0) - } + FnCallNode::MethodCallExpr(call_expr) => call_expr + .syntax() + .children() + .filter_map(ast::NameRef::cast) + .nth(0), } } pub fn arg_list(&self) -> Option { match *self { FnCallNode::CallExpr(expr) => expr.arg_list(), - FnCallNode::MethodCallExpr(expr) => expr.arg_list() + FnCallNode::MethodCallExpr(expr) => expr.arg_list(), } } } diff --git a/crates/ra_analysis/src/job.rs b/crates/ra_analysis/src/job.rs index ea1652a26e6..2871f983908 100644 --- a/crates/ra_analysis/src/job.rs +++ b/crates/ra_analysis/src/job.rs @@ -14,15 +14,20 @@ impl JobHandle { pub fn new() -> (JobHandle, JobToken) { let (sender_alive, receiver_alive) = bounded(0); let (sender_canceled, receiver_canceled) = bounded(0); - let token = JobToken { _job_alive: sender_alive, job_canceled: receiver_canceled }; - let handle = JobHandle { job_alive: receiver_alive, _job_canceled: sender_canceled }; + let token = JobToken { + _job_alive: sender_alive, + job_canceled: receiver_canceled, + }; + let handle = JobHandle { + job_alive: receiver_alive, + _job_canceled: sender_canceled, + }; (handle, token) } pub fn has_completed(&self) -> bool { is_closed(&self.job_alive) } - pub fn cancel(self) { - } + pub fn cancel(self) {} } impl JobToken { @@ -31,7 +36,6 @@ impl JobToken { } } - // We don't actually send messages through the channels, // and instead just check if the channel is closed, // so we use uninhabited enum as a message type diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index d8b355a81aa..2eeacaabe34 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs @@ -1,44 +1,40 @@ extern crate parking_lot; #[macro_use] extern crate log; -extern crate once_cell; -extern crate ra_syntax; -extern crate ra_editor; extern crate fst; +extern crate once_cell; +extern crate ra_editor; +extern crate ra_syntax; extern crate rayon; extern crate relative_path; #[macro_use] extern crate crossbeam_channel; extern crate im; -extern crate salsa; extern crate rustc_hash; +extern crate salsa; -mod symbol_index; -mod module_map; -mod imp; -mod job; -mod roots; mod db; mod descriptors; +mod imp; +mod job; +mod module_map; +mod roots; +mod symbol_index; -use std::{ - sync::Arc, - fmt::Debug, -}; +use std::{fmt::Debug, sync::Arc}; +use crate::imp::{AnalysisHostImpl, AnalysisImpl, FileResolverImp}; +use ra_syntax::{AtomEdit, File, TextRange, TextUnit}; use relative_path::{RelativePath, RelativePathBuf}; -use ra_syntax::{File, TextRange, TextUnit, AtomEdit}; use rustc_hash::FxHashMap; -use crate::imp::{AnalysisImpl, AnalysisHostImpl, FileResolverImp}; -pub use ra_editor::{ - StructureNode, LineIndex, FileSymbol, - Runnable, RunnableKind, HighlightedRange, CompletionItem, - Fold, FoldKind -}; pub use crate::{ - job::{JobToken, JobHandle}, descriptors::FnDescriptor, + job::{JobHandle, JobToken}, +}; +pub use ra_editor::{ + CompletionItem, FileSymbol, Fold, FoldKind, HighlightedRange, LineIndex, Runnable, + RunnableKind, StructureNode, }; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -59,20 +55,24 @@ pub trait FileResolver: Debug + Send + Sync + 'static { #[derive(Debug)] pub struct AnalysisHost { - imp: AnalysisHostImpl + imp: AnalysisHostImpl, } impl AnalysisHost { pub fn new() -> AnalysisHost { - AnalysisHost { imp: AnalysisHostImpl::new() } + AnalysisHost { + imp: AnalysisHostImpl::new(), + } } pub fn analysis(&self) -> Analysis { - Analysis { imp: self.imp.analysis() } + Analysis { + imp: self.imp.analysis(), + } } pub fn change_file(&mut self, file_id: FileId, text: Option) { self.change_files(::std::iter::once((file_id, text))); } - pub fn change_files(&mut self, mut changes: impl Iterator)>) { + pub fn change_files(&mut self, mut changes: impl Iterator)>) { self.imp.change_files(&mut changes) } pub fn set_file_resolver(&mut self, resolver: Arc) { @@ -115,7 +115,7 @@ pub enum FileSystemEdit { MoveFile { file: FileId, path: RelativePathBuf, - } + }, } #[derive(Debug)] @@ -144,7 +144,7 @@ impl Query { only_types: false, libs: false, exact: false, - limit: usize::max_value() + limit: usize::max_value(), } } pub fn only_types(&mut self) { @@ -163,7 +163,7 @@ impl Query { #[derive(Debug)] pub struct Analysis { - imp: AnalysisImpl + imp: AnalysisImpl, } impl Analysis { @@ -195,7 +195,11 @@ impl Analysis { } pub fn on_eq_typed(&self, file_id: FileId, offset: TextUnit) -> Option { let file = self.imp.file_syntax(file_id); - Some(SourceChange::from_local_edit(file_id, "add semicolon", ra_editor::on_eq_typed(&file, offset)?)) + Some(SourceChange::from_local_edit( + file_id, + "add semicolon", + ra_editor::on_eq_typed(&file, offset)?, + )) } pub fn file_structure(&self, file_id: FileId) -> Vec { let file = self.imp.file_syntax(file_id); @@ -204,8 +208,14 @@ impl Analysis { pub fn symbol_search(&self, query: Query, token: &JobToken) -> Vec<(FileId, FileSymbol)> { self.imp.world_symbols(query, token) } - pub fn approximately_resolve_symbol(&self, file_id: FileId, offset: TextUnit, token: &JobToken) -> Vec<(FileId, FileSymbol)> { - self.imp.approximately_resolve_symbol(file_id, offset, token) + pub fn approximately_resolve_symbol( + &self, + file_id: FileId, + offset: TextUnit, + token: &JobToken, + ) -> Vec<(FileId, FileSymbol)> { + self.imp + .approximately_resolve_symbol(file_id, offset, token) } pub fn parent_module(&self, file_id: FileId) -> Vec<(FileId, FileSymbol)> { self.imp.parent_module(file_id) @@ -239,15 +249,19 @@ impl Analysis { ra_editor::folding_ranges(&file) } - pub fn resolve_callable(&self, file_id: FileId, offset: TextUnit, token: &JobToken) - -> Option<(FnDescriptor, Option)> { + pub fn resolve_callable( + &self, + file_id: FileId, + offset: TextUnit, + token: &JobToken, + ) -> Option<(FnDescriptor, Option)> { self.imp.resolve_callable(file_id, offset, token) } } #[derive(Debug)] pub struct LibraryData { - root: roots::ReadonlySourceRoot + root: roots::ReadonlySourceRoot, } impl LibraryData { diff --git a/crates/ra_analysis/src/module_map.rs b/crates/ra_analysis/src/module_map.rs index c1799e3d4a8..ff0ec3cc7b2 100644 --- a/crates/ra_analysis/src/module_map.rs +++ b/crates/ra_analysis/src/module_map.rs @@ -1,10 +1,11 @@ -use std::sync::Arc; use crate::{ - FileId, - db::{SyntaxDatabase}, + db::SyntaxDatabase, descriptors::{ModuleDescriptor, ModuleTreeDescriptor}, + FileId, }; +use std::sync::Arc; + salsa::query_group! { pub(crate) trait ModulesDatabase: SyntaxDatabase { fn module_tree(key: ()) -> Arc { @@ -16,7 +17,6 @@ salsa::query_group! { } } - fn module_descriptor(db: &impl ModulesDatabase, file_id: FileId) -> Arc { let file = db.file_syntax(file_id); Arc::new(ModuleDescriptor::new(file.ast())) @@ -29,6 +29,9 @@ fn module_tree(db: &impl ModulesDatabase, (): ()) -> Arc { let module_descr = db.module_descriptor(file_id); files.push((file_id, module_descr)); } - let res = ModuleTreeDescriptor::new(files.iter().map(|(file_id, descr)| (*file_id, &**descr)), &file_set.resolver); + let res = ModuleTreeDescriptor::new( + files.iter().map(|(file_id, descr)| (*file_id, &**descr)), + &file_set.resolver, + ); Arc::new(res) } diff --git a/crates/ra_analysis/src/roots.rs b/crates/ra_analysis/src/roots.rs index 76bcecd38ed..1f2b21b272f 100644 --- a/crates/ra_analysis/src/roots.rs +++ b/crates/ra_analysis/src/roots.rs @@ -1,22 +1,19 @@ -use std::{ - sync::Arc, - panic, -}; +use std::{panic, sync::Arc}; use once_cell::sync::OnceCell; -use rayon::prelude::*; -use salsa::Database; -use rustc_hash::{FxHashMap, FxHashSet}; use ra_editor::LineIndex; use ra_syntax::File; +use rayon::prelude::*; +use rustc_hash::{FxHashMap, FxHashSet}; +use salsa::Database; use crate::{ - FileId, - imp::FileResolverImp, - symbol_index::SymbolIndex, - descriptors::{ModuleDescriptor, ModuleTreeDescriptor}, db::{self, FilesDatabase, SyntaxDatabase}, + descriptors::{ModuleDescriptor, ModuleTreeDescriptor}, + imp::FileResolverImp, module_map::ModulesDatabase, + symbol_index::SymbolIndex, + FileId, }; pub(crate) trait SourceRoot { @@ -35,7 +32,7 @@ pub(crate) struct WritableSourceRoot { impl WritableSourceRoot { pub fn apply_changes( &mut self, - changes: &mut dyn Iterator)>, + changes: &mut dyn Iterator)>, file_resolver: Option, ) { let mut changed = FxHashSet::default(); @@ -46,22 +43,22 @@ impl WritableSourceRoot { removed.insert(file_id); } Some(text) => { - self.db.query(db::FileTextQuery) + self.db + .query(db::FileTextQuery) .set(file_id, Arc::new(text)); changed.insert(file_id); } } } let file_set = self.db.file_set(()); - let mut files: FxHashSet = file_set - .files - .clone(); + let mut files: FxHashSet = file_set.files.clone(); for file_id in removed { files.remove(&file_id); } files.extend(changed); let resolver = file_resolver.unwrap_or_else(|| file_set.resolver.clone()); - self.db.query(db::FileSetQuery) + self.db + .query(db::FileSetQuery) .set((), Arc::new(db::FileSet { files, resolver })); } } @@ -71,9 +68,7 @@ impl SourceRoot for WritableSourceRoot { self.db.module_tree(()) } fn contains(&self, file_id: FileId) -> bool { - self.db.file_set(()) - .files - .contains(&file_id) + self.db.file_set(()).files.contains(&file_id) } fn lines(&self, file_id: FileId) -> Arc { self.db.file_lines(file_id) @@ -83,7 +78,7 @@ impl SourceRoot for WritableSourceRoot { } fn symbols<'a>(&'a self, acc: &mut Vec>) { let db = &self.db; - let symbols = db.file_set(()); + let symbols = db.file_set(()); let symbols = symbols .files .iter() @@ -108,12 +103,15 @@ impl FileData { } } fn lines(&self) -> &Arc { - self.lines.get_or_init(|| Arc::new(LineIndex::new(&self.text))) + self.lines + .get_or_init(|| Arc::new(LineIndex::new(&self.text))) } fn syntax(&self) -> &File { let text = &self.text; let syntax = &self.syntax; - match panic::catch_unwind(panic::AssertUnwindSafe(|| syntax.get_or_init(|| File::parse(text)))) { + match panic::catch_unwind(panic::AssertUnwindSafe(|| { + syntax.get_or_init(|| File::parse(text)) + })) { Ok(file) => file, Err(err) => { error!("Parser paniced on:\n------\n{}\n------\n", text); @@ -131,22 +129,23 @@ pub(crate) struct ReadonlySourceRoot { } impl ReadonlySourceRoot { - pub(crate) fn new(files: Vec<(FileId, String)>, file_resolver: FileResolverImp) -> ReadonlySourceRoot { - let modules = files.par_iter() + pub(crate) fn new( + files: Vec<(FileId, String)>, + file_resolver: FileResolverImp, + ) -> ReadonlySourceRoot { + let modules = files + .par_iter() .map(|(file_id, text)| { let syntax = File::parse(text); let mod_descr = ModuleDescriptor::new(syntax.ast()); (*file_id, syntax, mod_descr) }) .collect::>(); - let module_tree = ModuleTreeDescriptor::new( - modules.iter().map(|it| (it.0, &it.2)), - &file_resolver, - ); + let module_tree = + ModuleTreeDescriptor::new(modules.iter().map(|it| (it.0, &it.2)), &file_resolver); - let symbol_index = SymbolIndex::for_files( - modules.par_iter().map(|it| (it.0, it.1.clone())) - ); + let symbol_index = + SymbolIndex::for_files(modules.par_iter().map(|it| (it.0, it.1.clone()))); let file_map: FxHashMap = files .into_iter() .map(|(id, text)| (id, FileData::new(text))) diff --git a/crates/ra_analysis/src/symbol_index.rs b/crates/ra_analysis/src/symbol_index.rs index 54672fde42d..51eef817043 100644 --- a/crates/ra_analysis/src/symbol_index.rs +++ b/crates/ra_analysis/src/symbol_index.rs @@ -1,15 +1,16 @@ -use std::{ - sync::Arc, - hash::{Hash, Hasher}, -}; -use ra_editor::{FileSymbol, file_symbols}; +use crate::{FileId, JobToken, Query}; +use fst::{self, Streamer}; +use ra_editor::{file_symbols, FileSymbol}; use ra_syntax::{ File, SyntaxKind::{self, *}, }; -use fst::{self, Streamer}; use rayon::prelude::*; -use crate::{Query, FileId, JobToken}; + +use std::{ + hash::{Hash, Hasher}, + sync::Arc, +}; #[derive(Debug)] pub(crate) struct SymbolIndex { @@ -23,8 +24,7 @@ impl PartialEq for SymbolIndex { } } -impl Eq for SymbolIndex { -} +impl Eq for SymbolIndex {} impl Hash for SymbolIndex { fn hash(&self, hasher: &mut H) { @@ -33,14 +33,12 @@ impl Hash for SymbolIndex { } impl SymbolIndex { - pub(crate) fn for_files(files: impl ParallelIterator) -> SymbolIndex { + pub(crate) fn for_files(files: impl ParallelIterator) -> SymbolIndex { let mut symbols = files .flat_map(|(file_id, file)| { file_symbols(&file) .into_iter() - .map(move |symbol| { - (symbol.name.as_str().to_lowercase(), (file_id, symbol)) - }) + .map(move |symbol| (symbol.name.as_str().to_lowercase(), (file_id, symbol))) .collect::>() }) .collect::>(); @@ -48,9 +46,7 @@ impl SymbolIndex { symbols.dedup_by(|s1, s2| s1.0 == s2.0); let (names, symbols): (Vec, Vec<(FileId, FileSymbol)>) = symbols.into_iter().unzip(); - let map = fst::Map::from_iter( - names.into_iter().zip(0u64..) - ).unwrap(); + let map = fst::Map::from_iter(names.into_iter().zip(0u64..)).unwrap(); SymbolIndex { symbols, map } } @@ -65,7 +61,6 @@ impl Query { indices: &[Arc], token: &JobToken, ) -> Vec<(FileId, FileSymbol)> { - let mut op = fst::map::OpBuilder::new(); for file_symbols in indices.iter() { let automaton = fst::automaton::Subsequence::new(&self.lowercased); diff --git a/crates/ra_analysis/tests/tests.rs b/crates/ra_analysis/tests/tests.rs index 2d3679fa92c..e0c637d65d5 100644 --- a/crates/ra_analysis/tests/tests.rs +++ b/crates/ra_analysis/tests/tests.rs @@ -1,32 +1,31 @@ -extern crate relative_path; extern crate ra_analysis; -extern crate rustc_hash; extern crate ra_editor; extern crate ra_syntax; +extern crate relative_path; +extern crate rustc_hash; extern crate test_utils; -use std::{ - sync::Arc, -}; +use std::sync::Arc; -use rustc_hash::FxHashMap; +use ra_analysis::{ + Analysis, AnalysisHost, CrateGraph, CrateId, FileId, FileResolver, FnDescriptor, JobHandle, +}; use relative_path::{RelativePath, RelativePathBuf}; -use ra_analysis::{Analysis, AnalysisHost, FileId, FileResolver, JobHandle, CrateGraph, CrateId, FnDescriptor}; +use rustc_hash::FxHashMap; use test_utils::{assert_eq_dbg, extract_offset}; #[derive(Debug)] struct FileMap(Vec<(FileId, RelativePathBuf)>); impl FileMap { - fn iter<'a>(&'a self) -> impl Iterator + 'a { - self.0.iter().map(|(id, path)| (*id, path.as_relative_path())) + fn iter<'a>(&'a self) -> impl Iterator + 'a { + self.0 + .iter() + .map(|(id, path)| (*id, path.as_relative_path())) } fn path(&self, id: FileId) -> &RelativePath { - self.iter() - .find(|&(it, _)| it == id) - .unwrap() - .1 + self.iter().find(|&(it, _)| it == id).unwrap().1 } } @@ -71,10 +70,7 @@ fn get_signature(text: &str) -> (FnDescriptor, Option) { #[test] fn test_resolve_module() { - let snap = analysis(&[ - ("/lib.rs", "mod foo;"), - ("/foo.rs", "") - ]); + let snap = analysis(&[("/lib.rs", "mod foo;"), ("/foo.rs", "")]); let (_handle, token) = JobHandle::new(); let symbols = snap.approximately_resolve_symbol(FileId(1), 4.into(), &token); assert_eq_dbg( @@ -82,10 +78,7 @@ fn test_resolve_module() { &symbols, ); - let snap = analysis(&[ - ("/lib.rs", "mod foo;"), - ("/foo/mod.rs", "") - ]); + let snap = analysis(&[("/lib.rs", "mod foo;"), ("/foo/mod.rs", "")]); let symbols = snap.approximately_resolve_symbol(FileId(1), 4.into(), &token); assert_eq_dbg( r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#, @@ -114,18 +107,12 @@ fn test_unresolved_module_diagnostic() { fn test_unresolved_module_diagnostic_no_diag_for_inline_mode() { let snap = analysis(&[("/lib.rs", "mod foo {}")]); let diagnostics = snap.diagnostics(FileId(1)); - assert_eq_dbg( - r#"[]"#, - &diagnostics, - ); + assert_eq_dbg(r#"[]"#, &diagnostics); } #[test] fn test_resolve_parent_module() { - let snap = analysis(&[ - ("/lib.rs", "mod foo;"), - ("/foo.rs", ""), - ]); + let snap = analysis(&[("/lib.rs", "mod foo;"), ("/foo.rs", "")]); let symbols = snap.parent_module(FileId(2)); assert_eq_dbg( r#"[(FileId(1), FileSymbol { name: "foo", node_range: [0; 8), kind: MODULE })]"#, @@ -135,10 +122,7 @@ fn test_resolve_parent_module() { #[test] fn test_resolve_crate_root() { - let mut host = analysis_host(&[ - ("/lib.rs", "mod foo;"), - ("/foo.rs", ""), - ]); + let mut host = analysis_host(&[("/lib.rs", "mod foo;"), ("/foo.rs", "")]); let snap = host.analysis(); assert!(snap.crate_for(FileId(2)).is_empty()); @@ -152,20 +136,18 @@ fn test_resolve_crate_root() { host.set_crate_graph(crate_graph); let snap = host.analysis(); - assert_eq!( - snap.crate_for(FileId(2)), - vec![CrateId(1)], - ); + assert_eq!(snap.crate_for(FileId(2)), vec![CrateId(1)],); } #[test] fn test_fn_signature_two_args_first() { let (desc, param) = get_signature( -r#"fn foo(x: u32, y: u32) -> u32 {x + y} -fn bar() { foo(<|>3, ); }"#); + r#"fn foo(x: u32, y: u32) -> u32 {x + y} +fn bar() { foo(<|>3, ); }"#, + ); assert_eq!(desc.name, "foo".to_string()); - assert_eq!(desc.params, vec!("x".to_string(),"y".to_string())); + assert_eq!(desc.params, vec!("x".to_string(), "y".to_string())); assert_eq!(desc.ret_type, Some("-> u32".into())); assert_eq!(param, Some(0)); } @@ -174,10 +156,11 @@ fn bar() { foo(<|>3, ); }"#); fn test_fn_signature_two_args_second() { let (desc, param) = get_signature( r#"fn foo(x: u32, y: u32) -> u32 {x + y} -fn bar() { foo(3, <|>); }"#); +fn bar() { foo(3, <|>); }"#, + ); assert_eq!(desc.name, "foo".to_string()); - assert_eq!(desc.params, vec!("x".to_string(),"y".to_string())); + assert_eq!(desc.params, vec!("x".to_string(), "y".to_string())); assert_eq!(desc.ret_type, Some("-> u32".into())); assert_eq!(param, Some(1)); } @@ -185,8 +168,9 @@ fn bar() { foo(3, <|>); }"#); #[test] fn test_fn_signature_for_impl() { let (desc, param) = get_signature( -r#"struct F; impl F { pub fn new() { F{}} } -fn bar() {let _ : F = F::new(<|>);}"#); + r#"struct F; impl F { pub fn new() { F{}} } +fn bar() {let _ : F = F::new(<|>);}"#, + ); assert_eq!(desc.name, "new".to_string()); assert_eq!(desc.params, Vec::::new()); @@ -197,7 +181,7 @@ fn bar() {let _ : F = F::new(<|>);}"#); #[test] fn test_fn_signature_for_method_self() { let (desc, param) = get_signature( -r#"struct F; + r#"struct F; impl F { pub fn new() -> F{ F{} @@ -209,7 +193,8 @@ impl F { fn bar() { let f : F = F::new(); f.do_it(<|>); -}"#); +}"#, + ); assert_eq!(desc.name, "do_it".to_string()); assert_eq!(desc.params, vec!["&self".to_string()]); @@ -220,7 +205,7 @@ fn bar() { #[test] fn test_fn_signature_for_method_with_arg() { let (desc, param) = get_signature( -r#"struct F; + r#"struct F; impl F { pub fn new() -> F{ F{} @@ -232,7 +217,8 @@ impl F { fn bar() { let f : F = F::new(); f.do_it(<|>); -}"#); +}"#, + ); assert_eq!(desc.name, "do_it".to_string()); assert_eq!(desc.params, vec!["&self".to_string(), "x".to_string()]); diff --git a/crates/ra_cli/src/main.rs b/crates/ra_cli/src/main.rs index 11605cfd86c..239d846b323 100644 --- a/crates/ra_cli/src/main.rs +++ b/crates/ra_cli/src/main.rs @@ -2,19 +2,17 @@ extern crate clap; #[macro_use] extern crate failure; extern crate join_to_string; -extern crate ra_syntax; extern crate ra_editor; +extern crate ra_syntax; extern crate tools; -use std::{ - fs, io::Read, path::Path, - time::Instant -}; +use std::{fs, io::Read, path::Path, time::Instant}; + use clap::{App, Arg, SubCommand}; use join_to_string::join; +use ra_editor::{extend_selection, file_structure, syntax_tree}; +use ra_syntax::{File, TextRange}; use tools::collect_tests; -use ra_syntax::{TextRange, File}; -use ra_editor::{syntax_tree, file_structure, extend_selection}; type Result = ::std::result::Result; @@ -36,14 +34,12 @@ fn main() -> Result<()> { .takes_value(true), ), ) - .subcommand( - SubCommand::with_name("parse") - .arg(Arg::with_name("no-dump").long("--no-dump")) - ) + .subcommand(SubCommand::with_name("parse").arg(Arg::with_name("no-dump").long("--no-dump"))) .subcommand(SubCommand::with_name("symbols")) - .subcommand(SubCommand::with_name("extend-selection") - .arg(Arg::with_name("start")) - .arg(Arg::with_name("end")) + .subcommand( + SubCommand::with_name("extend-selection") + .arg(Arg::with_name("start")) + .arg(Arg::with_name("end")), ) .get_matches(); match matches.subcommand() { @@ -116,7 +112,8 @@ fn selections(file: &File, start: u32, end: u32) -> String { ranges.push(r); cur = extend_selection(&file, r); } - let ranges = ranges.iter() + let ranges = ranges + .iter() .map(|r| (1 + u32::from(r.start()), 1 + u32::from(r.end()))) .map(|(s, e)| format!("({} {})", s, e)); join(ranges) diff --git a/crates/ra_editor/src/code_actions.rs b/crates/ra_editor/src/code_actions.rs index 7b0a48c81a3..cadcd27207a 100644 --- a/crates/ra_editor/src/code_actions.rs +++ b/crates/ra_editor/src/code_actions.rs @@ -1,17 +1,14 @@ use join_to_string::join; use ra_syntax::{ - File, TextUnit, TextRange, Direction, - ast::{self, AstNode, AttrsOwner, TypeParamsOwner, NameOwner}, + algo::{find_covering_node, find_leaf_at_offset}, + ast::{self, AstNode, AttrsOwner, NameOwner, TypeParamsOwner}, + Direction, File, SyntaxKind::{COMMA, WHITESPACE}, - SyntaxNodeRef, - algo::{ - find_leaf_at_offset, - find_covering_node, - }, + SyntaxNodeRef, TextRange, TextUnit, }; -use crate::{EditBuilder, Edit, find_node_at_offset}; +use crate::{find_node_at_offset, Edit, EditBuilder}; #[derive(Debug)] pub struct LocalEdit { @@ -52,9 +49,7 @@ pub fn add_derive<'a>(file: &'a File, offset: TextUnit) -> Option { - tt.syntax().range().end() - TextUnit::of_char(')') - } + Some(tt) => tt.syntax().range().end() - TextUnit::of_char(')'), }; LocalEdit { edit: edit.finish(), @@ -74,14 +69,19 @@ pub fn add_impl<'a>(file: &'a File, offset: TextUnit) -> Option let mut buf = String::new(); buf.push_str("\n\nimpl"); if let Some(type_params) = type_params { - type_params.syntax().text() - .push_to(&mut buf); + type_params.syntax().text().push_to(&mut buf); } buf.push_str(" "); buf.push_str(name.text().as_str()); if let Some(type_params) = type_params { - let lifetime_params = type_params.lifetime_params().filter_map(|it| it.lifetime()).map(|it| it.text()); - let type_params = type_params.type_params().filter_map(|it| it.name()).map(|it| it.text()); + let lifetime_params = type_params + .lifetime_params() + .filter_map(|it| it.lifetime()) + .map(|it| it.text()); + let type_params = type_params + .type_params() + .filter_map(|it| it.name()) + .map(|it| it.text()); join(lifetime_params.chain(type_params)) .surround_with("<", ">") .to_buf(&mut buf); @@ -97,10 +97,17 @@ pub fn add_impl<'a>(file: &'a File, offset: TextUnit) -> Option }) } -pub fn introduce_variable<'a>(file: &'a File, range: TextRange) -> Option LocalEdit + 'a> { +pub fn introduce_variable<'a>( + file: &'a File, + range: TextRange, +) -> Option LocalEdit + 'a> { let node = find_covering_node(file.syntax(), range); let expr = node.ancestors().filter_map(ast::Expr::cast).next()?; - let anchor_stmt = expr.syntax().ancestors().filter_map(ast::Stmt::cast).next()?; + let anchor_stmt = expr + .syntax() + .ancestors() + .filter_map(ast::Stmt::cast) + .next()?; let indent = anchor_stmt.syntax().prev_sibling()?; if indent.kind() != WHITESPACE { return None; @@ -191,7 +198,8 @@ mod tests { " fn foo() { foo(<|>1 + 1<|>); -}", " +}", + " fn foo() { let <|>var_name = 1 + 1; foo(var_name); @@ -201,11 +209,12 @@ fn foo() { } #[test] fn test_intrdoduce_var_expr_stmt() { -check_action_range( + check_action_range( " fn foo() { <|>1 + 1<|>; -}", " +}", + " fn foo() { let <|>var_name = 1 + 1; }", diff --git a/crates/ra_editor/src/completion.rs b/crates/ra_editor/src/completion.rs index b6095dca9c5..86ef46ebd94 100644 --- a/crates/ra_editor/src/completion.rs +++ b/crates/ra_editor/src/completion.rs @@ -1,17 +1,18 @@ use rustc_hash::{FxHashMap, FxHashSet}; use ra_syntax::{ - File, TextUnit, AstNode, SyntaxNodeRef, SyntaxKind::*, + algo::visit::{visitor, visitor_ctx, Visitor, VisitorCtx}, ast::{self, LoopBodyOwner, ModuleItemOwner}, - algo::{ - visit::{visitor, Visitor, visitor_ctx, VisitorCtx}, - }, text_utils::is_subrange, + AstNode, File, + SyntaxKind::*, + SyntaxNodeRef, TextUnit, }; use crate::{ - AtomEdit, find_node_at_offset, + find_node_at_offset, scope::{FnScopes, ModuleScope}, + AtomEdit, }; #[derive(Debug)] @@ -21,7 +22,7 @@ pub struct CompletionItem { /// What string is used for filtering, defaults to label pub lookup: Option, /// What is inserted, defaults to label - pub snippet: Option + pub snippet: Option, } pub fn scope_completion(file: &File, offset: TextUnit) -> Option> { @@ -40,7 +41,12 @@ pub fn scope_completion(file: &File, offset: TextUnit) -> Option complete_mod_item_snippets(&mut res), _ => (), @@ -68,21 +74,23 @@ fn complete_name_ref(file: &File, name_ref: ast::NameRef, acc: &mut Vec(|it| Some(it.items())) .visit::(|it| Some(it.item_list()?.items())) - .accept(node) { + .accept(node) + { if let Some(items) = items { let scope = ModuleScope::new(items); acc.extend( - scope.entries().iter() + scope + .entries() + .iter() .filter(|entry| entry.syntax() != name_ref.syntax()) .map(|entry| CompletionItem { label: entry.name().to_string(), lookup: None, snippet: None, - }) + }), ); } break; - } else if !visited_fn { if let Some(fn_def) = ast::FnDef::cast(node) { visited_fn = true; @@ -103,26 +111,34 @@ fn param_completions(ctx: SyntaxNodeRef, acc: &mut Vec) { .visit::(process) .accept(node); } - params.into_iter() + params + .into_iter() .filter_map(|(label, (count, param))| { let lookup = param.pat()?.syntax().text().to_string(); - if count < 2 { None } else { Some((label, lookup)) } + if count < 2 { + None + } else { + Some((label, lookup)) + } }) .for_each(|(label, lookup)| { acc.push(CompletionItem { - label, lookup: Some(lookup), snippet: None + label, + lookup: Some(lookup), + snippet: None, }) }); - fn process<'a, N: ast::FnDefOwner<'a>>(node: N, params: &mut FxHashMap)>) { + fn process<'a, N: ast::FnDefOwner<'a>>( + node: N, + params: &mut FxHashMap)>, + ) { node.functions() .filter_map(|it| it.param_list()) .flat_map(|it| it.params()) .for_each(|param| { let text = param.syntax().text().to_string(); - params.entry(text) - .or_insert((0, param)) - .0 += 1; + params.entry(text).or_insert((0, param)).0 += 1; }) } } @@ -134,8 +150,12 @@ fn is_node<'a, N: AstNode<'a>>(node: SyntaxNodeRef<'a>) -> bool { } } - -fn complete_expr_keywords(file: &File, fn_def: ast::FnDef, name_ref: ast::NameRef, acc: &mut Vec) { +fn complete_expr_keywords( + file: &File, + fn_def: ast::FnDef, + name_ref: ast::NameRef, + acc: &mut Vec, +) { acc.push(keyword("if", "if $0 {}")); acc.push(keyword("match", "match $0 {}")); acc.push(keyword("while", "while $0 {}")); @@ -186,9 +206,14 @@ fn complete_return(fn_def: ast::FnDef, name_ref: ast::NameRef) -> Option false, - Some(expr_stmt) => expr_stmt.syntax().range() == name_ref.syntax().range() + Some(expr_stmt) => expr_stmt.syntax().range() == name_ref.syntax().range(), }; let snip = match (is_stmt, fn_def.ret_type().is_some()) { (true, true) => "return $0;", @@ -209,39 +234,37 @@ fn keyword(kw: &str, snip: &str) -> CompletionItem { fn complete_expr_snippets(acc: &mut Vec) { acc.push(CompletionItem { - label: "pd".to_string(), - lookup: None, - snippet: Some("eprintln!(\"$0 = {:?}\", $0);".to_string()), - } - ); + label: "pd".to_string(), + lookup: None, + snippet: Some("eprintln!(\"$0 = {:?}\", $0);".to_string()), + }); acc.push(CompletionItem { - label: "ppd".to_string(), - lookup: None, - snippet: Some("eprintln!(\"$0 = {:#?}\", $0);".to_string()), - } - ); + label: "ppd".to_string(), + lookup: None, + snippet: Some("eprintln!(\"$0 = {:#?}\", $0);".to_string()), + }); } fn complete_mod_item_snippets(acc: &mut Vec) { acc.push(CompletionItem { - label: "tfn".to_string(), - lookup: None, - snippet: Some("#[test]\nfn $1() {\n $0\n}".to_string()), - } - ); + label: "tfn".to_string(), + lookup: None, + snippet: Some("#[test]\nfn $1() {\n $0\n}".to_string()), + }); } fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec) { let mut shadowed = FxHashSet::default(); acc.extend( - scopes.scope_chain(name_ref.syntax()) + scopes + .scope_chain(name_ref.syntax()) .flat_map(|scope| scopes.entries(scope).iter()) .filter(|entry| shadowed.insert(entry.name())) .map(|entry| CompletionItem { label: entry.name().to_string(), lookup: None, snippet: None, - }) + }), ); if scopes.self_param.is_some() { acc.push(CompletionItem { @@ -281,20 +304,24 @@ mod tests { #[test] fn test_completion_let_scope() { - check_scope_completion(r" + check_scope_completion( + r" fn quux(x: i32) { let y = 92; 1 + <|>; let z = (); } - ", r#"[CompletionItem { label: "y", lookup: None, snippet: None }, + ", + r#"[CompletionItem { label: "y", lookup: None, snippet: None }, CompletionItem { label: "x", lookup: None, snippet: None }, - CompletionItem { label: "quux", lookup: None, snippet: None }]"#); + CompletionItem { label: "quux", lookup: None, snippet: None }]"#, + ); } #[test] fn test_completion_if_let_scope() { - check_scope_completion(r" + check_scope_completion( + r" fn quux() { if let Some(x) = foo() { let y = 92; @@ -304,67 +331,85 @@ mod tests { 1 + <|> } } - ", r#"[CompletionItem { label: "b", lookup: None, snippet: None }, + ", + r#"[CompletionItem { label: "b", lookup: None, snippet: None }, CompletionItem { label: "a", lookup: None, snippet: None }, - CompletionItem { label: "quux", lookup: None, snippet: None }]"#); + CompletionItem { label: "quux", lookup: None, snippet: None }]"#, + ); } #[test] fn test_completion_for_scope() { - check_scope_completion(r" + check_scope_completion( + r" fn quux() { for x in &[1, 2, 3] { <|> } } - ", r#"[CompletionItem { label: "x", lookup: None, snippet: None }, - CompletionItem { label: "quux", lookup: None, snippet: None }]"#); + ", + r#"[CompletionItem { label: "x", lookup: None, snippet: None }, + CompletionItem { label: "quux", lookup: None, snippet: None }]"#, + ); } #[test] fn test_completion_mod_scope() { - check_scope_completion(r" + check_scope_completion( + r" struct Foo; enum Baz {} fn quux() { <|> } - ", r#"[CompletionItem { label: "Foo", lookup: None, snippet: None }, + ", + r#"[CompletionItem { label: "Foo", lookup: None, snippet: None }, CompletionItem { label: "Baz", lookup: None, snippet: None }, - CompletionItem { label: "quux", lookup: None, snippet: None }]"#); + CompletionItem { label: "quux", lookup: None, snippet: None }]"#, + ); } #[test] fn test_completion_mod_scope_no_self_use() { - check_scope_completion(r" + check_scope_completion( + r" use foo<|>; - ", r#"[]"#); + ", + r#"[]"#, + ); } #[test] fn test_completion_mod_scope_nested() { - check_scope_completion(r" + check_scope_completion( + r" struct Foo; mod m { struct Bar; fn quux() { <|> } } - ", r#"[CompletionItem { label: "Bar", lookup: None, snippet: None }, - CompletionItem { label: "quux", lookup: None, snippet: None }]"#); + ", + r#"[CompletionItem { label: "Bar", lookup: None, snippet: None }, + CompletionItem { label: "quux", lookup: None, snippet: None }]"#, + ); } #[test] fn test_complete_type() { - check_scope_completion(r" + check_scope_completion( + r" struct Foo; fn x() -> <|> - ", r#"[CompletionItem { label: "Foo", lookup: None, snippet: None }, - CompletionItem { label: "x", lookup: None, snippet: None }]"#) + ", + r#"[CompletionItem { label: "Foo", lookup: None, snippet: None }, + CompletionItem { label: "x", lookup: None, snippet: None }]"#, + ) } #[test] fn test_complete_shadowing() { - check_scope_completion(r" + check_scope_completion( + r" fn foo() -> { let bar = 92; { @@ -372,15 +417,20 @@ mod tests { <|> } } - ", r#"[CompletionItem { label: "bar", lookup: None, snippet: None }, - CompletionItem { label: "foo", lookup: None, snippet: None }]"#) + ", + r#"[CompletionItem { label: "bar", lookup: None, snippet: None }, + CompletionItem { label: "foo", lookup: None, snippet: None }]"#, + ) } #[test] fn test_complete_self() { - check_scope_completion(r" + check_scope_completion( + r" impl S { fn foo(&self) { <|> } } - ", r#"[CompletionItem { label: "self", lookup: None, snippet: None }]"#) + ", + r#"[CompletionItem { label: "self", lookup: None, snippet: None }]"#, + ) } #[test] diff --git a/crates/ra_editor/src/edit.rs b/crates/ra_editor/src/edit.rs index 46e6873197b..c3149ec541c 100644 --- a/crates/ra_editor/src/edit.rs +++ b/crates/ra_editor/src/edit.rs @@ -1,8 +1,5 @@ use crate::{TextRange, TextUnit}; -use ra_syntax::{ - AtomEdit, - text_utils::contains_offset_nonstrict, -}; +use ra_syntax::{text_utils::contains_offset_nonstrict, AtomEdit}; #[derive(Debug, Clone)] pub struct Edit { @@ -11,7 +8,7 @@ pub struct Edit { #[derive(Debug)] pub struct EditBuilder { - atoms: Vec + atoms: Vec, } impl EditBuilder { @@ -36,7 +33,9 @@ impl EditBuilder { Edit { atoms } } pub fn invalidates_offset(&self, offset: TextUnit) -> bool { - self.atoms.iter().any(|atom| contains_offset_nonstrict(atom.delete, offset)) + self.atoms + .iter() + .any(|atom| contains_offset_nonstrict(atom.delete, offset)) } } @@ -74,7 +73,7 @@ impl Edit { break; } if offset < atom.delete.end() { - return None + return None; } res += TextUnit::of_str(&atom.insert); res -= atom.delete.len(); diff --git a/crates/ra_editor/src/extend_selection.rs b/crates/ra_editor/src/extend_selection.rs index ab03a717ed4..9ee1df28108 100644 --- a/crates/ra_editor/src/extend_selection.rs +++ b/crates/ra_editor/src/extend_selection.rs @@ -1,7 +1,8 @@ use ra_syntax::{ - File, TextRange, SyntaxNodeRef, TextUnit, Direction, + algo::{find_covering_node, find_leaf_at_offset, LeafAtOffset}, + Direction, File, SyntaxKind::*, - algo::{find_leaf_at_offset, LeafAtOffset, find_covering_node}, + SyntaxNodeRef, TextRange, TextUnit, }; pub fn extend_selection(file: &File, range: TextRange) -> Option { @@ -20,11 +21,11 @@ pub(crate) fn extend(root: SyntaxNodeRef, range: TextRange) -> Option LeafAtOffset::None => return None, LeafAtOffset::Single(l) => { if l.kind() == COMMENT { - extend_single_word_in_comment(l, offset).unwrap_or_else(||l.range()) + extend_single_word_in_comment(l, offset).unwrap_or_else(|| l.range()) } else { l.range() } - }, + } LeafAtOffset::Between(l, r) => pick_best(l, r).range(), }; return Some(leaf_range); @@ -66,7 +67,7 @@ fn extend_ws(root: SyntaxNodeRef, ws: SyntaxNodeRef, offset: TextUnit) -> TextRa if let Some(node) = ws.next_sibling() { let start = match ws_prefix.rfind('\n') { Some(idx) => ws.range().start() + TextUnit::from((idx + 1) as u32), - None => node.range().start() + None => node.range().start(), }; let end = if root.text().char_at(node.range().end()) == Some('\n') { node.range().end() + TextUnit::of_char('\n') @@ -94,10 +95,7 @@ fn extend_comments(node: SyntaxNodeRef) -> Option { let prev = adj_comments(node, Direction::Prev); let next = adj_comments(node, Direction::Next); if prev != next { - Some(TextRange::from_to( - prev.range().start(), - next.range().end(), - )) + Some(TextRange::from_to(prev.range().start(), next.range().end())) } else { None } @@ -109,7 +107,7 @@ fn adj_comments(node: SyntaxNodeRef, dir: Direction) -> SyntaxNodeRef { match node.kind() { COMMENT => res = node, WHITESPACE if !node.leaf_text().unwrap().as_str().contains("\n\n") => (), - _ => break + _ => break, } } res @@ -125,8 +123,7 @@ mod tests { let file = File::parse(&before); let mut range = TextRange::offset_len(cursor, 0.into()); for &after in afters { - range = extend_selection(&file, range) - .unwrap(); + range = extend_selection(&file, range).unwrap(); let actual = &before[range]; assert_eq!(after, actual); } @@ -134,10 +131,7 @@ mod tests { #[test] fn test_extend_selection_arith() { - do_check( - r#"fn foo() { <|>1 + 1 }"#, - &["1", "1 + 1", "{ 1 + 1 }"], - ); + do_check(r#"fn foo() { <|>1 + 1 }"#, &["1", "1 + 1", "{ 1 + 1 }"]); } #[test] @@ -149,7 +143,7 @@ impl S { } }"#, - &[" fn foo() {\n\n }\n"] + &[" fn foo() {\n\n }\n"], ); } @@ -165,7 +159,11 @@ struct B { <|> } "#, - &["\n \n", "{\n \n}", "/// bla\n/// bla\nstruct B {\n \n}"] + &[ + "\n \n", + "{\n \n}", + "/// bla\n/// bla\nstruct B {\n \n}", + ], ) } @@ -181,7 +179,7 @@ fn bar(){} // fn foo(){} "#, - &["// 1 + 1", "// fn foo() {\n// 1 + 1\n// }"] + &["// 1 + 1", "// fn foo() {\n// 1 + 1\n// }"], ); } @@ -191,42 +189,34 @@ fn bar(){} r#" fn main() { foo<|>+bar;} "#, - &["foo", "foo+bar"] + &["foo", "foo+bar"], ); do_check( r#" fn main() { foo+<|>bar;} "#, - &["bar", "foo+bar"] + &["bar", "foo+bar"], ); } #[test] fn test_extend_selection_prefer_lifetimes() { - do_check( - r#"fn foo<<|>'a>() {}"#, - &["'a", "<'a>"] - ); - do_check( - r#"fn foo<'a<|>>() {}"#, - &["'a", "<'a>"] - ); + do_check(r#"fn foo<<|>'a>() {}"#, &["'a", "<'a>"]); + do_check(r#"fn foo<'a<|>>() {}"#, &["'a", "<'a>"]); } #[test] fn test_extend_selection_select_first_word() { + do_check(r#"// foo bar b<|>az quxx"#, &["baz", "// foo bar baz quxx"]); do_check( - r#"// foo bar b<|>az quxx"#, - &["baz", "// foo bar baz quxx"] - ); - do_check(r#" + r#" impl S { fn foo() { // hel<|>lo world } } "#, - &["hello", "// hello world"] + &["hello", "// hello world"], ); } } diff --git a/crates/ra_editor/src/folding_ranges.rs b/crates/ra_editor/src/folding_ranges.rs index a1699d44940..e5bc0c4ee5c 100644 --- a/crates/ra_editor/src/folding_ranges.rs +++ b/crates/ra_editor/src/folding_ranges.rs @@ -1,11 +1,9 @@ use rustc_hash::FxHashSet; use ra_syntax::{ - ast, - AstNode, - File, TextRange, SyntaxNodeRef, + ast, AstNode, Direction, File, SyntaxKind::{self, *}, - Direction, + SyntaxNodeRef, TextRange, }; #[derive(Debug, PartialEq, Eq)] @@ -28,7 +26,10 @@ pub fn folding_ranges(file: &File) -> Vec { // Fold items that span multiple lines if let Some(kind) = fold_kind(node.kind()) { if has_newline(node) { - res.push(Fold { range: node.range(), kind }); + res.push(Fold { + range: node.range(), + kind, + }); } } @@ -37,8 +38,12 @@ pub fn folding_ranges(file: &File) -> Vec { continue; } if node.kind() == COMMENT { - contiguous_range_for_comment(node, &mut visited_comments) - .map(|range| res.push(Fold { range, kind: FoldKind::Comment })); + contiguous_range_for_comment(node, &mut visited_comments).map(|range| { + res.push(Fold { + range, + kind: FoldKind::Comment, + }) + }); } } @@ -49,13 +54,11 @@ fn fold_kind(kind: SyntaxKind) -> Option { match kind { COMMENT => Some(FoldKind::Comment), USE_ITEM => Some(FoldKind::Imports), - _ => None + _ => None, } } -fn has_newline( - node: SyntaxNodeRef, -) -> bool { +fn has_newline(node: SyntaxNodeRef) -> bool { for descendant in node.descendants() { if let Some(ws) = ast::Whitespace::cast(descendant) { if ws.has_newlines() { @@ -100,9 +103,7 @@ fn contiguous_range_for_comment<'a>( // The comment group ends because either: // * An element of a different kind was reached // * A comment of a different flavor was reached - _ => { - break - } + _ => break, } } @@ -128,7 +129,11 @@ mod tests { let folds = folding_ranges(&file); assert_eq!(folds.len(), ranges.len()); - for ((fold, range), fold_kind) in folds.into_iter().zip(ranges.into_iter()).zip(fold_kinds.into_iter()) { + for ((fold, range), fold_kind) in folds + .into_iter() + .zip(ranges.into_iter()) + .zip(fold_kinds.into_iter()) + { assert_eq!(fold.range.start(), range.start()); assert_eq!(fold.range.end(), range.end()); assert_eq!(&fold.kind, fold_kind); @@ -181,5 +186,4 @@ fn main() { do_check(text, folds); } - } diff --git a/crates/ra_editor/src/lib.rs b/crates/ra_editor/src/lib.rs index bd61fd1914f..417080d90bb 100644 --- a/crates/ra_editor/src/lib.rs +++ b/crates/ra_editor/src/lib.rs @@ -1,44 +1,41 @@ -extern crate ra_syntax; -extern crate superslice; extern crate itertools; extern crate join_to_string; +extern crate ra_syntax; extern crate rustc_hash; +extern crate superslice; #[cfg(test)] #[macro_use] extern crate test_utils as _test_utils; -mod extend_selection; -mod symbols; -mod line_index; -mod edit; -mod folding_ranges; mod code_actions; -mod typing; mod completion; +mod edit; +mod extend_selection; +mod folding_ranges; +mod line_index; mod scope; +mod symbols; #[cfg(test)] mod test_utils; +mod typing; -use ra_syntax::{ - File, TextUnit, TextRange, SmolStr, SyntaxNodeRef, - ast::{self, AstNode, NameOwner}, - algo::find_leaf_at_offset, - SyntaxKind::{self, *}, +pub use self::{ + code_actions::{add_derive, add_impl, flip_comma, introduce_variable, LocalEdit}, + completion::{scope_completion, CompletionItem}, + edit::{Edit, EditBuilder}, + extend_selection::extend_selection, + folding_ranges::{folding_ranges, Fold, FoldKind}, + line_index::{LineCol, LineIndex}, + symbols::{file_structure, file_symbols, FileSymbol, StructureNode}, + typing::{join_lines, on_enter, on_eq_typed}, }; pub use ra_syntax::AtomEdit; -pub use self::{ - line_index::{LineIndex, LineCol}, - extend_selection::extend_selection, - symbols::{StructureNode, file_structure, FileSymbol, file_symbols}, - edit::{EditBuilder, Edit}, - code_actions::{ - LocalEdit, - flip_comma, add_derive, add_impl, - introduce_variable, - }, - typing::{join_lines, on_eq_typed, on_enter}, - completion::{scope_completion, CompletionItem}, - folding_ranges::{Fold, FoldKind, folding_ranges} +use ra_syntax::{ + algo::find_leaf_at_offset, + ast::{self, AstNode, NameOwner}, + File, SmolStr, + SyntaxKind::{self, *}, + SyntaxNodeRef, TextRange, TextUnit, }; #[derive(Debug)] @@ -67,10 +64,7 @@ pub enum RunnableKind { pub fn matching_brace(file: &File, offset: TextUnit) -> Option { const BRACES: &[SyntaxKind] = &[ - L_CURLY, R_CURLY, - L_BRACK, R_BRACK, - L_PAREN, R_PAREN, - L_ANGLE, R_ANGLE, + L_CURLY, R_CURLY, L_BRACK, R_BRACK, L_PAREN, R_PAREN, L_ANGLE, R_ANGLE, ]; let (brace_node, brace_idx) = find_leaf_at_offset(file.syntax(), offset) .filter_map(|node| { @@ -80,7 +74,8 @@ pub fn matching_brace(file: &File, offset: TextUnit) -> Option { .next()?; let parent = brace_node.parent()?; let matching_kind = BRACES[brace_idx ^ 1]; - let matching_node = parent.children() + let matching_node = parent + .children() .find(|node| node.kind() == matching_kind)?; Some(matching_node.range().start()) } @@ -108,10 +103,13 @@ pub fn highlight(file: &File) -> Vec { } pub fn diagnostics(file: &File) -> Vec { - file.errors().into_iter().map(|err| Diagnostic { - range: TextRange::offset_len(err.offset, 1.into()), - msg: "Syntax Error: ".to_string() + &err.msg, - }).collect() + file.errors() + .into_iter() + .map(|err| Diagnostic { + range: TextRange::offset_len(err.offset, 1.into()), + msg: "Syntax Error: ".to_string() + &err.msg, + }) + .collect() } pub fn syntax_tree(file: &File) -> String { @@ -119,7 +117,8 @@ pub fn syntax_tree(file: &File) -> String { } pub fn runnables(file: &File) -> Vec { - file.syntax().descendants() + file.syntax() + .descendants() .filter_map(ast::FnDef::cast) .filter_map(|f| { let name = f.name()?.text(); @@ -127,7 +126,7 @@ pub fn runnables(file: &File) -> Vec { RunnableKind::Bin } else if f.has_atom_attr("test") { RunnableKind::Test { - name: name.to_string() + name: name.to_string(), } } else { return None; @@ -145,15 +144,18 @@ pub fn find_node_at_offset<'a, N: AstNode<'a>>( offset: TextUnit, ) -> Option { let leaves = find_leaf_at_offset(syntax, offset); - let leaf = leaves.clone() + let leaf = leaves + .clone() .find(|leaf| !leaf.kind().is_trivia()) .or_else(|| leaves.right_biased())?; - leaf.ancestors() - .filter_map(N::cast) - .next() + leaf.ancestors().filter_map(N::cast).next() } -pub fn resolve_local_name(file: &File, offset: TextUnit, name_ref: ast::NameRef) -> Option<(SmolStr, TextRange)> { +pub fn resolve_local_name( + file: &File, + offset: TextUnit, + name_ref: ast::NameRef, +) -> Option<(SmolStr, TextRange)> { let fn_def = find_node_at_offset::(file.syntax(), offset)?; let scopes = scope::FnScopes::new(fn_def); let scope_entry = scope::resolve_local_name(name_ref, &scopes)?; @@ -164,15 +166,17 @@ pub fn resolve_local_name(file: &File, offset: TextUnit, name_ref: ast::NameRef) #[cfg(test)] mod tests { use super::*; - use crate::test_utils::{assert_eq_dbg, extract_offset, add_cursor}; + use crate::test_utils::{add_cursor, assert_eq_dbg, extract_offset}; #[test] fn test_highlighting() { - let file = File::parse(r#" + let file = File::parse( + r#" // comment fn main() {} println!("Hello, {}!", 92); -"#); +"#, + ); let hls = highlight(&file); assert_eq_dbg( r#"[HighlightedRange { range: [1; 11), tag: "comment" }, @@ -187,7 +191,8 @@ fn main() {} #[test] fn test_runnables() { - let file = File::parse(r#" + let file = File::parse( + r#" fn main() {} #[test] @@ -196,7 +201,8 @@ fn test_foo() {} #[test] #[ignore] fn test_foo() {} -"#); +"#, + ); let runnables = runnables(&file); assert_eq_dbg( r#"[Runnable { range: [1; 13), kind: Bin }, @@ -219,9 +225,6 @@ fn test_foo() {} assert_eq_text!(after, &actual); } - do_check( - "struct Foo { a: i32, }<|>", - "struct Foo <|>{ a: i32, }", - ); + do_check("struct Foo { a: i32, }<|>", "struct Foo <|>{ a: i32, }"); } } diff --git a/crates/ra_editor/src/line_index.rs b/crates/ra_editor/src/line_index.rs index 95d64b8a807..da0f2a7f794 100644 --- a/crates/ra_editor/src/line_index.rs +++ b/crates/ra_editor/src/line_index.rs @@ -1,5 +1,5 @@ -use superslice::Ext; use crate::TextUnit; +use superslice::Ext; #[derive(Clone, Debug, Hash, PartialEq, Eq)] pub struct LineIndex { @@ -29,7 +29,10 @@ impl LineIndex { let line = self.newlines.upper_bound(&offset) - 1; let line_start_offset = self.newlines[line]; let col = offset - line_start_offset; - return LineCol { line: line as u32, col }; + return LineCol { + line: line as u32, + col, + }; } pub fn offset(&self, line_col: LineCol) -> TextUnit { @@ -42,21 +45,105 @@ impl LineIndex { fn test_line_index() { let text = "hello\nworld"; let index = LineIndex::new(text); - assert_eq!(index.line_col(0.into()), LineCol { line: 0, col: 0.into() }); - assert_eq!(index.line_col(1.into()), LineCol { line: 0, col: 1.into() }); - assert_eq!(index.line_col(5.into()), LineCol { line: 0, col: 5.into() }); - assert_eq!(index.line_col(6.into()), LineCol { line: 1, col: 0.into() }); - assert_eq!(index.line_col(7.into()), LineCol { line: 1, col: 1.into() }); - assert_eq!(index.line_col(8.into()), LineCol { line: 1, col: 2.into() }); - assert_eq!(index.line_col(10.into()), LineCol { line: 1, col: 4.into() }); - assert_eq!(index.line_col(11.into()), LineCol { line: 1, col: 5.into() }); - assert_eq!(index.line_col(12.into()), LineCol { line: 1, col: 6.into() }); + assert_eq!( + index.line_col(0.into()), + LineCol { + line: 0, + col: 0.into() + } + ); + assert_eq!( + index.line_col(1.into()), + LineCol { + line: 0, + col: 1.into() + } + ); + assert_eq!( + index.line_col(5.into()), + LineCol { + line: 0, + col: 5.into() + } + ); + assert_eq!( + index.line_col(6.into()), + LineCol { + line: 1, + col: 0.into() + } + ); + assert_eq!( + index.line_col(7.into()), + LineCol { + line: 1, + col: 1.into() + } + ); + assert_eq!( + index.line_col(8.into()), + LineCol { + line: 1, + col: 2.into() + } + ); + assert_eq!( + index.line_col(10.into()), + LineCol { + line: 1, + col: 4.into() + } + ); + assert_eq!( + index.line_col(11.into()), + LineCol { + line: 1, + col: 5.into() + } + ); + assert_eq!( + index.line_col(12.into()), + LineCol { + line: 1, + col: 6.into() + } + ); let text = "\nhello\nworld"; let index = LineIndex::new(text); - assert_eq!(index.line_col(0.into()), LineCol { line: 0, col: 0.into() }); - assert_eq!(index.line_col(1.into()), LineCol { line: 1, col: 0.into() }); - assert_eq!(index.line_col(2.into()), LineCol { line: 1, col: 1.into() }); - assert_eq!(index.line_col(6.into()), LineCol { line: 1, col: 5.into() }); - assert_eq!(index.line_col(7.into()), LineCol { line: 2, col: 0.into() }); + assert_eq!( + index.line_col(0.into()), + LineCol { + line: 0, + col: 0.into() + } + ); + assert_eq!( + index.line_col(1.into()), + LineCol { + line: 1, + col: 0.into() + } + ); + assert_eq!( + index.line_col(2.into()), + LineCol { + line: 1, + col: 1.into() + } + ); + assert_eq!( + index.line_col(6.into()), + LineCol { + line: 1, + col: 5.into() + } + ); + assert_eq!( + index.line_col(7.into()), + LineCol { + line: 2, + col: 0.into() + } + ); } diff --git a/crates/ra_editor/src/scope/fn_scope.rs b/crates/ra_editor/src/scope/fn_scope.rs index 99d698b607f..9088e5a608b 100644 --- a/crates/ra_editor/src/scope/fn_scope.rs +++ b/crates/ra_editor/src/scope/fn_scope.rs @@ -1,10 +1,11 @@ use std::fmt; + use rustc_hash::FxHashMap; use ra_syntax::{ - SyntaxNodeRef, SyntaxNode, SmolStr, AstNode, - ast::{self, NameOwner, LoopBodyOwner, ArgListOwner}, - algo::{generate} + algo::generate, + ast::{self, ArgListOwner, LoopBodyOwner, NameOwner}, + AstNode, SmolStr, SyntaxNode, SyntaxNodeRef, }; type ScopeId = usize; @@ -19,11 +20,12 @@ pub struct FnScopes { impl FnScopes { pub fn new(fn_def: ast::FnDef) -> FnScopes { let mut scopes = FnScopes { - self_param: fn_def.param_list() + self_param: fn_def + .param_list() .and_then(|it| it.self_param()) .map(|it| it.syntax().owned()), scopes: Vec::new(), - scope_for: FxHashMap::default() + scope_for: FxHashMap::default(), }; let root = scopes.root_scope(); scopes.add_params_bindings(root, fn_def.param_list()); @@ -35,27 +37,38 @@ impl FnScopes { pub fn entries(&self, scope: ScopeId) -> &[ScopeEntry] { &self.scopes[scope].entries } - pub fn scope_chain<'a>(&'a self, node: SyntaxNodeRef) -> impl Iterator + 'a { - generate(self.scope_for(node), move |&scope| self.scopes[scope].parent) + pub fn scope_chain<'a>(&'a self, node: SyntaxNodeRef) -> impl Iterator + 'a { + generate(self.scope_for(node), move |&scope| { + self.scopes[scope].parent + }) } fn root_scope(&mut self) -> ScopeId { let res = self.scopes.len(); - self.scopes.push(ScopeData { parent: None, entries: vec![] }); + self.scopes.push(ScopeData { + parent: None, + entries: vec![], + }); res } fn new_scope(&mut self, parent: ScopeId) -> ScopeId { let res = self.scopes.len(); - self.scopes.push(ScopeData { parent: Some(parent), entries: vec![] }); + self.scopes.push(ScopeData { + parent: Some(parent), + entries: vec![], + }); res } fn add_bindings(&mut self, scope: ScopeId, pat: ast::Pat) { - let entries = pat.syntax().descendants() + let entries = pat + .syntax() + .descendants() .filter_map(ast::BindPat::cast) .filter_map(ScopeEntry::new); self.scopes[scope].entries.extend(entries); } fn add_params_bindings(&mut self, scope: ScopeId, params: Option) { - params.into_iter() + params + .into_iter() .flat_map(|it| it.params()) .filter_map(|it| it.pat()) .for_each(|it| self.add_bindings(scope, it)); @@ -71,34 +84,33 @@ impl FnScopes { } pub struct ScopeEntry { - syntax: SyntaxNode + syntax: SyntaxNode, } impl ScopeEntry { fn new(pat: ast::BindPat) -> Option { if pat.name().is_some() { - Some(ScopeEntry { syntax: pat.syntax().owned() }) + Some(ScopeEntry { + syntax: pat.syntax().owned(), + }) } else { None } } pub fn name(&self) -> SmolStr { - self.ast().name() - .unwrap() - .text() + self.ast().name().unwrap().text() } pub fn ast(&self) -> ast::BindPat { - ast::BindPat::cast(self.syntax.borrowed()) - .unwrap() + ast::BindPat::cast(self.syntax.borrowed()).unwrap() } } impl fmt::Debug for ScopeEntry { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ScopeEntry") - .field("name", &self.name()) - .field("syntax", &self.syntax) - .finish() + .field("name", &self.name()) + .field("syntax", &self.syntax) + .finish() } } @@ -132,16 +144,16 @@ fn compute_block_scopes(block: ast::Block, scopes: &mut FnScopes, mut scope: Sco fn compute_expr_scopes(expr: ast::Expr, scopes: &mut FnScopes, scope: ScopeId) { match expr { ast::Expr::IfExpr(e) => { - let cond_scope = e.condition().and_then(|cond| { - compute_cond_scopes(cond, scopes, scope) - }); + let cond_scope = e + .condition() + .and_then(|cond| compute_cond_scopes(cond, scopes, scope)); if let Some(block) = e.then_branch() { compute_block_scopes(block, scopes, cond_scope.unwrap_or(scope)); } if let Some(block) = e.else_branch() { compute_block_scopes(block, scopes, scope); } - }, + } ast::Expr::BlockExpr(e) => { if let Some(block) = e.block() { compute_block_scopes(block, scopes, scope); @@ -153,9 +165,9 @@ fn compute_expr_scopes(expr: ast::Expr, scopes: &mut FnScopes, scope: ScopeId) { } } ast::Expr::WhileExpr(e) => { - let cond_scope = e.condition().and_then(|cond| { - compute_cond_scopes(cond, scopes, scope) - }); + let cond_scope = e + .condition() + .and_then(|cond| compute_cond_scopes(cond, scopes, scope)); if let Some(block) = e.loop_body() { compute_block_scopes(block, scopes, cond_scope.unwrap_or(scope)); } @@ -201,25 +213,31 @@ fn compute_expr_scopes(expr: ast::Expr, scopes: &mut FnScopes, scope: ScopeId) { } } } - _ => { - expr.syntax().children() - .filter_map(ast::Expr::cast) - .for_each(|expr| compute_expr_scopes(expr, scopes, scope)) - } + _ => expr + .syntax() + .children() + .filter_map(ast::Expr::cast) + .for_each(|expr| compute_expr_scopes(expr, scopes, scope)), }; fn compute_call_scopes( receiver: Option, arg_list: Option, - scopes: &mut FnScopes, scope: ScopeId, + scopes: &mut FnScopes, + scope: ScopeId, ) { - arg_list.into_iter() + arg_list + .into_iter() .flat_map(|it| it.args()) .chain(receiver) .for_each(|expr| compute_expr_scopes(expr, scopes, scope)); } - fn compute_cond_scopes(cond: ast::Condition, scopes: &mut FnScopes, scope: ScopeId) -> Option { + fn compute_cond_scopes( + cond: ast::Condition, + scopes: &mut FnScopes, + scope: ScopeId, + ) -> Option { if let Some(expr) = cond.expr() { compute_expr_scopes(expr, scopes, scope); } @@ -236,14 +254,18 @@ fn compute_expr_scopes(expr: ast::Expr, scopes: &mut FnScopes, scope: ScopeId) { #[derive(Debug)] struct ScopeData { parent: Option, - entries: Vec + entries: Vec, } -pub fn resolve_local_name<'a>(name_ref: ast::NameRef, scopes: &'a FnScopes) -> Option<&'a ScopeEntry> { +pub fn resolve_local_name<'a>( + name_ref: ast::NameRef, + scopes: &'a FnScopes, +) -> Option<&'a ScopeEntry> { use rustc_hash::FxHashSet; let mut shadowed = FxHashSet::default(); - let ret = scopes.scope_chain(name_ref.syntax()) + let ret = scopes + .scope_chain(name_ref.syntax()) .flat_map(|scope| scopes.entries(scope).iter()) .filter(|entry| shadowed.insert(entry.name())) .filter(|entry| entry.name() == name_ref.text()) @@ -255,8 +277,8 @@ pub fn resolve_local_name<'a>(name_ref: ast::NameRef, scopes: &'a FnScopes) -> O #[cfg(test)] mod tests { use super::*; - use ra_syntax::File; use crate::{find_node_at_offset, test_utils::extract_offset}; + use ra_syntax::File; fn do_check(code: &str, expected: &[&str]) { let (off, code) = extract_offset(code); @@ -272,7 +294,8 @@ mod tests { let marker: ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap(); let fn_def: ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); let scopes = FnScopes::new(fn_def); - let actual = scopes.scope_chain(marker.syntax()) + let actual = scopes + .scope_chain(marker.syntax()) .flat_map(|scope| scopes.entries(scope)) .map(|it| it.name()) .collect::>(); @@ -281,7 +304,8 @@ mod tests { #[test] fn test_lambda_scope() { - do_check(r" + do_check( + r" fn quux(foo: i32) { let f = |bar, baz: i32| { <|> @@ -293,7 +317,8 @@ mod tests { #[test] fn test_call_scope() { - do_check(r" + do_check( + r" fn quux() { f(|x| <|> ); }", @@ -303,7 +328,8 @@ mod tests { #[test] fn test_metod_call_scope() { - do_check(r" + do_check( + r" fn quux() { z.f(|x| <|> ); }", @@ -313,7 +339,8 @@ mod tests { #[test] fn test_loop_scope() { - do_check(r" + do_check( + r" fn quux() { loop { let x = (); @@ -326,7 +353,8 @@ mod tests { #[test] fn test_match() { - do_check(r" + do_check( + r" fn quux() { match () { Some(x) => { @@ -340,7 +368,8 @@ mod tests { #[test] fn test_shadow_variable() { - do_check(r" + do_check( + r" fn foo(x: String) { let x : &str = &x<|>; }", @@ -356,14 +385,20 @@ mod tests { let scopes = FnScopes::new(fn_def); - let local_name = resolve_local_name(name_ref, &scopes).unwrap().ast().name().unwrap(); - let expected_name = find_node_at_offset::(file.syntax(), expected_offset.into()).unwrap(); + let local_name = resolve_local_name(name_ref, &scopes) + .unwrap() + .ast() + .name() + .unwrap(); + let expected_name = + find_node_at_offset::(file.syntax(), expected_offset.into()).unwrap(); assert_eq!(local_name.syntax().range(), expected_name.syntax().range()); } #[test] fn test_resolve_local_name() { - do_check_local_name(r#" + do_check_local_name( + r#" fn foo(x: i32, y: u32) { { let z = x * 2; @@ -372,25 +407,30 @@ mod tests { let t = x<|> * 3; } }"#, - 21); + 21, + ); } #[test] fn test_resolve_local_name_declaration() { - do_check_local_name(r#" + do_check_local_name( + r#" fn foo(x: String) { let x : &str = &x<|>; }"#, - 21); + 21, + ); } #[test] fn test_resolve_local_name_shadow() { - do_check_local_name(r" + do_check_local_name( + r" fn foo(x: String) { let x : &str = &x; x<|> }", - 46); + 46, + ); } } diff --git a/crates/ra_editor/src/scope/mod.rs b/crates/ra_editor/src/scope/mod.rs index 7d6d530f787..cc2d493926c 100644 --- a/crates/ra_editor/src/scope/mod.rs +++ b/crates/ra_editor/src/scope/mod.rs @@ -2,7 +2,6 @@ mod fn_scope; mod mod_scope; pub use self::{ - fn_scope::{FnScopes, resolve_local_name}, + fn_scope::{resolve_local_name, FnScopes}, mod_scope::ModuleScope, }; - diff --git a/crates/ra_editor/src/scope/mod_scope.rs b/crates/ra_editor/src/scope/mod_scope.rs index d2a3e7c5837..8d7e408f851 100644 --- a/crates/ra_editor/src/scope/mod_scope.rs +++ b/crates/ra_editor/src/scope/mod_scope.rs @@ -1,6 +1,6 @@ use ra_syntax::{ - AstNode, SyntaxNode, SyntaxNodeRef, SmolStr, ast::{self, AstChildren}, + AstNode, SmolStr, SyntaxNode, SyntaxNodeRef, }; pub struct ModuleScope { @@ -13,7 +13,8 @@ pub struct Entry { } enum EntryKind { - Item, Import, + Item, + Import, } impl ModuleScope { @@ -34,9 +35,8 @@ impl ModuleScope { collect_imports(tree, &mut entries); } continue; - }, - ast::ModuleItem::ExternCrateItem(_) | - ast::ModuleItem::ImplItem(_) => continue, + } + ast::ModuleItem::ExternCrateItem(_) | ast::ModuleItem::ImplItem(_) => continue, }; entries.extend(entry) } @@ -52,20 +52,22 @@ impl ModuleScope { impl Entry { fn new<'a>(item: impl ast::NameOwner<'a>) -> Option { let name = item.name()?; - Some(Entry { node: name.syntax().owned(), kind: EntryKind::Item }) + Some(Entry { + node: name.syntax().owned(), + kind: EntryKind::Item, + }) } fn new_import(path: ast::Path) -> Option { let name_ref = path.segment()?.name_ref()?; - Some(Entry { node: name_ref.syntax().owned(), kind: EntryKind::Import }) + Some(Entry { + node: name_ref.syntax().owned(), + kind: EntryKind::Import, + }) } pub fn name(&self) -> SmolStr { match self.kind { - EntryKind::Item => - ast::Name::cast(self.node.borrowed()).unwrap() - .text(), - EntryKind::Import => - ast::NameRef::cast(self.node.borrowed()).unwrap() - .text(), + EntryKind::Item => ast::Name::cast(self.node.borrowed()).unwrap().text(), + EntryKind::Import => ast::NameRef::cast(self.node.borrowed()).unwrap().text(), } } pub fn syntax(&self) -> SyntaxNodeRef { @@ -75,32 +77,31 @@ impl Entry { fn collect_imports(tree: ast::UseTree, acc: &mut Vec) { if let Some(use_tree_list) = tree.use_tree_list() { - return use_tree_list.use_trees().for_each(|it| collect_imports(it, acc)); + return use_tree_list + .use_trees() + .for_each(|it| collect_imports(it, acc)); } if let Some(path) = tree.path() { acc.extend(Entry::new_import(path)); } } - #[cfg(test)] mod tests { use super::*; - use ra_syntax::{File, ast::ModuleItemOwner}; + use ra_syntax::{ast::ModuleItemOwner, File}; fn do_check(code: &str, expected: &[&str]) { let file = File::parse(&code); let scope = ModuleScope::new(file.ast().items()); - let actual = scope.entries - .iter() - .map(|it| it.name()) - .collect::>(); + let actual = scope.entries.iter().map(|it| it.name()).collect::>(); assert_eq!(expected, actual.as_slice()); } #[test] fn test_module_scope() { - do_check(" + do_check( + " struct Foo; enum Bar {} mod baz {} @@ -110,6 +111,8 @@ mod tests { t, }; type T = (); - ", &["Foo", "Bar", "baz", "quux", "z", "t", "T"]) + ", + &["Foo", "Bar", "baz", "quux", "z", "t", "T"], + ) } } diff --git a/crates/ra_editor/src/symbols.rs b/crates/ra_editor/src/symbols.rs index d9e4b2df7a4..b768b34bc59 100644 --- a/crates/ra_editor/src/symbols.rs +++ b/crates/ra_editor/src/symbols.rs @@ -1,12 +1,13 @@ +use crate::TextRange; + use ra_syntax::{ - SyntaxKind, SyntaxNodeRef, AstNode, File, SmolStr, - ast::{self, NameOwner}, algo::{ visit::{visitor, Visitor}, walk::{walk, WalkEvent}, }, + ast::{self, NameOwner}, + AstNode, File, SmolStr, SyntaxKind, SyntaxNodeRef, }; -use crate::TextRange; #[derive(Debug, Clone)] pub struct StructureNode { @@ -25,9 +26,7 @@ pub struct FileSymbol { } pub fn file_symbols(file: &File) -> Vec { - file.syntax().descendants() - .filter_map(to_symbol) - .collect() + file.syntax().descendants().filter_map(to_symbol).collect() } fn to_symbol(node: SyntaxNodeRef) -> Option { @@ -51,23 +50,20 @@ fn to_symbol(node: SyntaxNodeRef) -> Option { .accept(node)? } - pub fn file_structure(file: &File) -> Vec { let mut res = Vec::new(); let mut stack = Vec::new(); for event in walk(file.syntax()) { match event { - WalkEvent::Enter(node) => { - match structure_node(node) { - Some(mut symbol) => { - symbol.parent = stack.last().map(|&n| n); - stack.push(res.len()); - res.push(symbol); - } - None => (), + WalkEvent::Enter(node) => match structure_node(node) { + Some(mut symbol) => { + symbol.parent = stack.last().map(|&n| n); + stack.push(res.len()); + res.push(symbol); } - } + None => (), + }, WalkEvent::Exit(node) => { if structure_node(node).is_some() { stack.pop().unwrap(); @@ -131,7 +127,8 @@ mod tests { #[test] fn test_file_structure() { - let file = File::parse(r#" + let file = File::parse( + r#" struct Foo { x: i32 } @@ -148,7 +145,8 @@ const C: i32 = 92; impl E {} impl fmt::Debug for E {} -"#); +"#, + ); let symbols = file_structure(&file); assert_eq_dbg( r#"[StructureNode { parent: None, label: "Foo", navigation_range: [8; 11), node_range: [1; 26), kind: STRUCT_DEF }, diff --git a/crates/ra_editor/src/test_utils.rs b/crates/ra_editor/src/test_utils.rs index 49eb530d50b..bc3d700f64d 100644 --- a/crates/ra_editor/src/test_utils.rs +++ b/crates/ra_editor/src/test_utils.rs @@ -1,12 +1,8 @@ -use ra_syntax::{File, TextUnit, TextRange}; -pub use crate::_test_utils::*; use crate::LocalEdit; +pub use crate::_test_utils::*; +use ra_syntax::{File, TextRange, TextUnit}; -pub fn check_action Option> ( - before: &str, - after: &str, - f: F, -) { +pub fn check_action Option>(before: &str, after: &str, f: F) { let (before_cursor_pos, before) = extract_offset(before); let file = File::parse(&before); let result = f(&file, before_cursor_pos).expect("code action is not applicable"); @@ -19,7 +15,7 @@ pub fn check_action Option> ( assert_eq_text!(after, &actual); } -pub fn check_action_range Option> ( +pub fn check_action_range Option>( before: &str, after: &str, f: F, diff --git a/crates/ra_editor/src/typing.rs b/crates/ra_editor/src/typing.rs index 542b9e10bd9..50b52e7a127 100644 --- a/crates/ra_editor/src/typing.rs +++ b/crates/ra_editor/src/typing.rs @@ -1,32 +1,30 @@ use std::mem; use ra_syntax::{ - TextUnit, TextRange, SyntaxNodeRef, File, AstNode, SyntaxKind, + algo::{find_covering_node, find_leaf_at_offset, LeafAtOffset}, ast, - algo::{ - find_covering_node, find_leaf_at_offset, LeafAtOffset, - }, - text_utils::{intersect, contains_offset_nonstrict}, + text_utils::{contains_offset_nonstrict, intersect}, + AstNode, File, SyntaxKind, SyntaxKind::*, + SyntaxNodeRef, TextRange, TextUnit, }; -use crate::{LocalEdit, EditBuilder, find_node_at_offset}; +use crate::{find_node_at_offset, EditBuilder, LocalEdit}; pub fn join_lines(file: &File, range: TextRange) -> LocalEdit { let range = if range.is_empty() { let syntax = file.syntax(); let text = syntax.text().slice(range.start()..); let pos = match text.find('\n') { - None => return LocalEdit { - edit: EditBuilder::new().finish(), - cursor_position: None - }, - Some(pos) => pos + None => { + return LocalEdit { + edit: EditBuilder::new().finish(), + cursor_position: None, + } + } + Some(pos) => pos, }; - TextRange::offset_len( - range.start() + pos, - TextUnit::of_char('\n'), - ) + TextRange::offset_len(range.start() + pos, TextUnit::of_char('\n')) } else { range }; @@ -58,7 +56,9 @@ pub fn join_lines(file: &File, range: TextRange) -> LocalEdit { } pub fn on_enter(file: &File, offset: TextUnit) -> Option { - let comment = find_leaf_at_offset(file.syntax(), offset).left_biased().and_then(|it| ast::Comment::cast(it))?; + let comment = find_leaf_at_offset(file.syntax(), offset) + .left_biased() + .and_then(|it| ast::Comment::cast(it))?; if let ast::CommentFlavor::Multiline = comment.flavor() { return None; @@ -88,7 +88,7 @@ fn node_indent<'a>(file: &'a File, node: SyntaxNodeRef) -> Option<&'a str> { } LeafAtOffset::Single(n) => { assert!(n == node); - return Some("") + return Some(""); } LeafAtOffset::None => unreachable!(), }; @@ -110,7 +110,12 @@ pub fn on_eq_typed(file: &File, offset: TextUnit) -> Option { if contains_offset_nonstrict(expr_range, offset) && offset != expr_range.start() { return None; } - if file.syntax().text().slice(offset..expr_range.start()).contains('\n') { + if file + .syntax() + .text() + .slice(offset..expr_range.start()) + .contains('\n') + { return None; } } else { @@ -125,12 +130,7 @@ pub fn on_eq_typed(file: &File, offset: TextUnit) -> Option { }) } -fn remove_newline( - edit: &mut EditBuilder, - node: SyntaxNodeRef, - node_text: &str, - offset: TextUnit, -) { +fn remove_newline(edit: &mut EditBuilder, node: SyntaxNodeRef, node_text: &str, offset: TextUnit) { if node.kind() != WHITESPACE || node_text.bytes().filter(|&b| b == b'\n').count() != 1 { // The node is either the first or the last in the file let suff = &node_text[TextRange::from_to( @@ -156,7 +156,7 @@ fn remove_newline( // // into `my_function()` if join_single_expr_block(edit, node).is_some() { - return + return; } // The node is between two other nodes @@ -170,34 +170,28 @@ fn remove_newline( // Adds: a single whitespace edit.replace( TextRange::from_to(prev.range().start(), node.range().end()), - " ".to_string() + " ".to_string(), ); } else if let (Some(_), Some(next)) = (ast::Comment::cast(prev), ast::Comment::cast(next)) { // Removes: newline (incl. surrounding whitespace), start of the next comment edit.delete(TextRange::from_to( node.range().start(), - next.syntax().range().start() + TextUnit::of_str(next.prefix()) + next.syntax().range().start() + TextUnit::of_str(next.prefix()), )); } else { // Remove newline but add a computed amount of whitespace characters - edit.replace( - node.range(), - compute_ws(prev, next).to_string(), - ); + edit.replace(node.range(), compute_ws(prev, next).to_string()); } } fn is_trailing_comma(left: SyntaxKind, right: SyntaxKind) -> bool { match (left, right) { - (COMMA, R_PAREN) | (COMMA, R_BRACK) => true, - _ => false + (COMMA, R_PAREN) | (COMMA, R_BRACK) => true, + _ => false, } } -fn join_single_expr_block( - edit: &mut EditBuilder, - node: SyntaxNodeRef, -) -> Option<()> { +fn join_single_expr_block(edit: &mut EditBuilder, node: SyntaxNodeRef) -> Option<()> { let block = ast::Block::cast(node.parent()?)?; let block_expr = ast::BlockExpr::cast(block.syntax().parent()?)?; let expr = single_expr(block)?; @@ -244,7 +238,7 @@ fn compute_ws(left: SyntaxNodeRef, right: SyntaxNodeRef) -> &'static str { #[cfg(test)] mod tests { use super::*; - use crate::test_utils::{check_action, extract_range, extract_offset, add_cursor}; + use crate::test_utils::{add_cursor, check_action, extract_offset, extract_range}; fn check_join_lines(before: &str, after: &str) { check_action(before, after, |file, offset| { @@ -256,118 +250,142 @@ mod tests { #[test] fn test_join_lines_comma() { - check_join_lines(r" + check_join_lines( + r" fn foo() { <|>foo(1, ) } -", r" +", + r" fn foo() { <|>foo(1) } -"); +", + ); } #[test] fn test_join_lines_lambda_block() { - check_join_lines(r" + check_join_lines( + r" pub fn reparse(&self, edit: &AtomEdit) -> File { <|>self.incremental_reparse(edit).unwrap_or_else(|| { self.full_reparse(edit) }) } -", r" +", + r" pub fn reparse(&self, edit: &AtomEdit) -> File { <|>self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit)) } -"); +", + ); } #[test] fn test_join_lines_block() { - check_join_lines(r" + check_join_lines( + r" fn foo() { foo(<|>{ 92 }) -}", r" +}", + r" fn foo() { foo(<|>92) -}"); +}", + ); } #[test] fn test_join_lines_normal_comments() { - check_join_lines(r" + check_join_lines( + r" fn foo() { // Hello<|> // world! } -", r" +", + r" fn foo() { // Hello<|> world! } -"); +", + ); } #[test] fn test_join_lines_doc_comments() { - check_join_lines(r" + check_join_lines( + r" fn foo() { /// Hello<|> /// world! } -", r" +", + r" fn foo() { /// Hello<|> world! } -"); +", + ); } #[test] fn test_join_lines_mod_comments() { - check_join_lines(r" + check_join_lines( + r" fn foo() { //! Hello<|> //! world! } -", r" +", + r" fn foo() { //! Hello<|> world! } -"); +", + ); } #[test] fn test_join_lines_multiline_comments_1() { - check_join_lines(r" + check_join_lines( + r" fn foo() { // Hello<|> /* world! */ } -", r" +", + r" fn foo() { // Hello<|> world! */ } -"); +", + ); } #[test] fn test_join_lines_multiline_comments_2() { - check_join_lines(r" + check_join_lines( + r" fn foo() { // The<|> /* quick brown fox! */ } -", r" +", + r" fn foo() { // The<|> quick brown fox! */ } -"); +", + ); } fn check_join_lines_sel(before: &str, after: &str) { @@ -380,59 +398,71 @@ fn foo() { #[test] fn test_join_lines_selection_fn_args() { - check_join_lines_sel(r" + check_join_lines_sel( + r" fn foo() { <|>foo(1, 2, 3, <|>) } - ", r" + ", + r" fn foo() { foo(1, 2, 3) } - "); + ", + ); } #[test] fn test_join_lines_selection_struct() { - check_join_lines_sel(r" + check_join_lines_sel( + r" struct Foo <|>{ f: u32, }<|> - ", r" + ", + r" struct Foo { f: u32 } - "); + ", + ); } #[test] fn test_join_lines_selection_dot_chain() { - check_join_lines_sel(r" + check_join_lines_sel( + r" fn foo() { join(<|>type_params.type_params() .filter_map(|it| it.name()) .map(|it| it.text())<|>) -}", r" +}", + r" fn foo() { join(type_params.type_params().filter_map(|it| it.name()).map(|it| it.text())) -}"); +}", + ); } #[test] fn test_join_lines_selection_lambda_block_body() { - check_join_lines_sel(r" + check_join_lines_sel( + r" pub fn handle_find_matching_brace() { params.offsets .map(|offset| <|>{ world.analysis().matching_brace(&file, offset).unwrap_or(offset) }<|>) .collect(); -}", r" +}", + r" pub fn handle_find_matching_brace() { params.offsets .map(|offset| world.analysis().matching_brace(&file, offset).unwrap_or(offset)) .collect(); -}"); +}", + ); } #[test] @@ -454,15 +484,18 @@ pub fn handle_find_matching_brace() { // let foo =; // } // "); - do_check(r" + do_check( + r" fn foo() { let foo =<|> 1 + 1 } -", r" +", + r" fn foo() { let foo = 1 + 1; } -"); +", + ); // do_check(r" // fn foo() { // let foo =<|> @@ -496,28 +529,34 @@ fn foo() { assert!(apply_on_enter(text).is_none()) } - do_check(r" + do_check( + r" /// Some docs<|> fn foo() { } -", r" +", + r" /// Some docs /// <|> fn foo() { } -"); - do_check(r" +", + ); + do_check( + r" impl S { /// Some<|> docs. fn foo() {} } -", r" +", + r" impl S { /// Some /// <|> docs. fn foo() {} } -"); +", + ); do_check_noop(r"<|>//! docz"); } } diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs index 5598ec75f96..1dd4957911d 100644 --- a/crates/ra_lsp_server/src/caps.rs +++ b/crates/ra_lsp_server/src/caps.rs @@ -1,14 +1,8 @@ use languageserver_types::{ - ServerCapabilities, - CodeActionProviderCapability, - FoldingRangeProviderCapability, - TextDocumentSyncCapability, + CodeActionProviderCapability, CompletionOptions, DocumentOnTypeFormattingOptions, + ExecuteCommandOptions, FoldingRangeProviderCapability, ServerCapabilities, + SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind, TextDocumentSyncOptions, - TextDocumentSyncKind, - ExecuteCommandOptions, - CompletionOptions, - SignatureHelpOptions, - DocumentOnTypeFormattingOptions, }; pub fn server_capabilities() -> ServerCapabilities { @@ -20,7 +14,7 @@ pub fn server_capabilities() -> ServerCapabilities { will_save: None, will_save_wait_until: None, save: None, - } + }, )), hover_provider: None, completion_provider: Some(CompletionOptions { @@ -28,7 +22,7 @@ pub fn server_capabilities() -> ServerCapabilities { trigger_characters: None, }), signature_help_provider: Some(SignatureHelpOptions { - trigger_characters: Some(vec!["(".to_string(), ",".to_string()]) + trigger_characters: Some(vec!["(".to_string(), ",".to_string()]), }), definition_provider: Some(true), type_definition_provider: None, diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs index a75b160c539..8325e8c1e24 100644 --- a/crates/ra_lsp_server/src/conv.rs +++ b/crates/ra_lsp_server/src/conv.rs @@ -1,17 +1,12 @@ use languageserver_types::{ - Range, SymbolKind, Position, TextEdit, Location, Url, - TextDocumentIdentifier, VersionedTextDocumentIdentifier, TextDocumentItem, - TextDocumentPositionParams, TextDocumentEdit, + Location, Position, Range, SymbolKind, TextDocumentEdit, TextDocumentIdentifier, + TextDocumentItem, TextDocumentPositionParams, TextEdit, Url, VersionedTextDocumentIdentifier, }; -use ra_editor::{LineIndex, LineCol, Edit, AtomEdit}; -use ra_syntax::{SyntaxKind, TextUnit, TextRange}; -use ra_analysis::{FileId, SourceChange, SourceFileEdit, FileSystemEdit}; +use ra_analysis::{FileId, FileSystemEdit, SourceChange, SourceFileEdit}; +use ra_editor::{AtomEdit, Edit, LineCol, LineIndex}; +use ra_syntax::{SyntaxKind, TextRange, TextUnit}; -use crate::{ - Result, - server_world::ServerWorld, - req, -}; +use crate::{req, server_world::ServerWorld, Result}; pub trait Conv { type Output; @@ -190,8 +185,12 @@ impl TryConvWith for SourceChange { None => None, Some(pos) => { let line_index = world.analysis().file_line_index(pos.file_id); - let edits = self.source_file_edits.iter().find(|it| it.file_id == pos.file_id) - .map(|it| it.edits.as_slice()).unwrap_or(&[]); + let edits = self + .source_file_edits + .iter() + .find(|it| it.file_id == pos.file_id) + .map(|it| it.edits.as_slice()) + .unwrap_or(&[]); let line_col = translate_offset_with_edit(&*line_index, pos.offset, edits); let position = Position::new(line_col.line as u64, u32::from(line_col.col) as u64); Some(TextDocumentPositionParams { @@ -224,11 +223,11 @@ fn translate_offset_with_edit( let fallback = pre_edit_index.line_col(offset); let edit = match edits.first() { None => return fallback, - Some(edit) => edit + Some(edit) => edit, }; let end_offset = edit.delete.start() + TextUnit::of_str(&edit.insert); if !(edit.delete.start() <= offset && offset <= end_offset) { - return fallback + return fallback; } let rel_offset = offset - edit.delete.start(); let in_edit_line_col = LineIndex::new(&edit.insert).line_col(rel_offset); @@ -255,11 +254,11 @@ impl TryConvWith for SourceFileEdit { version: None, }; let line_index = world.analysis().file_line_index(self.file_id); - let edits = self.edits - .into_iter() - .map_conv_with(&line_index) - .collect(); - Ok(TextDocumentEdit { text_document, edits }) + let edits = self.edits.into_iter().map_conv_with(&line_index).collect(); + Ok(TextDocumentEdit { + text_document, + edits, + }) } } @@ -273,13 +272,13 @@ impl TryConvWith for FileSystemEdit { let path = &path.as_str()[3..]; // strip `../` b/c url is weird let uri = uri.join(path)?; req::FileSystemEdit::CreateFile { uri } - }, + } FileSystemEdit::MoveFile { file, path } => { let src = world.file_id_to_uri(file)?; let path = &path.as_str()[3..]; // strip `../` b/c url is weird let dst = src.join(path)?; req::FileSystemEdit::MoveFile { src, dst } - }, + } }; Ok(res) } @@ -291,12 +290,9 @@ pub fn to_location( world: &ServerWorld, line_index: &LineIndex, ) -> Result { - let url = file_id.try_conv_with(world)?; - let loc = Location::new( - url, - range.conv_with(line_index), - ); - Ok(loc) + let url = file_id.try_conv_with(world)?; + let loc = Location::new(url, range.conv_with(line_index)); + Ok(loc) } pub trait MapConvWith<'a>: Sized + 'a { @@ -309,8 +305,9 @@ pub trait MapConvWith<'a>: Sized + 'a { } impl<'a, I> MapConvWith<'a> for I - where I: Iterator + 'a, - I::Item: ConvWith +where + I: Iterator + 'a, + I::Item: ConvWith, { type Ctx = ::Ctx; type Output = ::Output; @@ -322,9 +319,9 @@ pub struct ConvWithIter<'a, I, Ctx: 'a> { } impl<'a, I, Ctx> Iterator for ConvWithIter<'a, I, Ctx> - where - I: Iterator, - I::Item: ConvWith, +where + I: Iterator, + I::Item: ConvWith, { type Item = ::Output; @@ -332,4 +329,3 @@ impl<'a, I, Ctx> Iterator for ConvWithIter<'a, I, Ctx> self.iter.next().map(|item| item.conv_with(self.ctx)) } } - diff --git a/crates/ra_lsp_server/src/lib.rs b/crates/ra_lsp_server/src/lib.rs index 7224b147609..f1b17f2825d 100644 --- a/crates/ra_lsp_server/src/lib.rs +++ b/crates/ra_lsp_server/src/lib.rs @@ -2,39 +2,36 @@ extern crate failure; #[macro_use] extern crate serde_derive; +extern crate languageserver_types; extern crate serde; extern crate serde_json; -extern crate languageserver_types; #[macro_use] extern crate crossbeam_channel; extern crate rayon; #[macro_use] extern crate log; +extern crate cargo_metadata; extern crate drop_bomb; -extern crate url_serde; -extern crate walkdir; extern crate im; extern crate relative_path; -extern crate cargo_metadata; extern crate rustc_hash; +extern crate url_serde; +extern crate walkdir; extern crate gen_lsp_server; -extern crate ra_editor; extern crate ra_analysis; +extern crate ra_editor; extern crate ra_syntax; mod caps; -pub mod req; mod conv; mod main_loop; -mod vfs; mod path_map; -mod server_world; mod project_model; +pub mod req; +mod server_world; pub mod thread_watcher; +mod vfs; pub type Result = ::std::result::Result; -pub use crate::{ - main_loop::main_loop, - caps::server_capabilities, -}; +pub use crate::{caps::server_capabilities, main_loop::main_loop}; diff --git a/crates/ra_lsp_server/src/main.rs b/crates/ra_lsp_server/src/main.rs index e5d1792b7e3..9f62347f129 100644 --- a/crates/ra_lsp_server/src/main.rs +++ b/crates/ra_lsp_server/src/main.rs @@ -6,7 +6,7 @@ extern crate flexi_logger; extern crate gen_lsp_server; extern crate ra_lsp_server; -use flexi_logger::{Logger, Duplicate}; +use flexi_logger::{Duplicate, Logger}; use gen_lsp_server::{run_server, stdio_transport}; use ra_lsp_server::Result; @@ -38,7 +38,8 @@ fn main_inner() -> Result<()> { receiver, sender, |params, r, s| { - let root = params.root_uri + let root = params + .root_uri .and_then(|it| it.to_file_path().ok()) .unwrap_or(cwd); ra_lsp_server::main_loop(false, root, r, s) @@ -49,4 +50,3 @@ fn main_inner() -> Result<()> { info!("... IO is down"); Ok(()) } - diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 5acb39b6001..c25b6385202 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -1,23 +1,20 @@ use rustc_hash::FxHashMap; use languageserver_types::{ - Diagnostic, DiagnosticSeverity, DocumentSymbol, - CodeActionResponse, Command, TextDocumentIdentifier, - SymbolInformation, Position, Location, TextEdit, - CompletionItem, InsertTextFormat, CompletionItemKind, - FoldingRange, FoldingRangeParams, FoldingRangeKind + CodeActionResponse, Command, CompletionItem, CompletionItemKind, Diagnostic, + DiagnosticSeverity, DocumentSymbol, FoldingRange, FoldingRangeKind, FoldingRangeParams, + InsertTextFormat, Location, Position, SymbolInformation, TextDocumentIdentifier, TextEdit, }; +use ra_analysis::{FileId, FoldKind, JobToken, Query, RunnableKind}; +use ra_syntax::text_utils::contains_offset_nonstrict; use serde_json::to_value; -use ra_analysis::{Query, FileId, RunnableKind, JobToken, FoldKind}; -use ra_syntax::{ - text_utils::contains_offset_nonstrict -}; use crate::{ - req::{self, Decoration}, Result, - conv::{Conv, ConvWith, TryConvWith, MapConvWith, to_location}, - server_world::ServerWorld, + conv::{to_location, Conv, ConvWith, MapConvWith, TryConvWith}, project_model::TargetKind, + req::{self, Decoration}, + server_world::ServerWorld, + Result, }; pub fn handle_syntax_tree( @@ -38,7 +35,9 @@ pub fn handle_extend_selection( let file_id = params.text_document.try_conv_with(&world)?; let file = world.analysis().file_syntax(file_id); let line_index = world.analysis().file_line_index(file_id); - let selections = params.selections.into_iter() + let selections = params + .selections + .into_iter() .map_conv_with(&line_index) .map(|r| world.analysis().extend_selection(&file, r)) .map_conv_with(&line_index) @@ -54,11 +53,15 @@ pub fn handle_find_matching_brace( let file_id = params.text_document.try_conv_with(&world)?; let file = world.analysis().file_syntax(file_id); let line_index = world.analysis().file_line_index(file_id); - let res = params.offsets + let res = params + .offsets .into_iter() .map_conv_with(&line_index) .map(|offset| { - world.analysis().matching_brace(&file, offset).unwrap_or(offset) + world + .analysis() + .matching_brace(&file, offset) + .unwrap_or(offset) }) .map_conv_with(&line_index) .collect(); @@ -73,7 +76,9 @@ pub fn handle_join_lines( let file_id = params.text_document.try_conv_with(&world)?; let line_index = world.analysis().file_line_index(file_id); let range = params.range.conv_with(&line_index); - world.analysis().join_lines(file_id, range) + world + .analysis() + .join_lines(file_id, range) .try_conv_with(&world) } @@ -87,7 +92,7 @@ pub fn handle_on_enter( let offset = params.position.conv_with(&line_index); match world.analysis().on_enter(file_id, offset) { None => Ok(None), - Some(edit) => Ok(Some(edit.try_conv_with(&world)?)) + Some(edit) => Ok(Some(edit.try_conv_with(&world)?)), } } @@ -158,7 +163,9 @@ pub fn handle_workspace_symbol( let all_symbols = params.query.contains("#"); let libs = params.query.contains("*"); let query = { - let query: String = params.query.chars() + let query: String = params + .query + .chars() .filter(|&c| c != '#' && c != '*') .collect(); let mut q = Query::new(query); @@ -180,22 +187,23 @@ pub fn handle_workspace_symbol( return Ok(Some(res)); - fn exec_query(world: &ServerWorld, query: Query, token: &JobToken) -> Result> { + fn exec_query( + world: &ServerWorld, + query: Query, + token: &JobToken, + ) -> Result> { let mut res = Vec::new(); for (file_id, symbol) in world.analysis().symbol_search(query, token) { let line_index = world.analysis().file_line_index(file_id); let info = SymbolInformation { name: symbol.name.to_string(), kind: symbol.kind.conv(), - location: to_location( - file_id, symbol.node_range, - world, &line_index - )?, + location: to_location(file_id, symbol.node_range, world, &line_index)?, container_name: None, deprecated: None, }; res.push(info); - }; + } Ok(res) } } @@ -209,12 +217,12 @@ pub fn handle_goto_definition( let line_index = world.analysis().file_line_index(file_id); let offset = params.position.conv_with(&line_index); let mut res = Vec::new(); - for (file_id, symbol) in world.analysis().approximately_resolve_symbol(file_id, offset, &token) { + for (file_id, symbol) in world + .analysis() + .approximately_resolve_symbol(file_id, offset, &token) + { let line_index = world.analysis().file_line_index(file_id); - let location = to_location( - file_id, symbol.node_range, - &world, &line_index, - )?; + let location = to_location(file_id, symbol.node_range, &world, &line_index)?; res.push(location) } Ok(Some(req::GotoDefinitionResponse::Array(res))) @@ -229,10 +237,7 @@ pub fn handle_parent_module( let mut res = Vec::new(); for (file_id, symbol) in world.analysis().parent_module(file_id) { let line_index = world.analysis().file_line_index(file_id); - let location = to_location( - file_id, symbol.node_range, - &world, &line_index - )?; + let location = to_location(file_id, symbol.node_range, &world, &line_index)?; res.push(location); } Ok(res) @@ -259,21 +264,16 @@ pub fn handle_runnables( let r = req::Runnable { range: runnable.range.conv_with(&line_index), label: match &runnable.kind { - RunnableKind::Test { name } => - format!("test {}", name), - RunnableKind::Bin => - "run binary".to_string(), + RunnableKind::Test { name } => format!("test {}", name), + RunnableKind::Bin => "run binary".to_string(), }, bin: "cargo".to_string(), args, env: { let mut m = FxHashMap::default(); - m.insert( - "RUST_BACKTRACE".to_string(), - "short".to_string(), - ); + m.insert("RUST_BACKTRACE".to_string(), "short".to_string()); m - } + }, }; res.push(r); } @@ -283,10 +283,16 @@ pub fn handle_runnables( let spec = if let Some(&crate_id) = world.analysis().crate_for(file_id).first() { let file_id = world.analysis().crate_root(crate_id); let path = world.path_map.get_path(file_id); - world.workspaces.iter() + world + .workspaces + .iter() .filter_map(|ws| { let tgt = ws.target_by_root(path)?; - Some((tgt.package(ws).name(ws).clone(), tgt.name(ws).clone(), tgt.kind(ws))) + Some(( + tgt.package(ws).name(ws).clone(), + tgt.name(ws).clone(), + tgt.kind(ws), + )) }) .next() } else { @@ -294,22 +300,22 @@ pub fn handle_runnables( }; let mut res = Vec::new(); match kind { - RunnableKind::Test { name } => { - res.push("test".to_string()); - if let Some((pkg_name, tgt_name, tgt_kind)) = spec { - spec_args(pkg_name, tgt_name, tgt_kind, &mut res); - } - res.push("--".to_string()); - res.push(name.to_string()); - res.push("--nocapture".to_string()); + RunnableKind::Test { name } => { + res.push("test".to_string()); + if let Some((pkg_name, tgt_name, tgt_kind)) = spec { + spec_args(pkg_name, tgt_name, tgt_kind, &mut res); } - RunnableKind::Bin => { - res.push("run".to_string()); - if let Some((pkg_name, tgt_name, tgt_kind)) = spec { - spec_args(pkg_name, tgt_name, tgt_kind, &mut res); - } + res.push("--".to_string()); + res.push(name.to_string()); + res.push("--nocapture".to_string()); + } + RunnableKind::Bin => { + res.push("run".to_string()); + if let Some((pkg_name, tgt_name, tgt_kind)) = spec { + spec_args(pkg_name, tgt_name, tgt_kind, &mut res); } } + } res } @@ -362,12 +368,13 @@ pub fn handle_completion( None => return Ok(None), Some(items) => items, }; - let items = items.into_iter() + let items = items + .into_iter() .map(|item| { let mut res = CompletionItem { label: item.label, filter_text: item.lookup, - .. Default::default() + ..Default::default() }; if let Some(snip) = item.snippet { res.insert_text = Some(snip); @@ -389,24 +396,27 @@ pub fn handle_folding_range( let file_id = params.text_document.try_conv_with(&world)?; let line_index = world.analysis().file_line_index(file_id); - let res = Some(world.analysis() - .folding_ranges(file_id) - .into_iter() - .map(|fold| { - let kind = match fold.kind { - FoldKind::Comment => FoldingRangeKind::Comment, - FoldKind::Imports => FoldingRangeKind::Imports - }; - let range = fold.range.conv_with(&line_index); - FoldingRange { - start_line: range.start.line, - start_character: Some(range.start.character), - end_line: range.end.line, - end_character: Some(range.start.character), - kind: Some(kind) - } - }) - .collect()); + let res = Some( + world + .analysis() + .folding_ranges(file_id) + .into_iter() + .map(|fold| { + let kind = match fold.kind { + FoldKind::Comment => FoldingRangeKind::Comment, + FoldKind::Imports => FoldingRangeKind::Imports, + }; + let range = fold.range.conv_with(&line_index); + FoldingRange { + start_line: range.start.line, + start_character: Some(range.start.character), + end_line: range.end.line, + end_character: Some(range.start.character), + kind: Some(kind), + } + }) + .collect(), + ); Ok(res) } @@ -422,25 +432,28 @@ pub fn handle_signature_help( let line_index = world.analysis().file_line_index(file_id); let offset = params.position.conv_with(&line_index); - if let Some((descriptor, active_param)) = world.analysis().resolve_callable(file_id, offset, &token) { - let parameters : Vec = - descriptor.params.iter().map(|param| - ParameterInformation { - label: param.clone(), - documentation: None - } - ).collect(); + if let Some((descriptor, active_param)) = + world.analysis().resolve_callable(file_id, offset, &token) + { + let parameters: Vec = descriptor + .params + .iter() + .map(|param| ParameterInformation { + label: param.clone(), + documentation: None, + }) + .collect(); let sig_info = SignatureInformation { label: descriptor.label, documentation: None, - parameters: Some(parameters) + parameters: Some(parameters), }; Ok(Some(req::SignatureHelp { signatures: vec![sig_info], active_signature: Some(0), - active_parameter: active_param.map(|a| a as u64) + active_parameter: active_param.map(|a| a as u64), })) } else { Ok(None) @@ -457,7 +470,10 @@ pub fn handle_code_action( let range = params.range.conv_with(&line_index); let assists = world.analysis().assists(file_id, range).into_iter(); - let fixes = world.analysis().diagnostics(file_id).into_iter() + let fixes = world + .analysis() + .diagnostics(file_id) + .into_iter() .filter_map(|d| Some((d.range, d.fix?))) .filter(|(range, _fix)| contains_offset_nonstrict(*range, range.start())) .map(|(_range, fix)| fix); @@ -483,7 +499,9 @@ pub fn publish_diagnostics( ) -> Result { let uri = world.file_id_to_uri(file_id)?; let line_index = world.analysis().file_line_index(file_id); - let diagnostics = world.analysis().diagnostics(file_id) + let diagnostics = world + .analysis() + .diagnostics(file_id) .into_iter() .map(|d| Diagnostic { range: d.range.conv_with(&line_index), @@ -492,7 +510,8 @@ pub fn publish_diagnostics( source: Some("rust-analyzer".to_string()), message: d.message, related_information: None, - }).collect(); + }) + .collect(); Ok(req::PublishDiagnosticsParams { uri, diagnostics }) } @@ -509,10 +528,13 @@ pub fn publish_decorations( fn highlight(world: &ServerWorld, file_id: FileId) -> Vec { let line_index = world.analysis().file_line_index(file_id); - world.analysis().highlight(file_id) + world + .analysis() + .highlight(file_id) .into_iter() .map(|h| Decoration { range: h.range.conv_with(&line_index), tag: h.tag, - }).collect() + }) + .collect() } diff --git a/crates/ra_lsp_server/src/main_loop/mod.rs b/crates/ra_lsp_server/src/main_loop/mod.rs index cf2477cb519..a11baf4aaec 100644 --- a/crates/ra_lsp_server/src/main_loop/mod.rs +++ b/crates/ra_lsp_server/src/main_loop/mod.rs @@ -1,29 +1,26 @@ mod handlers; mod subscriptions; -use std::{ - path::PathBuf, -}; +use std::path::PathBuf; -use serde::{Serialize, de::DeserializeOwned}; -use crossbeam_channel::{unbounded, Sender, Receiver}; -use rayon::{self, ThreadPool}; -use languageserver_types::{NumberOrString}; -use ra_analysis::{FileId, JobHandle, JobToken, LibraryData}; +use crossbeam_channel::{unbounded, Receiver, Sender}; use gen_lsp_server::{ - RawRequest, RawNotification, RawMessage, RawResponse, ErrorCode, - handle_shutdown, + handle_shutdown, ErrorCode, RawMessage, RawNotification, RawRequest, RawResponse, }; +use languageserver_types::NumberOrString; +use ra_analysis::{FileId, JobHandle, JobToken, LibraryData}; +use rayon::{self, ThreadPool}; use rustc_hash::FxHashMap; +use serde::{de::DeserializeOwned, Serialize}; use crate::{ + main_loop::subscriptions::Subscriptions, + project_model::{workspace_loader, CargoWorkspace}, req, - Result, - vfs::{self, FileEvent}, - server_world::{ServerWorldState, ServerWorld}, - main_loop::subscriptions::{Subscriptions}, - project_model::{CargoWorkspace, workspace_loader}, + server_world::{ServerWorld, ServerWorldState}, thread_watcher::Worker, + vfs::{self, FileEvent}, + Result, }; #[derive(Debug)] @@ -147,56 +144,50 @@ fn main_loop_inner( } state_changed = true; } - Event::Ws(ws) => { - match ws { - Ok(ws) => { - let workspaces = vec![ws]; - feedback(internal_mode, "workspace loaded", msg_sender); - for ws in workspaces.iter() { - for pkg in ws.packages().filter(|pkg| !pkg.is_member(ws)) { - debug!("sending root, {}", pkg.root(ws).to_path_buf().display()); - fs_worker.send(pkg.root(ws).to_path_buf()); - } + Event::Ws(ws) => match ws { + Ok(ws) => { + let workspaces = vec![ws]; + feedback(internal_mode, "workspace loaded", msg_sender); + for ws in workspaces.iter() { + for pkg in ws.packages().filter(|pkg| !pkg.is_member(ws)) { + debug!("sending root, {}", pkg.root(ws).to_path_buf().display()); + fs_worker.send(pkg.root(ws).to_path_buf()); } - state.set_workspaces(workspaces); - state_changed = true; } - Err(e) => warn!("loading workspace failed: {}", e), + state.set_workspaces(workspaces); + state_changed = true; } - } + Err(e) => warn!("loading workspace failed: {}", e), + }, Event::Lib(lib) => { feedback(internal_mode, "library loaded", msg_sender); state.add_lib(lib); } - Event::Msg(msg) => { - match msg { - RawMessage::Request(req) => { - let req = match handle_shutdown(req, msg_sender) { - Some(req) => req, - None => return Ok(()), - }; - match on_request(state, pending_requests, pool, &task_sender, req)? { - None => (), - Some(req) => { - error!("unknown request: {:?}", req); - let resp = RawResponse::err( - req.id, - ErrorCode::MethodNotFound as i32, - "unknown request".to_string(), - ); - msg_sender.send(RawMessage::Response(resp)) - } + Event::Msg(msg) => match msg { + RawMessage::Request(req) => { + let req = match handle_shutdown(req, msg_sender) { + Some(req) => req, + None => return Ok(()), + }; + match on_request(state, pending_requests, pool, &task_sender, req)? { + None => (), + Some(req) => { + error!("unknown request: {:?}", req); + let resp = RawResponse::err( + req.id, + ErrorCode::MethodNotFound as i32, + "unknown request".to_string(), + ); + msg_sender.send(RawMessage::Response(resp)) } } - RawMessage::Notification(not) => { - on_notification(msg_sender, state, pending_requests, subs, not)?; - state_changed = true; - } - RawMessage::Response(resp) => { - error!("unexpected response: {:?}", resp) - } } - } + RawMessage::Notification(not) => { + on_notification(msg_sender, state, pending_requests, subs, not)?; + state_changed = true; + } + RawMessage::Response(resp) => error!("unexpected response: {:?}", resp), + }, }; if state_changed { @@ -222,8 +213,7 @@ fn on_task( } msg_sender.send(RawMessage::Response(response)) } - Task::Notify(n) => - msg_sender.send(RawMessage::Notification(n)), + Task::Notify(n) => msg_sender.send(RawMessage::Notification(n)), } } @@ -237,7 +227,9 @@ fn on_request( let mut pool_dispatcher = PoolDispatcher { req: Some(req), res: None, - pool, world, sender + pool, + world, + sender, }; let req = pool_dispatcher .on::(handlers::handle_syntax_tree)? @@ -262,7 +254,7 @@ fn on_request( let inserted = pending_requests.insert(id, handle).is_none(); assert!(inserted, "duplicate request: {}", id); Ok(None) - }, + } Err(req) => Ok(Some(req)), } } @@ -285,45 +277,53 @@ fn on_notification( if let Some(handle) = pending_requests.remove(&id) { handle.cancel(); } - return Ok(()) + return Ok(()); } Err(not) => not, }; let not = match not.cast::() { Ok(params) => { let uri = params.text_document.uri; - let path = uri.to_file_path() + let path = uri + .to_file_path() .map_err(|()| format_err!("invalid uri: {}", uri))?; let file_id = state.add_mem_file(path, params.text_document.text); subs.add_sub(file_id); - return Ok(()) + return Ok(()); } Err(not) => not, }; let not = match not.cast::() { Ok(mut params) => { let uri = params.text_document.uri; - let path = uri.to_file_path() + let path = uri + .to_file_path() .map_err(|()| format_err!("invalid uri: {}", uri))?; - let text = params.content_changes.pop() + let text = params + .content_changes + .pop() .ok_or_else(|| format_err!("empty changes"))? .text; state.change_mem_file(path.as_path(), text)?; - return Ok(()) + return Ok(()); } Err(not) => not, }; let not = match not.cast::() { Ok(params) => { let uri = params.text_document.uri; - let path = uri.to_file_path() + let path = uri + .to_file_path() .map_err(|()| format_err!("invalid uri: {}", uri))?; let file_id = state.remove_mem_file(path.as_path())?; subs.remove_sub(file_id); - let params = req::PublishDiagnosticsParams { uri, diagnostics: Vec::new() }; + let params = req::PublishDiagnosticsParams { + uri, + diagnostics: Vec::new(), + }; let not = RawNotification::new::(¶ms); msg_sender.send(RawMessage::Notification(not)); - return Ok(()) + return Ok(()); } Err(not) => not, }; @@ -342,11 +342,12 @@ struct PoolDispatcher<'a> { impl<'a> PoolDispatcher<'a> { fn on<'b, R>( &'b mut self, - f: fn(ServerWorld, R::Params, JobToken) -> Result + f: fn(ServerWorld, R::Params, JobToken) -> Result, ) -> Result<&'b mut Self> - where R: req::Request, - R::Params: DeserializeOwned + Send + 'static, - R::Result: Serialize + 'static, + where + R: req::Request, + R::Params: DeserializeOwned + Send + 'static, + R::Result: Serialize + 'static, { let req = match self.req.take() { None => return Ok(self), @@ -360,16 +361,16 @@ impl<'a> PoolDispatcher<'a> { self.pool.spawn(move || { let resp = match f(world, params, token) { Ok(resp) => RawResponse::ok::(id, &resp), - Err(e) => RawResponse::err(id, ErrorCode::InternalError as i32, e.to_string()), + Err(e) => { + RawResponse::err(id, ErrorCode::InternalError as i32, e.to_string()) + } }; let task = Task::Respond(resp); sender.send(task); }); self.res = Some((id, handle)); } - Err(req) => { - self.req = Some(req) - } + Err(req) => self.req = Some(req), } Ok(self) } @@ -392,18 +393,14 @@ fn update_file_notifications_on_threadpool( pool.spawn(move || { for file_id in subscriptions { match handlers::publish_diagnostics(&world, file_id) { - Err(e) => { - error!("failed to compute diagnostics: {:?}", e) - } + Err(e) => error!("failed to compute diagnostics: {:?}", e), Ok(params) => { let not = RawNotification::new::(¶ms); sender.send(Task::Notify(not)); } } match handlers::publish_decorations(&world, file_id) { - Err(e) => { - error!("failed to compute decorations: {:?}", e) - } + Err(e) => error!("failed to compute decorations: {:?}", e), Ok(params) => { let not = RawNotification::new::(¶ms); sender.send(Task::Notify(not)) diff --git a/crates/ra_lsp_server/src/main_loop/subscriptions.rs b/crates/ra_lsp_server/src/main_loop/subscriptions.rs index 31015338287..03f41e8705f 100644 --- a/crates/ra_lsp_server/src/main_loop/subscriptions.rs +++ b/crates/ra_lsp_server/src/main_loop/subscriptions.rs @@ -1,5 +1,5 @@ -use rustc_hash::FxHashSet; use ra_analysis::FileId; +use rustc_hash::FxHashSet; pub struct Subscriptions { subs: FxHashSet, @@ -7,7 +7,9 @@ pub struct Subscriptions { impl Subscriptions { pub fn new() -> Subscriptions { - Subscriptions { subs: FxHashSet::default() } + Subscriptions { + subs: FxHashSet::default(), + } } pub fn add_sub(&mut self, file_id: FileId) { self.subs.insert(file_id); diff --git a/crates/ra_lsp_server/src/path_map.rs b/crates/ra_lsp_server/src/path_map.rs index 19c3b1d3bc1..585013acd3e 100644 --- a/crates/ra_lsp_server/src/path_map.rs +++ b/crates/ra_lsp_server/src/path_map.rs @@ -1,11 +1,13 @@ -use std::path::{PathBuf, Path, Component}; use im; -use relative_path::RelativePath; use ra_analysis::{FileId, FileResolver}; +use relative_path::RelativePath; + +use std::path::{Component, Path, PathBuf}; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Root { - Workspace, Lib + Workspace, + Lib, } #[derive(Debug, Default, Clone)] @@ -21,7 +23,8 @@ impl PathMap { Default::default() } pub fn get_or_insert(&mut self, path: PathBuf, root: Root) -> FileId { - self.path2id.get(path.as_path()) + self.path2id + .get(path.as_path()) .map(|&id| id) .unwrap_or_else(|| { let id = self.new_file_id(); @@ -33,9 +36,7 @@ impl PathMap { self.path2id.get(path).map(|&id| id) } pub fn get_path(&self, file_id: FileId) -> &Path { - self.id2path.get(&file_id) - .unwrap() - .as_path() + self.id2path.get(&file_id).unwrap().as_path() } pub fn get_root(&self, file_id: FileId) -> Root { self.id2root[&file_id] @@ -55,7 +56,12 @@ impl PathMap { impl FileResolver for PathMap { fn file_stem(&self, file_id: FileId) -> String { - self.get_path(file_id).file_stem().unwrap().to_str().unwrap().to_string() + self.get_path(file_id) + .file_stem() + .unwrap() + .to_str() + .unwrap() + .to_string() } fn resolve(&self, file_id: FileId, path: &RelativePath) -> Option { @@ -101,10 +107,6 @@ mod test { let mut m = PathMap::new(); let id1 = m.get_or_insert(PathBuf::from("/foo"), Root::Workspace); let id2 = m.get_or_insert(PathBuf::from("/foo/bar.rs"), Root::Workspace); - assert_eq!( - m.resolve(id1, &RelativePath::new("bar.rs")), - Some(id2), - ) + assert_eq!(m.resolve(id1, &RelativePath::new("bar.rs")), Some(id2),) } } - diff --git a/crates/ra_lsp_server/src/project_model.rs b/crates/ra_lsp_server/src/project_model.rs index c144d95960c..d170ceb7335 100644 --- a/crates/ra_lsp_server/src/project_model.rs +++ b/crates/ra_lsp_server/src/project_model.rs @@ -1,13 +1,12 @@ -use std::{ - path::{Path, PathBuf}, -}; -use rustc_hash::{FxHashMap, FxHashSet}; use cargo_metadata::{metadata_run, CargoOpt}; use ra_syntax::SmolStr; +use rustc_hash::{FxHashMap, FxHashSet}; + +use std::path::{Path, PathBuf}; use crate::{ + thread_watcher::{ThreadWatcher, Worker}, Result, - thread_watcher::{Worker, ThreadWatcher}, }; #[derive(Debug, Clone)] @@ -39,7 +38,12 @@ struct TargetData { #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum TargetKind { - Bin, Lib, Example, Test, Bench, Other, + Bin, + Lib, + Example, + Test, + Bench, + Other, } impl Package { @@ -49,7 +53,7 @@ impl Package { pub fn root(self, ws: &CargoWorkspace) -> &Path { ws.pkg(self).manifest.parent().unwrap() } - pub fn targets<'a>(self, ws: &'a CargoWorkspace) -> impl Iterator + 'a { + pub fn targets<'a>(self, ws: &'a CargoWorkspace) -> impl Iterator + 'a { ws.pkg(self).targets.iter().cloned() } pub fn is_member(self, ws: &CargoWorkspace) -> bool { @@ -78,13 +82,15 @@ impl CargoWorkspace { let meta = metadata_run( Some(cargo_toml.as_path()), true, - Some(CargoOpt::AllFeatures) - ).map_err(|e| format_err!("cargo metadata failed: {}", e))?; + Some(CargoOpt::AllFeatures), + ) + .map_err(|e| format_err!("cargo metadata failed: {}", e))?; let mut pkg_by_id = FxHashMap::default(); let mut packages = Vec::new(); let mut targets = Vec::new(); - let ws_members: FxHashSet = meta.workspace_members + let ws_members: FxHashSet = meta + .workspace_members .into_iter() .map(|it| it.raw) .collect(); @@ -114,7 +120,7 @@ impl CargoWorkspace { Ok(CargoWorkspace { packages, targets }) } - pub fn packages<'a>(&'a self) -> impl Iterator + 'a { + pub fn packages<'a>(&'a self) -> impl Iterator + 'a { (0..self.packages.len()).map(Package) } pub fn target_by_root(&self, root: &Path) -> Option { @@ -155,7 +161,7 @@ impl TargetKind { "example" => TargetKind::Example, _ if kind.contains("lib") => TargetKind::Lib, _ => continue, - } + }; } TargetKind::Other } @@ -170,6 +176,6 @@ pub fn workspace_loader() -> (Worker>, ThreadWat .into_iter() .map(|path| CargoWorkspace::from_cargo_metadata(path.as_path())) .for_each(|it| output_sender.send(it)) - } + }, ) } diff --git a/crates/ra_lsp_server/src/req.rs b/crates/ra_lsp_server/src/req.rs index 1630edf7fae..b76bfbcbc67 100644 --- a/crates/ra_lsp_server/src/req.rs +++ b/crates/ra_lsp_server/src/req.rs @@ -1,20 +1,13 @@ +use languageserver_types::{Location, Position, Range, TextDocumentIdentifier, Url}; use rustc_hash::FxHashMap; -use languageserver_types::{TextDocumentIdentifier, Range, Url, Position, Location}; use url_serde; pub use languageserver_types::{ - request::*, notification::*, - InitializeResult, PublishDiagnosticsParams, - DocumentSymbolParams, DocumentSymbolResponse, - CodeActionParams, ApplyWorkspaceEditParams, - ExecuteCommandParams, - WorkspaceSymbolParams, - TextDocumentPositionParams, - TextEdit, - CompletionParams, CompletionResponse, - DocumentOnTypeFormattingParams, - TextDocumentEdit, - SignatureHelp, Hover + notification::*, request::*, ApplyWorkspaceEditParams, CodeActionParams, CompletionParams, + CompletionResponse, DocumentOnTypeFormattingParams, DocumentSymbolParams, + DocumentSymbolResponse, ExecuteCommandParams, Hover, InitializeResult, + PublishDiagnosticsParams, SignatureHelp, TextDocumentEdit, TextDocumentPositionParams, + TextEdit, WorkspaceSymbolParams, }; pub enum SyntaxTree {} @@ -28,7 +21,7 @@ impl Request for SyntaxTree { #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] pub struct SyntaxTreeParams { - pub text_document: TextDocumentIdentifier + pub text_document: TextDocumentIdentifier, } pub enum ExtendSelection {} @@ -94,7 +87,7 @@ pub struct PublishDecorationsParams { #[serde(rename_all = "camelCase")] pub struct Decoration { pub range: Range, - pub tag: &'static str + pub tag: &'static str, } pub enum ParentModule {} @@ -167,14 +160,14 @@ pub struct SourceChange { pub enum FileSystemEdit { CreateFile { #[serde(with = "url_serde")] - uri: Url + uri: Url, }, MoveFile { #[serde(with = "url_serde")] src: Url, #[serde(with = "url_serde")] dst: Url, - } + }, } pub enum InternalFeedback {} diff --git a/crates/ra_lsp_server/src/server_world.rs b/crates/ra_lsp_server/src/server_world.rs index 9b3013ae8b4..35ff65ea161 100644 --- a/crates/ra_lsp_server/src/server_world.rs +++ b/crates/ra_lsp_server/src/server_world.rs @@ -1,18 +1,18 @@ use std::{ fs, - path::{PathBuf, Path}, + path::{Path, PathBuf}, sync::Arc, }; -use rustc_hash::FxHashMap; use languageserver_types::Url; -use ra_analysis::{FileId, AnalysisHost, Analysis, CrateGraph, CrateId, LibraryData, FileResolver}; +use ra_analysis::{Analysis, AnalysisHost, CrateGraph, CrateId, FileId, FileResolver, LibraryData}; +use rustc_hash::FxHashMap; use crate::{ - Result, path_map::{PathMap, Root}, - vfs::{FileEvent, FileEventKind}, project_model::CargoWorkspace, + vfs::{FileEvent, FileEventKind}, + Result, }; #[derive(Debug)] @@ -42,16 +42,15 @@ impl ServerWorldState { { let pm = &mut self.path_map; let mm = &mut self.mem_map; - let changes = events.into_iter() + let changes = events + .into_iter() .map(|event| { let text = match event.kind { FileEventKind::Add(text) => Some(text), }; (event.path, text) }) - .map(|(path, text)| { - (pm.get_or_insert(path, Root::Workspace), text) - }) + .map(|(path, text)| (pm.get_or_insert(path, Root::Workspace), text)) .filter_map(|(id, text)| { if mm.contains_key(&id) { mm.insert(id, text); @@ -62,12 +61,17 @@ impl ServerWorldState { }); self.analysis_host.change_files(changes); } - self.analysis_host.set_file_resolver(Arc::new(self.path_map.clone())); + self.analysis_host + .set_file_resolver(Arc::new(self.path_map.clone())); } - pub fn events_to_files(&mut self, events: Vec) -> (Vec<(FileId, String)>, Arc) { + pub fn events_to_files( + &mut self, + events: Vec, + ) -> (Vec<(FileId, String)>, Arc) { let files = { let pm = &mut self.path_map; - events.into_iter() + events + .into_iter() .map(|event| { let text = match event.kind { FileEventKind::Add(text) => text, @@ -86,7 +90,8 @@ impl ServerWorldState { pub fn add_mem_file(&mut self, path: PathBuf, text: String) -> FileId { let file_id = self.path_map.get_or_insert(path, Root::Workspace); - self.analysis_host.set_file_resolver(Arc::new(self.path_map.clone())); + self.analysis_host + .set_file_resolver(Arc::new(self.path_map.clone())); self.mem_map.insert(file_id, None); if self.path_map.get_root(file_id) != Root::Lib { self.analysis_host.change_file(file_id, Some(text)); @@ -95,9 +100,10 @@ impl ServerWorldState { } pub fn change_mem_file(&mut self, path: &Path, text: String) -> Result<()> { - let file_id = self.path_map.get_id(path).ok_or_else(|| { - format_err!("change to unknown file: {}", path.display()) - })?; + let file_id = self + .path_map + .get_id(path) + .ok_or_else(|| format_err!("change to unknown file: {}", path.display()))?; if self.path_map.get_root(file_id) != Root::Lib { self.analysis_host.change_file(file_id, Some(text)); } @@ -105,9 +111,10 @@ impl ServerWorldState { } pub fn remove_mem_file(&mut self, path: &Path) -> Result { - let file_id = self.path_map.get_id(path).ok_or_else(|| { - format_err!("change to unknown file: {}", path.display()) - })?; + let file_id = self + .path_map + .get_id(path) + .ok_or_else(|| format_err!("change to unknown file: {}", path.display()))?; match self.mem_map.remove(&file_id) { Some(_) => (), None => bail!("unmatched close notification"), @@ -122,17 +129,17 @@ impl ServerWorldState { pub fn set_workspaces(&mut self, ws: Vec) { let mut crate_roots = FxHashMap::default(); ws.iter() - .flat_map(|ws| { - ws.packages() - .flat_map(move |pkg| pkg.targets(ws)) - .map(move |tgt| tgt.root(ws)) - }) - .for_each(|root| { - if let Some(file_id) = self.path_map.get_id(root) { - let crate_id = CrateId(crate_roots.len() as u32); - crate_roots.insert(crate_id, file_id); - } - }); + .flat_map(|ws| { + ws.packages() + .flat_map(move |pkg| pkg.targets(ws)) + .map(move |tgt| tgt.root(ws)) + }) + .for_each(|root| { + if let Some(file_id) = self.path_map.get_id(root) { + let crate_id = CrateId(crate_roots.len() as u32); + crate_roots.insert(crate_id, file_id); + } + }); let crate_graph = CrateGraph { crate_roots }; self.workspaces = Arc::new(ws); self.analysis_host.set_crate_graph(crate_graph); @@ -141,7 +148,7 @@ impl ServerWorldState { ServerWorld { workspaces: Arc::clone(&self.workspaces), analysis: self.analysis_host.analysis(), - path_map: self.path_map.clone() + path_map: self.path_map.clone(), } } } @@ -152,9 +159,12 @@ impl ServerWorld { } pub fn uri_to_file_id(&self, uri: &Url) -> Result { - let path = uri.to_file_path() + let path = uri + .to_file_path() .map_err(|()| format_err!("invalid uri: {}", uri))?; - self.path_map.get_id(&path).ok_or_else(|| format_err!("unknown file: {}", path.display())) + self.path_map + .get_id(&path) + .ok_or_else(|| format_err!("unknown file: {}", path.display())) } pub fn file_id_to_uri(&self, id: FileId) -> Result { diff --git a/crates/ra_lsp_server/src/thread_watcher.rs b/crates/ra_lsp_server/src/thread_watcher.rs index 3257effcba3..67952eb747a 100644 --- a/crates/ra_lsp_server/src/thread_watcher.rs +++ b/crates/ra_lsp_server/src/thread_watcher.rs @@ -1,7 +1,8 @@ -use std::thread; -use crossbeam_channel::{bounded, unbounded, Sender, Receiver}; -use drop_bomb::DropBomb; use crate::Result; +use crossbeam_channel::{bounded, unbounded, Receiver, Sender}; +use drop_bomb::DropBomb; + +use std::thread; pub struct Worker { pub inp: Sender, @@ -50,11 +51,13 @@ impl ThreadWatcher { info!("waiting for {} to finish ...", self.name); let name = self.name; self.bomb.defuse(); - let res = self.thread.join() + let res = self + .thread + .join() .map_err(|_| format_err!("ThreadWatcher {} died", name)); match &res { Ok(()) => info!("... {} terminated with ok", name), - Err(_) => error!("... {} terminated with err", name) + Err(_) => error!("... {} terminated with err", name), } res } @@ -66,5 +69,9 @@ impl ThreadWatcher { fn worker_chan(buf: usize) -> ((Sender, Receiver), Receiver, Sender) { let (input_sender, input_receiver) = bounded::(buf); let (output_sender, output_receiver) = unbounded::(); - ((input_sender, output_receiver), input_receiver, output_sender) + ( + (input_sender, output_receiver), + input_receiver, + output_sender, + ) } diff --git a/crates/ra_lsp_server/src/vfs.rs b/crates/ra_lsp_server/src/vfs.rs index d8f9b1aac9a..417a3c19ae4 100644 --- a/crates/ra_lsp_server/src/vfs.rs +++ b/crates/ra_lsp_server/src/vfs.rs @@ -1,14 +1,11 @@ use std::{ - path::{PathBuf, Path}, fs, + path::{Path, PathBuf}, }; use walkdir::WalkDir; -use crate::{ - thread_watcher::{Worker, ThreadWatcher}, -}; - +use crate::thread_watcher::{ThreadWatcher, Worker}; #[derive(Debug)] pub struct FileEvent { @@ -24,7 +21,8 @@ pub enum FileEventKind { pub fn roots_loader() -> (Worker)>, ThreadWatcher) { Worker::)>::spawn( "roots loader", - 128, |input_receiver, output_sender| { + 128, + |input_receiver, output_sender| { input_receiver .into_iter() .map(|path| { @@ -34,7 +32,7 @@ pub fn roots_loader() -> (Worker)>, ThreadWatc (path, events) }) .for_each(|it| output_sender.send(it)) - } + }, ) } diff --git a/crates/ra_lsp_server/tests/heavy_tests/main.rs b/crates/ra_lsp_server/tests/heavy_tests/main.rs index 7265b5999e9..8e566d3c8fb 100644 --- a/crates/ra_lsp_server/tests/heavy_tests/main.rs +++ b/crates/ra_lsp_server/tests/heavy_tests/main.rs @@ -1,12 +1,12 @@ #[macro_use] extern crate crossbeam_channel; -extern crate tempdir; +extern crate flexi_logger; +extern crate gen_lsp_server; extern crate languageserver_types; +extern crate ra_lsp_server; extern crate serde; extern crate serde_json; -extern crate gen_lsp_server; -extern crate flexi_logger; -extern crate ra_lsp_server; +extern crate tempdir; mod support; @@ -14,17 +14,18 @@ use ra_lsp_server::req::{Runnables, RunnablesParams}; use crate::support::project; - const LOG: &'static str = ""; #[test] fn test_runnables_no_project() { - let server = project(r" + let server = project( + r" //- lib.rs #[test] fn foo() { } -"); +", + ); server.request::( RunnablesParams { text_document: server.doc_id("lib.rs"), @@ -41,13 +42,14 @@ fn foo() { "start": { "character": 0, "line": 0 } } } - ]"# + ]"#, ); } #[test] fn test_runnables_project() { - let server = project(r#" + let server = project( + r#" //- Cargo.toml [package] name = "foo" @@ -59,7 +61,8 @@ pub fn foo() {} //- tests/spam.rs #[test] fn test_eggs() {} -"#); +"#, + ); server.wait_for_feedback("workspace loaded"); server.request::( RunnablesParams { diff --git a/crates/ra_lsp_server/tests/heavy_tests/support.rs b/crates/ra_lsp_server/tests/heavy_tests/support.rs index d1339f62fcc..004d7e8adde 100644 --- a/crates/ra_lsp_server/tests/heavy_tests/support.rs +++ b/crates/ra_lsp_server/tests/heavy_tests/support.rs @@ -1,34 +1,33 @@ use std::{ - fs, cell::{Cell, RefCell}, + fs, path::PathBuf, - time::Duration, sync::Once, + time::Duration, }; -use tempdir::TempDir; use crossbeam_channel::{after, Receiver}; use flexi_logger::Logger; +use gen_lsp_server::{RawMessage, RawNotification, RawRequest}; use languageserver_types::{ - Url, - TextDocumentIdentifier, - request::{Request, Shutdown}, notification::DidOpenTextDocument, - DidOpenTextDocumentParams, - TextDocumentItem, + request::{Request, Shutdown}, + DidOpenTextDocumentParams, TextDocumentIdentifier, TextDocumentItem, Url, }; use serde::Serialize; -use serde_json::{Value, from_str, to_string_pretty}; -use gen_lsp_server::{RawMessage, RawRequest, RawNotification}; +use serde_json::{from_str, to_string_pretty, Value}; +use tempdir::TempDir; -use ra_lsp_server::{main_loop, req, thread_watcher::{ThreadWatcher, Worker}}; +use ra_lsp_server::{ + main_loop, req, + thread_watcher::{ThreadWatcher, Worker}, +}; pub fn project(fixture: &str) -> Server { static INIT: Once = Once::new(); INIT.call_once(|| Logger::with_env_or_str(crate::LOG).start().unwrap()); - let tmp_dir = TempDir::new("test-project") - .unwrap(); + let tmp_dir = TempDir::new("test-project").unwrap(); let mut buf = String::new(); let mut file_name = None; let mut paths = vec![]; @@ -40,7 +39,7 @@ pub fn project(fixture: &str) -> Server { fs::write(path.as_path(), buf.as_bytes()).unwrap(); paths.push((path, buf.clone())); } - } + }; }; for line in fixture.lines() { if line.starts_with("//-") { @@ -71,9 +70,8 @@ impl Server { "test server", 128, move |mut msg_receiver, mut msg_sender| { - main_loop(true, path, &mut msg_receiver, &mut msg_sender) - .unwrap() - } + main_loop(true, path, &mut msg_receiver, &mut msg_sender).unwrap() + }, ); let res = Server { req_id: Cell::new(1), @@ -91,8 +89,8 @@ impl Server { language_id: "rust".to_string(), version: 0, text, - } - } + }, + }, )) } res @@ -105,11 +103,7 @@ impl Server { } } - pub fn request( - &self, - params: R::Params, - expected_resp: &str, - ) + pub fn request(&self, params: R::Params, expected_resp: &str) where R: Request, R::Params: Serialize, @@ -119,7 +113,8 @@ impl Server { let expected_resp: Value = from_str(expected_resp).unwrap(); let actual = self.send_request::(id, params); assert_eq!( - expected_resp, actual, + expected_resp, + actual, "Expected:\n{}\n\ Actual:\n{}\n", to_string_pretty(&expected_resp).unwrap(), @@ -135,12 +130,9 @@ impl Server { let r = RawRequest::new::(id, ¶ms); self.send_request_(r) } - fn send_request_(&self, r: RawRequest) -> Value - { + fn send_request_(&self, r: RawRequest) -> Value { let id = r.id; - self.worker.as_ref() - .unwrap() - .send(RawMessage::Request(r)); + self.worker.as_ref().unwrap().send(RawMessage::Request(r)); while let Some(msg) = self.recv() { match msg { RawMessage::Request(req) => panic!("unexpected request: {:?}", req), @@ -161,11 +153,10 @@ impl Server { } pub fn wait_for_feedback_n(&self, feedback: &str, n: usize) { let f = |msg: &RawMessage| match msg { - RawMessage::Notification(n) if n.method == "internalFeedback" => { - return n.clone().cast::() - .unwrap() == feedback - } - _ => false, + RawMessage::Notification(n) if n.method == "internalFeedback" => { + return n.clone().cast::().unwrap() == feedback + } + _ => false, }; let mut total = 0; for msg in self.messages.borrow().iter() { @@ -181,14 +172,14 @@ impl Server { } } fn recv(&self) -> Option { - recv_timeout(&self.worker.as_ref().unwrap().out) - .map(|msg| { - self.messages.borrow_mut().push(msg.clone()); - msg - }) + recv_timeout(&self.worker.as_ref().unwrap().out).map(|msg| { + self.messages.borrow_mut().push(msg.clone()); + msg + }) } fn send_notification(&self, not: RawNotification) { - self.worker.as_ref() + self.worker + .as_ref() .unwrap() .send(RawMessage::Notification(not)); } @@ -201,10 +192,7 @@ impl Drop for Server { while let Some(msg) = recv_timeout(&receiver) { drop(msg); } - self.watcher.take() - .unwrap() - .stop() - .unwrap(); + self.watcher.take().unwrap().stop().unwrap(); } } diff --git a/crates/ra_syntax/src/algo/mod.rs b/crates/ra_syntax/src/algo/mod.rs index e686a570442..b4896c48228 100644 --- a/crates/ra_syntax/src/algo/mod.rs +++ b/crates/ra_syntax/src/algo/mod.rs @@ -1,16 +1,18 @@ -pub mod walk; pub mod visit; +pub mod walk; use crate::{ - SyntaxNodeRef, TextUnit, TextRange, text_utils::{contains_offset_nonstrict, is_subrange}, + SyntaxNodeRef, TextRange, TextUnit, }; pub fn find_leaf_at_offset(node: SyntaxNodeRef, offset: TextUnit) -> LeafAtOffset { let range = node.range(); assert!( contains_offset_nonstrict(range, offset), - "Bad offset: range {:?} offset {:?}", range, offset + "Bad offset: range {:?} offset {:?}", + range, + offset ); if range.is_empty() { return LeafAtOffset::None; @@ -20,20 +22,23 @@ pub fn find_leaf_at_offset(node: SyntaxNodeRef, offset: TextUnit) -> LeafAtOffse return LeafAtOffset::Single(node); } - let mut children = node.children() - .filter(|child| { - let child_range = child.range(); - !child_range.is_empty() && contains_offset_nonstrict(child_range, offset) - }); + let mut children = node.children().filter(|child| { + let child_range = child.range(); + !child_range.is_empty() && contains_offset_nonstrict(child_range, offset) + }); let left = children.next().unwrap(); let right = children.next(); assert!(children.next().is_none()); return if let Some(right) = right { - match (find_leaf_at_offset(left, offset), find_leaf_at_offset(right, offset)) { - (LeafAtOffset::Single(left), LeafAtOffset::Single(right)) => - LeafAtOffset::Between(left, right), - _ => unreachable!() + match ( + find_leaf_at_offset(left, offset), + find_leaf_at_offset(right, offset), + ) { + (LeafAtOffset::Single(left), LeafAtOffset::Single(right)) => { + LeafAtOffset::Between(left, right) + } + _ => unreachable!(), } } else { find_leaf_at_offset(left, offset) @@ -44,7 +49,7 @@ pub fn find_leaf_at_offset(node: SyntaxNodeRef, offset: TextUnit) -> LeafAtOffse pub enum LeafAtOffset<'a> { None, Single(SyntaxNodeRef<'a>), - Between(SyntaxNodeRef<'a>, SyntaxNodeRef<'a>) + Between(SyntaxNodeRef<'a>, SyntaxNodeRef<'a>), } impl<'a> LeafAtOffset<'a> { @@ -52,7 +57,7 @@ impl<'a> LeafAtOffset<'a> { match self { LeafAtOffset::None => None, LeafAtOffset::Single(node) => Some(node), - LeafAtOffset::Between(_, right) => Some(right) + LeafAtOffset::Between(_, right) => Some(right), } } @@ -60,7 +65,7 @@ impl<'a> LeafAtOffset<'a> { match self { LeafAtOffset::None => None, LeafAtOffset::Single(node) => Some(node), - LeafAtOffset::Between(left, _) => Some(left) + LeafAtOffset::Between(left, _) => Some(left), } } } @@ -71,8 +76,14 @@ impl<'f> Iterator for LeafAtOffset<'f> { fn next(&mut self) -> Option> { match *self { LeafAtOffset::None => None, - LeafAtOffset::Single(node) => { *self = LeafAtOffset::None; Some(node) } - LeafAtOffset::Between(left, right) => { *self = LeafAtOffset::Single(right); Some(left) } + LeafAtOffset::Single(node) => { + *self = LeafAtOffset::None; + Some(node) + } + LeafAtOffset::Between(left, right) => { + *self = LeafAtOffset::Single(right); + Some(left) + } } } } @@ -81,14 +92,15 @@ pub fn find_covering_node(root: SyntaxNodeRef, range: TextRange) -> SyntaxNodeRe assert!( is_subrange(root.range(), range), "node range: {:?}, target range: {:?}", - root.range(), range, + root.range(), + range, ); let (left, right) = match ( find_leaf_at_offset(root, range.start()).right_biased(), - find_leaf_at_offset(root, range.end()).left_biased() + find_leaf_at_offset(root, range.end()).left_biased(), ) { (Some(l), Some(r)) => (l, r), - _ => return root + _ => return root, }; common_ancestor(left, right) @@ -103,7 +115,7 @@ fn common_ancestor<'a>(n1: SyntaxNodeRef<'a>, n2: SyntaxNodeRef<'a>) -> SyntaxNo panic!("Can't find common ancestor of {:?} and {:?}", n1, n2) } -pub fn generate(seed: Option, step: impl Fn(&T) -> Option) -> impl Iterator { +pub fn generate(seed: Option, step: impl Fn(&T) -> Option) -> impl Iterator { ::itertools::unfold(seed, move |slot| { slot.take().map(|curr| { *slot = step(&curr); diff --git a/crates/ra_syntax/src/algo/visit.rs b/crates/ra_syntax/src/algo/visit.rs index 1ae988a8777..c021f464c3f 100644 --- a/crates/ra_syntax/src/algo/visit.rs +++ b/crates/ra_syntax/src/algo/visit.rs @@ -1,23 +1,31 @@ +use crate::{AstNode, SyntaxNodeRef}; + use std::marker::PhantomData; -use crate::{SyntaxNodeRef, AstNode}; - -pub fn visitor<'a, T>() -> impl Visitor<'a, Output=T> { +pub fn visitor<'a, T>() -> impl Visitor<'a, Output = T> { EmptyVisitor { ph: PhantomData } } -pub fn visitor_ctx<'a, T, C>(ctx: C) -> impl VisitorCtx<'a, Output=T, Ctx=C> { - EmptyVisitorCtx { ph: PhantomData, ctx } +pub fn visitor_ctx<'a, T, C>(ctx: C) -> impl VisitorCtx<'a, Output = T, Ctx = C> { + EmptyVisitorCtx { + ph: PhantomData, + ctx, + } } pub trait Visitor<'a>: Sized { type Output; fn accept(self, node: SyntaxNodeRef<'a>) -> Option; fn visit(self, f: F) -> Vis - where N: AstNode<'a>, - F: FnOnce(N) -> Self::Output, + where + N: AstNode<'a>, + F: FnOnce(N) -> Self::Output, { - Vis { inner: self, f, ph: PhantomData } + Vis { + inner: self, + f, + ph: PhantomData, + } } } @@ -26,16 +34,21 @@ pub trait VisitorCtx<'a>: Sized { type Ctx; fn accept(self, node: SyntaxNodeRef<'a>) -> Result; fn visit(self, f: F) -> VisCtx - where N: AstNode<'a>, - F: FnOnce(N, Self::Ctx) -> Self::Output, + where + N: AstNode<'a>, + F: FnOnce(N, Self::Ctx) -> Self::Output, { - VisCtx { inner: self, f, ph: PhantomData } + VisCtx { + inner: self, + f, + ph: PhantomData, + } } } #[derive(Debug)] struct EmptyVisitor { - ph: PhantomData T> + ph: PhantomData T>, } impl<'a, T> Visitor<'a> for EmptyVisitor { @@ -69,10 +82,10 @@ pub struct Vis { } impl<'a, V, N, F> Visitor<'a> for Vis - where - V: Visitor<'a>, - N: AstNode<'a>, - F: FnOnce(N) -> >::Output, +where + V: Visitor<'a>, + N: AstNode<'a>, + F: FnOnce(N) -> >::Output, { type Output = >::Output; @@ -90,21 +103,19 @@ pub struct VisCtx { } impl<'a, V, N, F> VisitorCtx<'a> for VisCtx - where - V: VisitorCtx<'a>, - N: AstNode<'a>, - F: FnOnce(N, >::Ctx) -> >::Output, +where + V: VisitorCtx<'a>, + N: AstNode<'a>, + F: FnOnce(N, >::Ctx) -> >::Output, { type Output = >::Output; type Ctx = >::Ctx; fn accept(self, node: SyntaxNodeRef<'a>) -> Result { let VisCtx { inner, f, .. } = self; - inner.accept(node).or_else(|ctx| - match N::cast(node) { - None => Err(ctx), - Some(node) => Ok(f(node, ctx)) - } - ) + inner.accept(node).or_else(|ctx| match N::cast(node) { + None => Err(ctx), + Some(node) => Ok(f(node, ctx)), + }) } } diff --git a/crates/ra_syntax/src/algo/walk.rs b/crates/ra_syntax/src/algo/walk.rs index d3441562623..9afa86401bf 100644 --- a/crates/ra_syntax/src/algo/walk.rs +++ b/crates/ra_syntax/src/algo/walk.rs @@ -1,8 +1,4 @@ -use crate::{ - SyntaxNodeRef, - algo::generate, -}; - +use crate::{algo::generate, SyntaxNodeRef}; #[derive(Debug, Copy, Clone)] pub enum WalkEvent<'a> { diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 160d186b8d8..a15e0017692 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs @@ -1,6 +1,8 @@ // This file is automatically generated based on the file `./generated.rs.tera` when `cargo gen-kinds` is run // Do not edit manually +#![cfg_attr(rustfmt, rustfmt_skip)] + use crate::{ ast, SyntaxNodeRef, AstNode, diff --git a/crates/ra_syntax/src/ast/generated.rs.tera b/crates/ra_syntax/src/ast/generated.rs.tera index 5cb7a35ed91..d2a281137e1 100644 --- a/crates/ra_syntax/src/ast/generated.rs.tera +++ b/crates/ra_syntax/src/ast/generated.rs.tera @@ -3,6 +3,8 @@ the below applies to the result of this template #}// This file is automatically generated based on the file `./generated.rs.tera` when `cargo gen-kinds` is run // Do not edit manually +#![cfg_attr(rustfmt, rustfmt_skip)] + use crate::{ ast, SyntaxNodeRef, AstNode, diff --git a/crates/ra_syntax/src/ast/mod.rs b/crates/ra_syntax/src/ast/mod.rs index 88193a1edec..34958b6cb3b 100644 --- a/crates/ra_syntax/src/ast/mod.rs +++ b/crates/ra_syntax/src/ast/mod.rs @@ -4,15 +4,18 @@ use std::marker::PhantomData; use itertools::Itertools; -use crate::{ - SmolStr, SyntaxNodeRef, SyntaxKind::*, - yellow::{RefRoot, SyntaxNodeChildren}, -}; pub use self::generated::*; +use crate::{ + yellow::{RefRoot, SyntaxNodeChildren}, + SmolStr, + SyntaxKind::*, + SyntaxNodeRef, +}; pub trait AstNode<'a>: Clone + Copy + 'a { fn cast(syntax: SyntaxNodeRef<'a>) -> Option - where Self: Sized; + where + Self: Sized; fn syntax(self) -> SyntaxNodeRef<'a>; } @@ -64,9 +67,7 @@ pub trait AttrsOwner<'a>: AstNode<'a> { impl<'a> FnDef<'a> { pub fn has_atom_attr(&self, atom: &str) -> bool { - self.attrs() - .filter_map(|x| x.as_atom()) - .any(|x| x == atom) + self.attrs().filter_map(|x| x.as_atom()).any(|x| x == atom) } } @@ -135,7 +136,7 @@ pub enum CommentFlavor { Line, Doc, ModuleDoc, - Multiline + Multiline, } impl CommentFlavor { @@ -145,7 +146,7 @@ impl CommentFlavor { Line => "//", Doc => "///", ModuleDoc => "//!", - Multiline => "/*" + Multiline => "/*", } } } @@ -166,16 +167,14 @@ impl<'a> Whitespace<'a> { impl<'a> Name<'a> { pub fn text(&self) -> SmolStr { - let ident = self.syntax().first_child() - .unwrap(); + let ident = self.syntax().first_child().unwrap(); ident.leaf_text().unwrap().clone() } } impl<'a> NameRef<'a> { pub fn text(&self) -> SmolStr { - let ident = self.syntax().first_child() - .unwrap(); + let ident = self.syntax().first_child().unwrap(); ident.leaf_text().unwrap().clone() } } @@ -241,7 +240,6 @@ fn children<'a, P: AstNode<'a>, C: AstNode<'a>>(parent: P) -> AstChildren<'a, C> AstChildren::new(parent.syntax()) } - #[derive(Debug)] pub struct AstChildren<'a, N> { inner: SyntaxNodeChildren>, diff --git a/crates/ra_syntax/src/grammar/expressions/atom.rs b/crates/ra_syntax/src/grammar/expressions/atom.rs index e21de68c5bd..11f766d3356 100644 --- a/crates/ra_syntax/src/grammar/expressions/atom.rs +++ b/crates/ra_syntax/src/grammar/expressions/atom.rs @@ -13,9 +13,18 @@ use super::*; // let _ = b"e"; // let _ = br"f"; // } -pub(crate) const LITERAL_FIRST: TokenSet = - token_set![TRUE_KW, FALSE_KW, INT_NUMBER, FLOAT_NUMBER, BYTE, CHAR, - STRING, RAW_STRING, BYTE_STRING, RAW_BYTE_STRING]; +pub(crate) const LITERAL_FIRST: TokenSet = token_set![ + TRUE_KW, + FALSE_KW, + INT_NUMBER, + FLOAT_NUMBER, + BYTE, + CHAR, + STRING, + RAW_STRING, + BYTE_STRING, + RAW_BYTE_STRING +]; pub(crate) fn literal(p: &mut Parser) -> Option { if !p.at_ts(LITERAL_FIRST) { @@ -26,15 +35,31 @@ pub(crate) fn literal(p: &mut Parser) -> Option { Some(m.complete(p, LITERAL)) } -pub(super) const ATOM_EXPR_FIRST: TokenSet = - token_set_union![ - LITERAL_FIRST, - token_set![L_CURLY, L_PAREN, L_BRACK, PIPE, MOVE_KW, IF_KW, WHILE_KW, MATCH_KW, UNSAFE_KW, - RETURN_KW, IDENT, SELF_KW, SUPER_KW, CRATE_KW, COLONCOLON, BREAK_KW, CONTINUE_KW, LIFETIME ], - ]; +pub(super) const ATOM_EXPR_FIRST: TokenSet = token_set_union![ + LITERAL_FIRST, + token_set![ + L_CURLY, + L_PAREN, + L_BRACK, + PIPE, + MOVE_KW, + IF_KW, + WHILE_KW, + MATCH_KW, + UNSAFE_KW, + RETURN_KW, + IDENT, + SELF_KW, + SUPER_KW, + CRATE_KW, + COLONCOLON, + BREAK_KW, + CONTINUE_KW, + LIFETIME + ], +]; -const EXPR_RECOVERY_SET: TokenSet = - token_set![LET_KW]; +const EXPR_RECOVERY_SET: TokenSet = token_set![LET_KW]; pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option { match literal(p) { @@ -80,7 +105,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option block_expr(p, None), RETURN_KW => return_expr(p), CONTINUE_KW => continue_expr(p), @@ -119,7 +144,14 @@ fn tuple_expr(p: &mut Parser) -> CompletedMarker { } } p.expect(R_PAREN); - m.complete(p, if saw_expr && !saw_comma { PAREN_EXPR } else { TUPLE_EXPR }) + m.complete( + p, + if saw_expr && !saw_comma { + PAREN_EXPR + } else { + TUPLE_EXPR + }, + ) } // test array_expr diff --git a/crates/ra_syntax/src/grammar/expressions/mod.rs b/crates/ra_syntax/src/grammar/expressions/mod.rs index 20e0fa3289e..60c8602f9f0 100644 --- a/crates/ra_syntax/src/grammar/expressions/mod.rs +++ b/crates/ra_syntax/src/grammar/expressions/mod.rs @@ -1,23 +1,32 @@ mod atom; -use super::*; -pub(super) use self::atom::{literal, LITERAL_FIRST}; pub(crate) use self::atom::match_arm_list; +pub(super) use self::atom::{literal, LITERAL_FIRST}; +use super::*; const EXPR_FIRST: TokenSet = LHS_FIRST; pub(super) fn expr(p: &mut Parser) -> BlockLike { - let r = Restrictions { forbid_structs: false, prefer_stmt: false }; + let r = Restrictions { + forbid_structs: false, + prefer_stmt: false, + }; expr_bp(p, r, 1) } pub(super) fn expr_stmt(p: &mut Parser) -> BlockLike { - let r = Restrictions { forbid_structs: false, prefer_stmt: true }; + let r = Restrictions { + forbid_structs: false, + prefer_stmt: true, + }; expr_bp(p, r, 1) } fn expr_no_struct(p: &mut Parser) { - let r = Restrictions { forbid_structs: true, prefer_stmt: false }; + let r = Restrictions { + forbid_structs: true, + prefer_stmt: false, + }; expr_bp(p, r, 1); } @@ -107,10 +116,8 @@ enum Op { fn current_op(p: &Parser) -> (u8, Op) { if let Some(t) = p.next3() { match t { - (L_ANGLE, L_ANGLE, EQ) => - return (1, Op::Composite(SHLEQ, 3)), - (R_ANGLE, R_ANGLE, EQ) => - return (1, Op::Composite(SHREQ, 3)), + (L_ANGLE, L_ANGLE, EQ) => return (1, Op::Composite(SHLEQ, 3)), + (R_ANGLE, R_ANGLE, EQ) => return (1, Op::Composite(SHREQ, 3)), _ => (), } } @@ -201,11 +208,10 @@ fn is_block(kind: SyntaxKind) -> bool { } } -const LHS_FIRST: TokenSet = - token_set_union![ - token_set![AMP, STAR, EXCL, DOTDOT, MINUS], - atom::ATOM_EXPR_FIRST, - ]; +const LHS_FIRST: TokenSet = token_set_union![ + token_set![AMP, STAR, EXCL, DOTDOT, MINUS], + atom::ATOM_EXPR_FIRST, +]; fn lhs(p: &mut Parser, r: Restrictions) -> Option { let m; @@ -265,11 +271,13 @@ fn postfix_expr(p: &mut Parser, r: Restrictions, mut lhs: CompletedMarker) -> Co // } L_PAREN if allow_calls => call_expr(p, lhs), L_BRACK if allow_calls => index_expr(p, lhs), - DOT if p.nth(1) == IDENT => if p.nth(2) == L_PAREN || p.nth(2) == COLONCOLON { - method_call_expr(p, lhs) - } else { - field_expr(p, lhs) - }, + DOT if p.nth(1) == IDENT => { + if p.nth(2) == L_PAREN || p.nth(2) == COLONCOLON { + method_call_expr(p, lhs) + } else { + field_expr(p, lhs) + } + } DOT if p.nth(1) == INT_NUMBER => field_expr(p, lhs), // test postfix_range // fn foo() { let x = 1..; } @@ -318,10 +326,7 @@ fn index_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { // y.bar::(1, 2,); // } fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { - assert!( - p.at(DOT) && p.nth(1) == IDENT - && (p.nth(2) == L_PAREN || p.nth(2) == COLONCOLON) - ); + assert!(p.at(DOT) && p.nth(1) == IDENT && (p.nth(2) == L_PAREN || p.nth(2) == COLONCOLON)); let m = lhs.precede(p); p.bump(); name_ref(p); @@ -410,7 +415,7 @@ fn path_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker { items::macro_call_after_excl(p); m.complete(p, MACRO_CALL) } - _ => m.complete(p, PATH_EXPR) + _ => m.complete(p, PATH_EXPR), } } diff --git a/crates/ra_syntax/src/grammar/items/mod.rs b/crates/ra_syntax/src/grammar/items/mod.rs index 2567313ab1c..dc4742bce95 100644 --- a/crates/ra_syntax/src/grammar/items/mod.rs +++ b/crates/ra_syntax/src/grammar/items/mod.rs @@ -1,16 +1,15 @@ - mod consts; mod nominal; mod traits; mod use_item; -use super::*; pub(crate) use self::{ - expressions::{named_field_list, match_arm_list}, + expressions::{match_arm_list, named_field_list}, nominal::{enum_variant_list, named_field_def_list}, - traits::{trait_item_list, impl_item_list}, + traits::{impl_item_list, trait_item_list}, use_item::use_tree_list, }; +use super::*; // test mod_contents // fn foo() {} @@ -26,12 +25,14 @@ pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) { } pub(super) enum ItemFlavor { - Mod, Trait + Mod, + Trait, } -const ITEM_RECOVERY_SET: TokenSet = - token_set![FN_KW, STRUCT_KW, ENUM_KW, IMPL_KW, TRAIT_KW, CONST_KW, STATIC_KW, LET_KW, - MOD_KW, PUB_KW, CRATE_KW]; +const ITEM_RECOVERY_SET: TokenSet = token_set![ + FN_KW, STRUCT_KW, ENUM_KW, IMPL_KW, TRAIT_KW, CONST_KW, STATIC_KW, LET_KW, MOD_KW, PUB_KW, + CRATE_KW +]; pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemFlavor) { let m = p.start(); @@ -153,10 +154,12 @@ pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem { traits::impl_item(p); IMPL_ITEM } - _ => return if has_mods { - MaybeItem::Modifiers - } else { - MaybeItem::None + _ => { + return if has_mods { + MaybeItem::Modifiers + } else { + MaybeItem::None + } } }; @@ -194,7 +197,7 @@ fn items_without_modifiers(p: &mut Parser) -> Option { if p.at(SEMI) { p.err_and_bump( "expected item, found `;`\n\ - consider removing this semicolon" + consider removing this semicolon", ); } STRUCT_DEF @@ -227,7 +230,9 @@ fn items_without_modifiers(p: &mut Parser) -> Option { } // test extern_block // extern {} - EXTERN_KW if la == L_CURLY || ((la == STRING || la == RAW_STRING) && p.nth(2) == L_CURLY) => { + EXTERN_KW + if la == L_CURLY || ((la == STRING || la == RAW_STRING) && p.nth(2) == L_CURLY) => + { abi(p); extern_item_list(p); EXTERN_BLOCK @@ -267,10 +272,8 @@ fn fn_def(p: &mut Parser, flavor: ItemFlavor) { if p.at(L_PAREN) { match flavor { - ItemFlavor::Mod => - params::param_list(p), - ItemFlavor::Trait => - params::param_list_opt_patterns(p), + ItemFlavor::Mod => params::param_list(p), + ItemFlavor::Trait => params::param_list_opt_patterns(p), } } else { p.error("expected function arguments"); @@ -361,7 +364,7 @@ pub(super) fn macro_call_after_excl(p: &mut Parser) -> BlockLike { _ => { p.error("expected `{`, `[`, `(`"); BlockLike::NotBlock - }, + } }; flavor @@ -385,9 +388,9 @@ pub(crate) fn token_tree(p: &mut Parser) { return; } R_PAREN | R_BRACK => p.err_and_bump("unmatched brace"), - _ => p.bump() + _ => p.bump(), } - }; + } p.expect(closing_paren_kind); m.complete(p, TOKEN_TREE); } diff --git a/crates/ra_syntax/src/grammar/items/traits.rs b/crates/ra_syntax/src/grammar/items/traits.rs index 5dfdb470ca8..31258c25373 100644 --- a/crates/ra_syntax/src/grammar/items/traits.rs +++ b/crates/ra_syntax/src/grammar/items/traits.rs @@ -128,4 +128,3 @@ pub(crate) fn impl_type(p: &mut Parser) { } types::type_(p); } - diff --git a/crates/ra_syntax/src/grammar/mod.rs b/crates/ra_syntax/src/grammar/mod.rs index 1199ba2300e..c875640730a 100644 --- a/crates/ra_syntax/src/grammar/mod.rs +++ b/crates/ra_syntax/src/grammar/mod.rs @@ -31,28 +31,18 @@ mod type_args; mod type_params; mod types; -use crate::{ - token_set::TokenSet, - parser_api::{Marker, CompletedMarker, Parser}, - SyntaxKind::{self, *}, -}; pub(crate) use self::{ - expressions::{ - block, - }, + expressions::block, items::{ - enum_variant_list, - extern_item_list, - impl_item_list, - match_arm_list, - mod_item_list, - named_field_def_list, - named_field_list, - token_tree, - trait_item_list, - use_tree_list, + enum_variant_list, extern_item_list, impl_item_list, match_arm_list, mod_item_list, + named_field_def_list, named_field_list, token_tree, trait_item_list, use_tree_list, }, }; +use crate::{ + parser_api::{CompletedMarker, Marker, Parser}, + token_set::TokenSet, + SyntaxKind::{self, *}, +}; pub(crate) fn root(p: &mut Parser) { let m = p.start(); @@ -61,7 +51,6 @@ pub(crate) fn root(p: &mut Parser) { m.complete(p, ROOT); } - #[derive(Clone, Copy, PartialEq, Eq)] enum BlockLike { Block, @@ -69,7 +58,9 @@ enum BlockLike { } impl BlockLike { - fn is_block(self) -> bool { self == BlockLike::Block } + fn is_block(self) -> bool { + self == BlockLike::Block + } } fn opt_visibility(p: &mut Parser) { diff --git a/crates/ra_syntax/src/grammar/params.rs b/crates/ra_syntax/src/grammar/params.rs index 903c2593998..b71a72ca3e9 100644 --- a/crates/ra_syntax/src/grammar/params.rs +++ b/crates/ra_syntax/src/grammar/params.rs @@ -61,12 +61,8 @@ fn list_(p: &mut Parser, flavor: Flavor) { m.complete(p, PARAM_LIST); } - const VALUE_PARAMETER_FIRST: TokenSet = - token_set_union![ - patterns::PATTERN_FIRST, - types::TYPE_FIRST, - ]; + token_set_union![patterns::PATTERN_FIRST, types::TYPE_FIRST,]; fn value_parameter(p: &mut Parser, flavor: Flavor) { let m = p.start(); @@ -76,7 +72,7 @@ fn value_parameter(p: &mut Parser, flavor: Flavor) { if p.at(COLON) || flavor.type_required() { types::ascription(p) } - }, + } // test value_parameters_no_patterns // type F = Box; Flavor::OptionalPattern => { @@ -86,13 +82,14 @@ fn value_parameter(p: &mut Parser, flavor: Flavor) { let la3 = p.nth(3); if la0 == IDENT && la1 == COLON || la0 == AMP && la1 == IDENT && la2 == COLON - || la0 == AMP && la1 == MUT_KW && la2 == IDENT && la3 == COLON { + || la0 == AMP && la1 == MUT_KW && la2 == IDENT && la3 == COLON + { patterns::pattern(p); types::ascription(p); } else { types::type_(p); } - }, + } } m.complete(p, PARAM); } diff --git a/crates/ra_syntax/src/grammar/paths.rs b/crates/ra_syntax/src/grammar/paths.rs index b6d44d53af3..a35a339ccac 100644 --- a/crates/ra_syntax/src/grammar/paths.rs +++ b/crates/ra_syntax/src/grammar/paths.rs @@ -97,7 +97,7 @@ fn opt_path_type_args(p: &mut Parser, mode: Mode) { } else { type_args::opt_type_arg_list(p, false) } - }, + } Mode::Expr => type_args::opt_type_arg_list(p, true), } } diff --git a/crates/ra_syntax/src/grammar/patterns.rs b/crates/ra_syntax/src/grammar/patterns.rs index 420bae7a77e..9d35dbb3d8d 100644 --- a/crates/ra_syntax/src/grammar/patterns.rs +++ b/crates/ra_syntax/src/grammar/patterns.rs @@ -1,11 +1,10 @@ use super::*; -pub(super) const PATTERN_FIRST: TokenSet = - token_set_union![ - token_set![REF_KW, MUT_KW, L_PAREN, L_BRACK, AMP, UNDERSCORE], - expressions::LITERAL_FIRST, - paths::PATH_FIRST, - ]; +pub(super) const PATTERN_FIRST: TokenSet = token_set_union![ + token_set![REF_KW, MUT_KW, L_PAREN, L_BRACK, AMP, UNDERSCORE], + expressions::LITERAL_FIRST, + paths::PATH_FIRST, +]; pub(super) fn pattern(p: &mut Parser) { pattern_r(p, PAT_RECOVERY_SET) @@ -29,12 +28,13 @@ pub(super) fn pattern_r(p: &mut Parser, recovery_set: TokenSet) { const PAT_RECOVERY_SET: TokenSet = token_set![LET_KW, IF_KW, WHILE_KW, LOOP_KW, MATCH_KW, R_PAREN, COMMA]; - fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option { let la0 = p.nth(0); let la1 = p.nth(1); - if la0 == REF_KW || la0 == MUT_KW - || (la0 == IDENT && !(la1 == COLONCOLON || la1 == L_PAREN || la1 == L_CURLY)) { + if la0 == REF_KW + || la0 == MUT_KW + || (la0 == IDENT && !(la1 == COLONCOLON || la1 == L_PAREN || la1 == L_CURLY)) + { return Some(bind_pat(p, true)); } if paths::is_path_start(p) { @@ -87,7 +87,7 @@ fn path_pat(p: &mut Parser) -> CompletedMarker { field_pat_list(p); STRUCT_PAT } - _ => PATH_PAT + _ => PATH_PAT, }; m.complete(p, kind) } @@ -195,7 +195,7 @@ fn pat_list(p: &mut Parser, ket: SyntaxKind) { break; } pattern(p) - }, + } } if !p.at(ket) { p.expect(COMMA); diff --git a/crates/ra_syntax/src/grammar/type_params.rs b/crates/ra_syntax/src/grammar/type_params.rs index 79bc95ce414..79f5036b415 100644 --- a/crates/ra_syntax/src/grammar/type_params.rs +++ b/crates/ra_syntax/src/grammar/type_params.rs @@ -72,12 +72,8 @@ pub(super) fn bounds_without_colon(p: &mut Parser) { p.eat(QUESTION); match p.current() { LIFETIME => p.bump(), - FOR_KW => { - types::for_type(p) - } - _ if paths::is_path_start(p) => { - types::path_type(p) - } + FOR_KW => types::for_type(p), + _ if paths::is_path_start(p) => types::path_type(p), _ => break, } if has_paren { @@ -104,7 +100,7 @@ pub(super) fn opt_where_clause(p: &mut Parser) { p.bump(); loop { if !(paths::is_path_start(p) || p.current() == LIFETIME) { - break + break; } where_predicate(p); if p.current() != L_CURLY && p.current() != SEMI { @@ -130,7 +126,6 @@ fn where_predicate(p: &mut Parser) { } else { p.error("expected colon") } - } m.complete(p, WHERE_PRED); } diff --git a/crates/ra_syntax/src/grammar/types.rs b/crates/ra_syntax/src/grammar/types.rs index 27e5b086e3d..f308aef894e 100644 --- a/crates/ra_syntax/src/grammar/types.rs +++ b/crates/ra_syntax/src/grammar/types.rs @@ -1,15 +1,14 @@ use super::*; -pub(super) const TYPE_FIRST: TokenSet = - token_set_union![ - token_set![ - L_PAREN, EXCL, STAR, L_BRACK, AMP, UNDERSCORE, FN_KW, UNSAFE_KW, EXTERN_KW, FOR_KW, IMPL_KW, DYN_KW, L_ANGLE, - ], - paths::PATH_FIRST, - ]; +pub(super) const TYPE_FIRST: TokenSet = token_set_union![ + token_set![ + L_PAREN, EXCL, STAR, L_BRACK, AMP, UNDERSCORE, FN_KW, UNSAFE_KW, EXTERN_KW, FOR_KW, + IMPL_KW, DYN_KW, L_ANGLE, + ], + paths::PATH_FIRST, +]; -const TYPE_RECOVERY_SET: TokenSet = - token_set![R_PAREN, COMMA]; +const TYPE_RECOVERY_SET: TokenSet = token_set![R_PAREN, COMMA]; pub(super) fn type_(p: &mut Parser) { match p.current() { @@ -200,7 +199,6 @@ pub(super) fn for_type(p: &mut Parser) { FN_KW | UNSAFE_KW | EXTERN_KW => fn_pointer_type(p), _ if paths::is_path_start(p) => path_type_(p, false), _ => p.error("expected a path"), - } m.complete(p, FOR_TYPE); } diff --git a/crates/ra_syntax/src/lexer/mod.rs b/crates/ra_syntax/src/lexer/mod.rs index 9dc0b63d6b8..f388da273fa 100644 --- a/crates/ra_syntax/src/lexer/mod.rs +++ b/crates/ra_syntax/src/lexer/mod.rs @@ -58,12 +58,16 @@ fn next_token_inner(c: char, ptr: &mut Ptr) -> SyntaxKind { } match c { - '#' => if scan_shebang(ptr) { - return SHEBANG; - }, - '/' => if let Some(kind) = scan_comment(ptr) { - return kind; - }, + '#' => { + if scan_shebang(ptr) { + return SHEBANG; + } + } + '/' => { + if let Some(kind) = scan_comment(ptr) { + return kind; + } + } _ => (), } diff --git a/crates/ra_syntax/src/lexer/ptr.rs b/crates/ra_syntax/src/lexer/ptr.rs index c4708cb1c95..fa79d8862a4 100644 --- a/crates/ra_syntax/src/lexer/ptr.rs +++ b/crates/ra_syntax/src/lexer/ptr.rs @@ -134,10 +134,10 @@ mod tests { #[test] fn test_nth_is_p() { let ptr = Ptr::new("test"); - assert!(ptr.nth_is_p(0,|c| c == 't')); - assert!(!ptr.nth_is_p(1,|c| c == 't')); - assert!(ptr.nth_is_p(3,|c| c == 't')); - assert!(!ptr.nth_is_p(150,|c| c == 't')); + assert!(ptr.nth_is_p(0, |c| c == 't')); + assert!(!ptr.nth_is_p(1, |c| c == 't')); + assert!(ptr.nth_is_p(3, |c| c == 't')); + assert!(!ptr.nth_is_p(150, |c| c == 't')); } #[test] diff --git a/crates/ra_syntax/src/lexer/strings.rs b/crates/ra_syntax/src/lexer/strings.rs index bceacdcac20..5090feae649 100644 --- a/crates/ra_syntax/src/lexer/strings.rs +++ b/crates/ra_syntax/src/lexer/strings.rs @@ -71,7 +71,7 @@ pub(crate) fn scan_string(ptr: &mut Ptr) { } _ => { ptr.bump(); - }, + } } } } @@ -90,7 +90,7 @@ pub(crate) fn scan_raw_string(ptr: &mut Ptr) { while let Some(c) = ptr.bump() { if c == '"' { let mut hashes_left = hashes; - while ptr.at('#') && hashes_left > 0{ + while ptr.at('#') && hashes_left > 0 { hashes_left -= 1; ptr.bump(); } diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs index 7eba5ee614f..7a9718aad4d 100644 --- a/crates/ra_syntax/src/lib.rs +++ b/crates/ra_syntax/src/lib.rs @@ -20,11 +20,11 @@ #![allow(missing_docs)] //#![warn(unreachable_pub)] // rust-lang/rust#47816 -extern crate itertools; -extern crate unicode_xid; extern crate drop_bomb; +extern crate itertools; extern crate parking_lot; extern crate rowan; +extern crate unicode_xid; #[cfg(test)] #[macro_use] @@ -35,33 +35,31 @@ pub mod ast; mod lexer; #[macro_use] mod token_set; -mod parser_api; mod grammar; +mod parser_api; mod parser_impl; mod reparsing; mod syntax_kinds; -mod yellow; +pub mod text_utils; /// Utilities for simple uses of the parser. pub mod utils; -pub mod text_utils; +mod yellow; pub use crate::{ - rowan::{SmolStr, TextRange, TextUnit}, ast::AstNode, lexer::{tokenize, Token}, - syntax_kinds::SyntaxKind, - yellow::{SyntaxNode, SyntaxNodeRef, OwnedRoot, RefRoot, TreeRoot, SyntaxError, Direction}, reparsing::AtomEdit, + rowan::{SmolStr, TextRange, TextUnit}, + syntax_kinds::SyntaxKind, + yellow::{Direction, OwnedRoot, RefRoot, SyntaxError, SyntaxNode, SyntaxNodeRef, TreeRoot}, }; -use crate::{ - yellow::{GreenNode}, -}; +use crate::yellow::GreenNode; #[derive(Clone, Debug, Hash, PartialEq, Eq)] pub struct File { - root: SyntaxNode + root: SyntaxNode, } impl File { @@ -74,21 +72,21 @@ impl File { } pub fn parse(text: &str) -> File { let tokens = tokenize(&text); - let (green, errors) = parser_impl::parse_with( - yellow::GreenBuilder::new(), - text, &tokens, grammar::root, - ); + let (green, errors) = + parser_impl::parse_with(yellow::GreenBuilder::new(), text, &tokens, grammar::root); File::new(green, errors) } pub fn reparse(&self, edit: &AtomEdit) -> File { - self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit)) + self.incremental_reparse(edit) + .unwrap_or_else(|| self.full_reparse(edit)) } pub fn incremental_reparse(&self, edit: &AtomEdit) -> Option { reparsing::incremental_reparse(self.syntax(), edit, self.errors()) .map(|(green_node, errors)| File::new(green_node, errors)) } fn full_reparse(&self, edit: &AtomEdit) -> File { - let text = text_utils::replace_range(self.syntax().text().to_string(), edit.delete, &edit.insert); + let text = + text_utils::replace_range(self.syntax().text().to_string(), edit.delete, &edit.insert); File::parse(&text) } pub fn ast(&self) -> ast::Root { diff --git a/crates/ra_syntax/src/parser_api.rs b/crates/ra_syntax/src/parser_api.rs index cc23bb75e3a..42046d36fde 100644 --- a/crates/ra_syntax/src/parser_api.rs +++ b/crates/ra_syntax/src/parser_api.rs @@ -1,8 +1,8 @@ use crate::{ - token_set::TokenSet, - parser_impl::ParserImpl, - SyntaxKind::{self, ERROR}, drop_bomb::DropBomb, + parser_impl::ParserImpl, + token_set::TokenSet, + SyntaxKind::{self, ERROR}, }; /// `Parser` struct provides the low-level API for @@ -116,9 +116,7 @@ impl<'t> Parser<'t> { /// Create an error node and consume the next token. pub(crate) fn err_recover(&mut self, message: &str, recovery: TokenSet) { - if self.at(SyntaxKind::L_CURLY) - || self.at(SyntaxKind::R_CURLY) - || self.at_ts(recovery) { + if self.at(SyntaxKind::L_CURLY) || self.at(SyntaxKind::R_CURLY) || self.at_ts(recovery) { self.error(message); } else { let m = self.start(); diff --git a/crates/ra_syntax/src/parser_impl/event.rs b/crates/ra_syntax/src/parser_impl/event.rs index 928d2cc7a16..79fa21389d1 100644 --- a/crates/ra_syntax/src/parser_impl/event.rs +++ b/crates/ra_syntax/src/parser_impl/event.rs @@ -7,14 +7,14 @@ //! tree builder: the parser produces a stream of events like //! `start node`, `finish node`, and `FileBuilder` converts //! this stream to a real tree. -use std::mem; use crate::{ - TextUnit, TextRange, SmolStr, lexer::Token, parser_impl::Sink, + SmolStr, SyntaxKind::{self, *}, + TextRange, TextUnit, }; - +use std::mem; /// `Parser` produces a flat list of `Event`s. /// They are converted to a tree-structure in @@ -89,20 +89,28 @@ pub(super) struct EventProcessor<'a, S: Sink> { } impl<'a, S: Sink> EventProcessor<'a, S> { - pub(super) fn new(sink: S, text: &'a str, tokens: &'a[Token], events: &'a mut [Event]) -> EventProcessor<'a, S> { + pub(super) fn new( + sink: S, + text: &'a str, + tokens: &'a [Token], + events: &'a mut [Event], + ) -> EventProcessor<'a, S> { EventProcessor { sink, text_pos: 0.into(), text, token_pos: 0, tokens, - events + events, } } pub(super) fn process(mut self) -> S { fn tombstone() -> Event { - Event::Start { kind: TOMBSTONE, forward_parent: None } + Event::Start { + kind: TOMBSTONE, + forward_parent: None, + } } let mut forward_parents = Vec::new(); @@ -112,7 +120,10 @@ impl<'a, S: Sink> EventProcessor<'a, S> { kind: TOMBSTONE, .. } => (), - Event::Start { kind, forward_parent } => { + Event::Start { + kind, + forward_parent, + } => { forward_parents.push(kind); let mut idx = i; let mut fp = forward_parent; @@ -125,7 +136,7 @@ impl<'a, S: Sink> EventProcessor<'a, S> { } => { forward_parents.push(kind); forward_parent - }, + } _ => unreachable!(), }; } @@ -136,7 +147,7 @@ impl<'a, S: Sink> EventProcessor<'a, S> { Event::Finish => { let last = i == self.events.len() - 1; self.finish(last); - }, + } Event::Token { kind, n_raw_tokens } => { self.eat_ws(); let n_raw_tokens = n_raw_tokens as usize; @@ -162,19 +173,16 @@ impl<'a, S: Sink> EventProcessor<'a, S> { .take_while(|it| it.kind.is_trivia()) .count(); let leading_trivias = &self.tokens[self.token_pos..self.token_pos + n_trivias]; - let mut trivia_end = self.text_pos + leading_trivias - .iter() - .map(|it| it.len) - .sum::(); + let mut trivia_end = + self.text_pos + leading_trivias.iter().map(|it| it.len).sum::(); let n_attached_trivias = { - let leading_trivias = leading_trivias.iter().rev() - .map(|it| { - let next_end = trivia_end - it.len; - let range = TextRange::from_to(next_end, trivia_end); - trivia_end = next_end; - (it.kind, &self.text[range]) - }); + let leading_trivias = leading_trivias.iter().rev().map(|it| { + let next_end = trivia_end - it.len; + let range = TextRange::from_to(next_end, trivia_end); + trivia_end = next_end; + (it.kind, &self.text[range]) + }); n_attached_trivias(kind, leading_trivias) }; self.eat_n_trivias(n_trivias - n_attached_trivias); @@ -215,7 +223,10 @@ impl<'a, S: Sink> EventProcessor<'a, S> { } } -fn n_attached_trivias<'a>(kind: SyntaxKind, trivias: impl Iterator) -> usize { +fn n_attached_trivias<'a>( + kind: SyntaxKind, + trivias: impl Iterator, +) -> usize { match kind { STRUCT_DEF | ENUM_DEF | FN_DEF | TRAIT_DEF | MODULE => { let mut res = 0; @@ -236,5 +247,4 @@ fn n_attached_trivias<'a>(kind: SyntaxKind, trivias: impl Iterator 0, } - } diff --git a/crates/ra_syntax/src/parser_impl/mod.rs b/crates/ra_syntax/src/parser_impl/mod.rs index c2a6448e7ae..2b026d61e4c 100644 --- a/crates/ra_syntax/src/parser_impl/mod.rs +++ b/crates/ra_syntax/src/parser_impl/mod.rs @@ -4,13 +4,13 @@ mod input; use std::cell::Cell; use crate::{ - TextUnit, SmolStr, lexer::Token, parser_api::Parser, parser_impl::{ - event::{EventProcessor, Event}, + event::{Event, EventProcessor}, input::{InputPosition, ParserInput}, }, + SmolStr, TextUnit, }; use crate::SyntaxKind::{self, EOF, TOMBSTONE}; @@ -86,7 +86,9 @@ impl<'t> ParserImpl<'t> { let c2 = self.inp.kind(self.pos + 1); let c3 = self.inp.kind(self.pos + 2); if self.inp.start(self.pos + 1) == self.inp.start(self.pos) + self.inp.len(self.pos) - && self.inp.start(self.pos + 2) == self.inp.start(self.pos + 1) + self.inp.len(self.pos + 1){ + && self.inp.start(self.pos + 2) + == self.inp.start(self.pos + 1) + self.inp.len(self.pos + 1) + { Some((c1, c2, c3)) } else { None @@ -138,10 +140,7 @@ impl<'t> ParserImpl<'t> { fn do_bump(&mut self, kind: SyntaxKind, n_raw_tokens: u8) { self.pos += u32::from(n_raw_tokens); - self.event(Event::Token { - kind, - n_raw_tokens, - }); + self.event(Event::Token { kind, n_raw_tokens }); } pub(super) fn error(&mut self, msg: String) { diff --git a/crates/ra_syntax/src/reparsing.rs b/crates/ra_syntax/src/reparsing.rs index 16272fe8887..a0014e01627 100644 --- a/crates/ra_syntax/src/reparsing.rs +++ b/crates/ra_syntax/src/reparsing.rs @@ -1,14 +1,11 @@ use crate::algo; use crate::grammar; use crate::lexer::{tokenize, Token}; -use crate::yellow::{self, GreenNode, SyntaxNodeRef, SyntaxError}; -use crate::parser_impl; use crate::parser_api::Parser; -use crate::{ - TextUnit, TextRange, - SyntaxKind::*, -}; +use crate::parser_impl; use crate::text_utils::replace_range; +use crate::yellow::{self, GreenNode, SyntaxError, SyntaxNodeRef}; +use crate::{SyntaxKind::*, TextRange, TextUnit}; #[derive(Debug, Clone)] pub struct AtomEdit { @@ -18,7 +15,10 @@ pub struct AtomEdit { impl AtomEdit { pub fn replace(range: TextRange, replace_with: String) -> AtomEdit { - AtomEdit { delete: range, insert: replace_with } + AtomEdit { + delete: range, + insert: replace_with, + } } pub fn delete(range: TextRange) -> AtomEdit { @@ -48,12 +48,7 @@ fn reparse_leaf<'node>( ) -> Option<(SyntaxNodeRef<'node>, GreenNode, Vec)> { let node = algo::find_covering_node(node, edit.delete); match node.kind() { - | WHITESPACE - | COMMENT - | DOC_COMMENT - | IDENT - | STRING - | RAW_STRING => { + WHITESPACE | COMMENT | DOC_COMMENT | IDENT | STRING | RAW_STRING => { let text = get_text_after_edit(node, &edit); let tokens = tokenize(&text); let token = match tokens[..] { @@ -84,10 +79,7 @@ fn reparse_block<'node>( return None; } let (green, new_errors) = - parser_impl::parse_with( - yellow::GreenBuilder::new(), - &text, &tokens, reparser, - ); + parser_impl::parse_with(yellow::GreenBuilder::new(), &text, &tokens, reparser); Some((node, green, new_errors)) } @@ -101,9 +93,7 @@ fn get_text_after_edit(node: SyntaxNodeRef, edit: &AtomEdit) -> String { fn is_contextual_kw(text: &str) -> bool { match text { - | "auto" - | "default" - | "union" => true, + "auto" | "default" | "union" => true, _ => false, } } @@ -113,7 +103,8 @@ fn find_reparsable_node<'node>( range: TextRange, ) -> Option<(SyntaxNodeRef<'node>, fn(&mut Parser))> { let node = algo::find_covering_node(node, range); - return node.ancestors() + return node + .ancestors() .filter_map(|node| reparser(node).map(|r| (node, r))) .next(); @@ -145,17 +136,20 @@ fn find_reparsable_node<'node>( fn is_balanced(tokens: &[Token]) -> bool { if tokens.len() == 0 || tokens.first().unwrap().kind != L_CURLY - || tokens.last().unwrap().kind != R_CURLY { + || tokens.last().unwrap().kind != R_CURLY + { return false; } let mut balance = 0usize; for t in tokens.iter() { match t.kind { L_CURLY => balance += 1, - R_CURLY => balance = match balance.checked_sub(1) { - Some(b) => b, - None => return false, - }, + R_CURLY => { + balance = match balance.checked_sub(1) { + Some(b) => b, + None => return false, + } + } _ => (), } } @@ -191,24 +185,14 @@ fn merge_errors( #[cfg(test)] mod tests { use super::{ - super::{ - File, - test_utils::extract_range, - text_utils::replace_range, - utils::dump_tree, - }, - reparse_leaf, reparse_block, AtomEdit, GreenNode, SyntaxError, SyntaxNodeRef, + super::{test_utils::extract_range, text_utils::replace_range, utils::dump_tree, File}, + reparse_block, reparse_leaf, AtomEdit, GreenNode, SyntaxError, SyntaxNodeRef, }; - fn do_check( - before: &str, - replace_with: &str, - reparser: F, - ) where - for<'a> F: Fn( - SyntaxNodeRef<'a>, - &AtomEdit, - ) -> Option<(SyntaxNodeRef<'a>, GreenNode, Vec)> + fn do_check(before: &str, replace_with: &str, reparser: F) + where + for<'a> F: Fn(SyntaxNodeRef<'a>, &AtomEdit) + -> Option<(SyntaxNodeRef<'a>, GreenNode, Vec)>, { let (range, before) = extract_range(before); let after = replace_range(before.clone(), range, replace_with); @@ -216,7 +200,10 @@ mod tests { let fully_reparsed = File::parse(&after); let incrementally_reparsed = { let f = File::parse(&before); - let edit = AtomEdit { delete: range, insert: replace_with.to_string() }; + let edit = AtomEdit { + delete: range, + insert: replace_with.to_string(), + }; let (node, green, new_errors) = reparser(f.syntax(), &edit).expect("cannot incrementally reparse"); let green_root = node.replace_with(green); @@ -232,113 +219,183 @@ mod tests { #[test] fn reparse_block_tests() { - let do_check = |before, replace_to| - do_check(before, replace_to, reparse_block); + let do_check = |before, replace_to| do_check(before, replace_to, reparse_block); - do_check(r" + do_check( + r" fn foo() { let x = foo + <|>bar<|> } -", "baz"); - do_check(r" +", + "baz", + ); + do_check( + r" fn foo() { let x = foo<|> + bar<|> } -", "baz"); - do_check(r" +", + "baz", + ); + do_check( + r" struct Foo { f: foo<|><|> } -", ",\n g: (),"); - do_check(r" +", + ",\n g: (),", + ); + do_check( + r" fn foo { let; 1 + 1; <|>92<|>; } -", "62"); - do_check(r" +", + "62", + ); + do_check( + r" mod foo { fn <|><|> } -", "bar"); - do_check(r" +", + "bar", + ); + do_check( + r" trait Foo { type <|>Foo<|>; } -", "Output"); - do_check(r" +", + "Output", + ); + do_check( + r" impl IntoIterator for Foo { f<|><|> } -", "n next("); - do_check(r" +", + "n next(", + ); + do_check( + r" use a::b::{foo,<|>,bar<|>}; - ", "baz"); - do_check(r" + ", + "baz", + ); + do_check( + r" pub enum A { Foo<|><|> } -", "\nBar;\n"); - do_check(r" +", + "\nBar;\n", + ); + do_check( + r" foo!{a, b<|><|> d} -", ", c[3]"); - do_check(r" +", + ", c[3]", + ); + do_check( + r" fn foo() { vec![<|><|>] } -", "123"); - do_check(r" +", + "123", + ); + do_check( + r" extern { fn<|>;<|> } -", " exit(code: c_int)"); +", + " exit(code: c_int)", + ); } #[test] fn reparse_leaf_tests() { - let do_check = |before, replace_to| - do_check(before, replace_to, reparse_leaf); + let do_check = |before, replace_to| do_check(before, replace_to, reparse_leaf); - do_check(r"<|><|> + do_check( + r"<|><|> fn foo() -> i32 { 1 } -", "\n\n\n \n"); - do_check(r" +", + "\n\n\n \n", + ); + do_check( + r" fn foo() -> <|><|> {} -", " \n"); - do_check(r" +", + " \n", + ); + do_check( + r" fn <|>foo<|>() -> i32 { 1 } -", "bar"); - do_check(r" +", + "bar", + ); + do_check( + r" fn foo<|><|>foo() { } -", "bar"); - do_check(r" +", + "bar", + ); + do_check( + r" fn foo /* <|><|> */ () {} -", "some comment"); - do_check(r" +", + "some comment", + ); + do_check( + r" fn baz <|><|> () {} -", " \t\t\n\n"); - do_check(r" +", + " \t\t\n\n", + ); + do_check( + r" fn baz <|><|> () {} -", " \t\t\n\n"); - do_check(r" +", + " \t\t\n\n", + ); + do_check( + r" /// foo <|><|>omment mod { } -", "c"); - do_check(r#" +", + "c", + ); + do_check( + r#" fn -> &str { "Hello<|><|>" } -"#, ", world"); - do_check(r#" +"#, + ", world", + ); + do_check( + r#" fn -> &str { // "Hello<|><|>" -"#, ", world"); - do_check(r##" +"#, + ", world", + ); + do_check( + r##" fn -> &str { r#"Hello<|><|>"# -"##, ", world"); - do_check(r" +"##, + ", world", + ); + do_check( + r" #[derive(<|>Copy<|>)] enum Foo { } -", "Clone"); +", + "Clone", + ); } } diff --git a/crates/ra_syntax/src/syntax_kinds/mod.rs b/crates/ra_syntax/src/syntax_kinds/mod.rs index 3041e56339a..0fcd07cbfe0 100644 --- a/crates/ra_syntax/src/syntax_kinds/mod.rs +++ b/crates/ra_syntax/src/syntax_kinds/mod.rs @@ -1,7 +1,7 @@ mod generated; -use std::fmt; use crate::SyntaxKind::*; +use std::fmt; pub use self::generated::SyntaxKind; diff --git a/crates/ra_syntax/src/text_utils.rs b/crates/ra_syntax/src/text_utils.rs index adf26ef30a5..abda5ec3933 100644 --- a/crates/ra_syntax/src/text_utils.rs +++ b/crates/ra_syntax/src/text_utils.rs @@ -23,4 +23,4 @@ pub fn replace_range(mut text: String, range: TextRange, replace_with: &str) -> let end = u32::from(range.end()) as usize; text.replace_range(start..end, replace_with); text -} \ No newline at end of file +} diff --git a/crates/ra_syntax/src/utils.rs b/crates/ra_syntax/src/utils.rs index df1f4b37242..27248ff324b 100644 --- a/crates/ra_syntax/src/utils.rs +++ b/crates/ra_syntax/src/utils.rs @@ -1,8 +1,8 @@ -use std::fmt::Write; use crate::{ algo::walk::{walk, WalkEvent}, - SyntaxKind, File, SyntaxNodeRef + File, SyntaxKind, SyntaxNodeRef, }; +use std::fmt::Write; /// Parse a file and create a string representation of the resulting parse tree. pub fn dump_tree(syntax: SyntaxNodeRef) -> String { @@ -58,9 +58,7 @@ pub(crate) fn validate_block_structure(root: SyntaxNodeRef) { let mut stack = Vec::new(); for node in root.descendants() { match node.kind() { - SyntaxKind::L_CURLY => { - stack.push(node) - } + SyntaxKind::L_CURLY => stack.push(node), SyntaxKind::R_CURLY => { if let Some(pair) = stack.pop() { assert_eq!( diff --git a/crates/ra_syntax/src/yellow/builder.rs b/crates/ra_syntax/src/yellow/builder.rs index 67a1a382b5a..d6405340993 100644 --- a/crates/ra_syntax/src/yellow/builder.rs +++ b/crates/ra_syntax/src/yellow/builder.rs @@ -1,10 +1,9 @@ -use rowan::GreenNodeBuilder; use crate::{ - TextUnit, SmolStr, parser_impl::Sink, - yellow::{GreenNode, SyntaxError, RaTypes}, - SyntaxKind, + yellow::{GreenNode, RaTypes, SyntaxError}, + SmolStr, SyntaxKind, TextUnit, }; +use rowan::GreenNodeBuilder; pub(crate) struct GreenBuilder { errors: Vec, @@ -36,7 +35,10 @@ impl Sink for GreenBuilder { } fn error(&mut self, message: String, offset: TextUnit) { - let error = SyntaxError { msg: message, offset }; + let error = SyntaxError { + msg: message, + offset, + }; self.errors.push(error) } diff --git a/crates/ra_syntax/src/yellow/mod.rs b/crates/ra_syntax/src/yellow/mod.rs index ab9bca0f020..b5c9da81352 100644 --- a/crates/ra_syntax/src/yellow/mod.rs +++ b/crates/ra_syntax/src/yellow/mod.rs @@ -1,16 +1,16 @@ mod builder; mod syntax_text; +use self::syntax_text::SyntaxText; +use crate::{SmolStr, SyntaxKind, TextRange, TextUnit}; +use rowan::Types; use std::{ fmt, hash::{Hash, Hasher}, }; -use rowan::Types; -use crate::{SyntaxKind, TextUnit, TextRange, SmolStr}; -use self::syntax_text::SyntaxText; -pub use rowan::{TreeRoot}; pub(crate) use self::builder::GreenBuilder; +pub use rowan::TreeRoot; #[derive(Debug, Clone, Copy)] pub enum RaTypes {} @@ -31,9 +31,7 @@ pub struct SyntaxError { } #[derive(Clone, Copy)] -pub struct SyntaxNode = OwnedRoot>( - ::rowan::SyntaxNode, -); +pub struct SyntaxNode = OwnedRoot>(::rowan::SyntaxNode); pub type SyntaxNodeRef<'a> = SyntaxNode>; impl PartialEq> for SyntaxNode @@ -69,16 +67,16 @@ impl<'a> SyntaxNodeRef<'a> { pub fn leaf_text(self) -> Option<&'a SmolStr> { self.0.leaf_text() } - pub fn ancestors(self) -> impl Iterator> { + pub fn ancestors(self) -> impl Iterator> { crate::algo::generate(Some(self), |&node| node.parent()) } - pub fn descendants(self) -> impl Iterator> { + pub fn descendants(self) -> impl Iterator> { crate::algo::walk::walk(self).filter_map(|event| match event { crate::algo::walk::WalkEvent::Enter(node) => Some(node), crate::algo::walk::WalkEvent::Exit(_) => None, }) } - pub fn siblings(self, direction: Direction) -> impl Iterator> { + pub fn siblings(self, direction: Direction) -> impl Iterator> { crate::algo::generate(Some(self), move |&node| match direction { Direction::Next => node.next_sibling(), Direction::Prev => node.prev_sibling(), @@ -142,9 +140,7 @@ impl> fmt::Debug for SyntaxNode { } #[derive(Debug)] -pub struct SyntaxNodeChildren>( - ::rowan::SyntaxNodeChildren -); +pub struct SyntaxNodeChildren>(::rowan::SyntaxNodeChildren); impl> Iterator for SyntaxNodeChildren { type Item = SyntaxNode; @@ -154,7 +150,6 @@ impl> Iterator for SyntaxNodeChildren { } } - fn has_short_text(kind: SyntaxKind) -> bool { use crate::SyntaxKind::*; match kind { diff --git a/crates/ra_syntax/src/yellow/syntax_text.rs b/crates/ra_syntax/src/yellow/syntax_text.rs index ae33b993de0..5395ca90b92 100644 --- a/crates/ra_syntax/src/yellow/syntax_text.rs +++ b/crates/ra_syntax/src/yellow/syntax_text.rs @@ -1,10 +1,8 @@ -use std::{ - fmt, ops, -}; +use std::{fmt, ops}; use crate::{ + text_utils::{contains_offset_nonstrict, intersect}, SyntaxNodeRef, TextRange, TextUnit, - text_utils::{intersect, contains_offset_nonstrict}, }; #[derive(Clone)] @@ -17,19 +15,17 @@ impl<'a> SyntaxText<'a> { pub(crate) fn new(node: SyntaxNodeRef<'a>) -> SyntaxText<'a> { SyntaxText { node, - range: node.range() + range: node.range(), } } - pub fn chunks(&self) -> impl Iterator { + pub fn chunks(&self) -> impl Iterator { let range = self.range; - self.node - .descendants() - .filter_map(move |node| { - let text = node.leaf_text()?; - let range = intersect(range, node.range())?; - let range = range - node.range().start(); - Some(&text[range]) - }) + self.node.descendants().filter_map(move |node| { + let text = node.leaf_text()?; + let range = intersect(range, node.range())?; + let range = range - node.range().start(); + Some(&text[range]) + }) } pub fn push_to(&self, buf: &mut String) { self.chunks().for_each(|it| buf.push_str(it)); @@ -55,11 +51,13 @@ impl<'a> SyntaxText<'a> { self.range.len() } pub fn slice(&self, range: impl SyntaxTextSlice) -> SyntaxText<'a> { - let range = range.restrict(self.range) - .unwrap_or_else(|| { - panic!("invalid slice, range: {:?}, slice: {:?}", self.range, range) - }); - SyntaxText { node: self.node, range } + let range = range.restrict(self.range).unwrap_or_else(|| { + panic!("invalid slice, range: {:?}, slice: {:?}", self.range, range) + }); + SyntaxText { + node: self.node, + range, + } } pub fn char_at(&self, offset: TextUnit) -> Option { let mut start: TextUnit = 0.into(); diff --git a/crates/ra_syntax/tests/test.rs b/crates/ra_syntax/tests/test.rs index 27380efefd6..9d1ded093b8 100644 --- a/crates/ra_syntax/tests/test.rs +++ b/crates/ra_syntax/tests/test.rs @@ -4,14 +4,14 @@ extern crate test_utils; extern crate walkdir; use std::{ + fmt::Write, fs, path::{Path, PathBuf}, - fmt::Write, }; use ra_syntax::{ + utils::{check_fuzz_invariants, dump_tree}, File, - utils::{dump_tree, check_fuzz_invariants}, }; #[test] @@ -37,7 +37,6 @@ fn parser_fuzz_tests() { } } - /// Read file and normalize newlines. /// /// `rustc` seems to always normalize `\r\n` newlines to `\n`: @@ -54,8 +53,8 @@ fn read_text(path: &Path) -> String { } pub fn dir_tests(paths: &[&str], f: F) - where - F: Fn(&str) -> String, +where + F: Fn(&str) -> String, { for (path, input_code) in collect_tests(paths) { let parse_tree = f(&input_code); diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs index ee73153f02f..dbe2997eba8 100644 --- a/crates/test_utils/src/lib.rs +++ b/crates/test_utils/src/lib.rs @@ -2,9 +2,9 @@ extern crate difference; extern crate itertools; extern crate text_unit; -use std::fmt; use itertools::Itertools; -use text_unit::{TextUnit, TextRange}; +use std::fmt; +use text_unit::{TextRange, TextUnit}; pub use self::difference::Changeset as __Changeset; diff --git a/crates/tools/src/lib.rs b/crates/tools/src/lib.rs index 9a1b12a1644..5d5d372bb85 100644 --- a/crates/tools/src/lib.rs +++ b/crates/tools/src/lib.rs @@ -1,17 +1,17 @@ extern crate itertools; #[macro_use] extern crate failure; +extern crate heck; extern crate ron; extern crate tera; -extern crate heck; +use heck::{CamelCase, ShoutySnakeCase, SnakeCase}; +use itertools::Itertools; use std::{ collections::HashMap, fs, path::{Path, PathBuf}, }; -use itertools::Itertools; -use heck::{CamelCase, ShoutySnakeCase, SnakeCase}; pub type Result = ::std::result::Result; @@ -61,7 +61,6 @@ pub fn collect_tests(s: &str) -> Vec<(usize, Test)> { res } - pub fn update(path: &Path, contents: &str, verify: bool) -> Result<()> { match fs::read_to_string(path) { Ok(ref old_contents) if old_contents == contents => { @@ -116,5 +115,8 @@ pub fn render_template(template: &Path) -> Result { } pub fn project_root() -> PathBuf { - Path::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap()).parent().unwrap().to_path_buf() + Path::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap()) + .parent() + .unwrap() + .to_path_buf() } diff --git a/crates/tools/src/main.rs b/crates/tools/src/main.rs index 6eacfc190c4..b662d78df81 100644 --- a/crates/tools/src/main.rs +++ b/crates/tools/src/main.rs @@ -11,7 +11,10 @@ use std::{ path::{Path, PathBuf}, process::Command, }; -use tools::{AST, AST_TEMPLATE, Result, SYNTAX_KINDS, SYNTAX_KINDS_TEMPLATE, Test, collect_tests, render_template, update, project_root}; +use tools::{ + collect_tests, project_root, render_template, update, Result, Test, AST, AST_TEMPLATE, + SYNTAX_KINDS, SYNTAX_KINDS_TEMPLATE, +}; const GRAMMAR_DIR: &str = "./crates/ra_syntax/src/grammar"; const INLINE_TESTS_DIR: &str = "./crates/ra_syntax/tests/data/parser/inline"; @@ -40,18 +43,23 @@ fn main() -> Result<()> { fn run_gen_command(name: &str, verify: bool) -> Result<()> { match name { "gen-kinds" => { - update(&project_root().join(SYNTAX_KINDS), &render_template(&project_root().join(SYNTAX_KINDS_TEMPLATE))?, verify)?; - update(&project_root().join(AST), &render_template(&project_root().join(AST_TEMPLATE))?, verify)?; - }, - "gen-tests" => { - gen_tests(verify)? - }, + update( + &project_root().join(SYNTAX_KINDS), + &render_template(&project_root().join(SYNTAX_KINDS_TEMPLATE))?, + verify, + )?; + update( + &project_root().join(AST), + &render_template(&project_root().join(AST_TEMPLATE))?, + verify, + )?; + } + "gen-tests" => gen_tests(verify)?, _ => unreachable!(), } Ok(()) } - fn gen_tests(verify: bool) -> Result<()> { let tests = tests_from_dir(Path::new(GRAMMAR_DIR))?; @@ -133,11 +141,20 @@ fn install_code_extension() -> Result<()> { } else { run(r"npm install", "./editors/code")?; } - run(r"node ./node_modules/vsce/out/vsce package", "./editors/code")?; + run( + r"node ./node_modules/vsce/out/vsce package", + "./editors/code", + )?; if cfg!(windows) { - run(r"cmd.exe /c code.cmd --install-extension ./ra-lsp-0.0.1.vsix", "./editors/code")?; + run( + r"cmd.exe /c code.cmd --install-extension ./ra-lsp-0.0.1.vsix", + "./editors/code", + )?; } else { - run(r"code --install-extension ./ra-lsp-0.0.1.vsix", "./editors/code")?; + run( + r"code --install-extension ./ra-lsp-0.0.1.vsix", + "./editors/code", + )?; } Ok(()) } @@ -145,7 +162,11 @@ fn install_code_extension() -> Result<()> { fn run(cmdline: &'static str, dir: &str) -> Result<()> { eprintln!("\nwill run: {}", cmdline); let manifest_dir = env!("CARGO_MANIFEST_DIR"); - let project_dir = Path::new(manifest_dir).ancestors().nth(2).unwrap().join(dir); + let project_dir = Path::new(manifest_dir) + .ancestors() + .nth(2) + .unwrap() + .join(dir); let mut args = cmdline.split_whitespace(); let exec = args.next().unwrap(); let status = Command::new(exec) diff --git a/crates/tools/tests/cli.rs b/crates/tools/tests/cli.rs index f507d80a291..16899bb5f43 100644 --- a/crates/tools/tests/cli.rs +++ b/crates/tools/tests/cli.rs @@ -1,13 +1,23 @@ extern crate tools; -use tools::{AST, AST_TEMPLATE, SYNTAX_KINDS, SYNTAX_KINDS_TEMPLATE, render_template, update, project_root}; +use tools::{ + project_root, render_template, update, AST, AST_TEMPLATE, SYNTAX_KINDS, SYNTAX_KINDS_TEMPLATE, +}; #[test] fn verify_template_generation() { - if let Err(error) = update(&project_root().join(SYNTAX_KINDS), &render_template(&project_root().join(SYNTAX_KINDS_TEMPLATE)).unwrap(), true) { + if let Err(error) = update( + &project_root().join(SYNTAX_KINDS), + &render_template(&project_root().join(SYNTAX_KINDS_TEMPLATE)).unwrap(), + true, + ) { panic!("{}. Please update it by running `cargo gen-kinds`", error); } - if let Err(error) = update(&project_root().join(AST), &render_template(&project_root().join(AST_TEMPLATE)).unwrap(), true) { + if let Err(error) = update( + &project_root().join(AST), + &render_template(&project_root().join(AST_TEMPLATE)).unwrap(), + true, + ) { panic!("{}. Please update it by running `cargo gen-kinds`", error); } }