-use rustc_hash::{FxHashMap, FxHashSet};
-use ra_editor::{find_node_at_offset};
+use ra_editor::find_node_at_offset;
use ra_syntax::{
- AtomEdit, File, TextUnit, AstNode, SyntaxNodeRef,
algo::visit::{visitor, visitor_ctx, Visitor, VisitorCtx},
ast::{self, AstChildren, LoopBodyOwner, ModuleItemOwner},
+ AstNode, AtomEdit, File,
SyntaxKind::*,
+ SyntaxNodeRef, TextUnit,
};
+use rustc_hash::{FxHashMap, FxHashSet};
use crate::{
- FileId, Cancelable,
- input::FilesDatabase,
db::{self, SyntaxDatabase},
- descriptors::DescriptorDatabase,
descriptors::function::FnScopes,
- descriptors::module::{ModuleTree, ModuleId, ModuleScope},
+ descriptors::module::{ModuleId, ModuleScope, ModuleTree},
+ descriptors::DescriptorDatabase,
+ input::FilesDatabase,
+ Cancelable, FileId,
};
-
#[derive(Debug)]
pub struct CompletionItem {
/// What user sees in pop-up
pub snippet: Option<String>,
}
-pub(crate) fn resolve_based_completion(db: &db::RootDatabase, file_id: FileId, offset: TextUnit) -> Cancelable<Option<Vec<CompletionItem>>> {
+pub(crate) fn resolve_based_completion(
+ db: &db::RootDatabase,
+ file_id: FileId,
+ offset: TextUnit,
+) -> Cancelable<Option<Vec<CompletionItem>>> {
let source_root_id = db.file_source_root(file_id);
let file = db.file_syntax(file_id);
let module_tree = db.module_tree(source_root_id)?;
Ok(Some(res))
}
-
-
-pub(crate) fn find_target_module(module_tree: &ModuleTree, module_id: ModuleId, file: &File, offset: TextUnit) -> Option<ModuleId> {
+pub(crate) fn find_target_module(
+ module_tree: &ModuleTree,
+ module_id: ModuleId,
+ file: &File,
+ offset: TextUnit,
+) -> Option<ModuleId> {
let name_ref: ast::NameRef = find_node_at_offset(file.syntax(), offset)?;
let mut crate_path = crate_path(name_ref)?;
}
fn crate_path(name_ref: ast::NameRef) -> Option<Vec<ast::NameRef>> {
- let mut path = name_ref.syntax()
- .parent().and_then(ast::PathSegment::cast)?
+ let mut path = name_ref
+ .syntax()
+ .parent()
+ .and_then(ast::PathSegment::cast)?
.parent_path();
let mut res = Vec::new();
loop {
match segment.kind()? {
ast::PathSegmentKind::Name(name) => res.push(name),
ast::PathSegmentKind::CrateKw => break,
- ast::PathSegmentKind::SelfKw | ast::PathSegmentKind::SuperKw =>
- return None,
+ ast::PathSegmentKind::SelfKw | ast::PathSegmentKind::SuperKw => return None,
}
path = path.qualifier()?;
}
Some(res)
}
-
pub(crate) fn scope_completion(
db: &db::RootDatabase,
file_id: FileId,
);
}
-fn complete_name_ref(
- file: &File,
- name_ref: ast::NameRef,
- acc: &mut Vec<CompletionItem>,
-) {
+fn complete_name_ref(file: &File, name_ref: ast::NameRef, acc: &mut Vec<CompletionItem>) {
if !is_node::<ast::Path>(name_ref.syntax()) {
return;
}
.visit::<ast::LoopExpr, _>(LoopBodyOwner::loop_body)
.accept(node);
if let Some(Some(body)) = loop_body {
- if name_ref.syntax().range().is_subrange(&body.syntax().range()) {
+ if name_ref
+ .syntax()
+ .range()
+ .is_subrange(&body.syntax().range())
+ {
return true;
}
}
#[cfg(test)]
mod tests {
- use test_utils::{assert_eq_dbg};
+ use test_utils::assert_eq_dbg;
- use crate::mock_analysis::{single_file_with_position};
+ use crate::mock_analysis::single_file_with_position;
use super::*;
-use std::{
- sync::Arc,
-};
+use std::sync::Arc;
use ra_editor::LineIndex;
use ra_syntax::File;
use crate::{
db,
- Cancelable, Canceled,
descriptors::{
- DescriptorDatabase, SubmodulesQuery, ModuleTreeQuery, ModuleScopeQuery,
- FnSyntaxQuery, FnScopesQuery
+ DescriptorDatabase, FnScopesQuery, FnSyntaxQuery, ModuleScopeQuery, ModuleTreeQuery,
+ SubmodulesQuery,
},
symbol_index::SymbolIndex,
- syntax_ptr::{SyntaxPtrDatabase, ResolveSyntaxPtrQuery},
- FileId,
+ syntax_ptr::{ResolveSyntaxPtrQuery, SyntaxPtrDatabase},
+ Cancelable, Canceled, FileId,
};
#[derive(Default, Debug)]
use std::sync::Arc;
-use ra_syntax::{
- ast::{AstNode, FnDef, FnDefNode},
-};
+use ra_syntax::ast::{AstNode, FnDef, FnDefNode};
-use crate::{
- descriptors::{
- DescriptorDatabase,
- function::{FnId, FnScopes},
- },
+use crate::descriptors::{
+ function::{FnId, FnScopes},
+ DescriptorDatabase,
};
/// Resolve `FnId` to the corresponding `SyntaxNode`
pub(super) mod imp;
mod scope;
-use std::cmp::{min, max};
+use std::cmp::{max, min};
use ra_syntax::{
ast::{self, AstNode, DocCommentsOwner, NameOwner},
- TextRange, TextUnit
+ TextRange, TextUnit,
};
-use crate::{
- FileId,
- syntax_ptr::SyntaxPtr
-};
-
-pub(crate) use self::scope::{FnScopes, resolve_local_name};
+use crate::{syntax_ptr::SyntaxPtr, FileId};
+pub(crate) use self::scope::{resolve_local_name, FnScopes};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct FnId(SyntaxPtr);
}
}
-
#[derive(Debug, Clone)]
pub struct FnDescriptor {
pub name: String,
pub label: String,
pub ret_type: Option<String>,
pub params: Vec<String>,
- pub doc: Option<String>
+ pub doc: Option<String>,
}
impl FnDescriptor {
};
if let Some((comment_range, docs)) = FnDescriptor::extract_doc_comments(node) {
- let comment_range = comment_range.checked_sub(node.syntax().range().start()).unwrap();
+ let comment_range = comment_range
+ .checked_sub(node.syntax().range().start())
+ .unwrap();
let start = comment_range.start().to_usize();
let end = comment_range.end().to_usize();
ret_type,
params,
label: label.trim().to_owned(),
- doc
+ doc,
})
}
let comment_text = node.doc_comment_text();
- let (begin, end) = node.doc_comments()
+ let (begin, end) = node
+ .doc_comments()
.map(|comment| comment.syntax().range())
.map(|range| (range.start().to_usize(), range.end().to_usize()))
- .fold((std::usize::MAX, std::usize::MIN), |acc, range| (min(acc.0, range.0), max(acc.1, range.1)));
+ .fold((std::usize::MAX, std::usize::MIN), |acc, range| {
+ (min(acc.0, range.0), max(acc.1, range.1))
+ });
let range = TextRange::from_to(TextUnit::from_usize(begin), TextUnit::from_usize(end));
res
}
}
-
&self.get(scope).entries
}
pub fn scope_chain<'a>(&'a self, node: SyntaxNodeRef) -> impl Iterator<Item = ScopeId> + 'a {
- generate(self.scope_for(node), move |&scope| {
- self.get(scope).parent
- })
+ generate(self.scope_for(node), move |&scope| self.get(scope).parent)
}
fn root_scope(&mut self) -> ScopeId {
let res = ScopeId(self.scopes.len() as u32);
#[cfg(test)]
mod tests {
+ use ra_editor::find_node_at_offset;
use ra_syntax::File;
use test_utils::extract_offset;
- use ra_editor::{find_node_at_offset};
use super::*;
-
fn do_check(code: &str, expected: &[&str]) {
let (off, code) = extract_offset(code);
let code = {
-pub(crate) mod module;
pub(crate) mod function;
+pub(crate) mod module;
use std::sync::Arc;
use ra_syntax::{
- SmolStr,
ast::{self, AstNode, FnDefNode},
- TextRange
+ SmolStr, TextRange,
};
use crate::{
- FileId, Cancelable,
db::SyntaxDatabase,
- descriptors::module::{ModuleTree, ModuleId, ModuleScope},
- descriptors::function::{FnId, FnScopes, resolve_local_name},
+ descriptors::function::{resolve_local_name, FnId, FnScopes},
+ descriptors::module::{ModuleId, ModuleScope, ModuleTree},
input::SourceRootId,
- syntax_ptr::{SyntaxPtrDatabase, LocalSyntaxPtr},
+ syntax_ptr::{LocalSyntaxPtr, SyntaxPtrDatabase},
+ Cancelable, FileId,
};
-
salsa::query_group! {
pub(crate) trait DescriptorDatabase: SyntaxDatabase + SyntaxPtrDatabase {
fn module_tree(source_root_id: SourceRootId) -> Cancelable<Arc<ModuleTree>> {
#[derive(Debug)]
pub struct ReferenceDescriptor {
pub range: TextRange,
- pub name: String
+ pub name: String,
}
#[derive(Debug)]
pub struct DeclarationDescriptor<'a> {
pat: ast::BindPat<'a>,
- pub range: TextRange
+ pub range: TextRange,
}
impl<'a> DeclarationDescriptor<'a> {
pub fn new(pat: ast::BindPat) -> DeclarationDescriptor {
let range = pat.syntax().range();
- DeclarationDescriptor {
- pat,
- range
- }
+ DeclarationDescriptor { pat, range }
}
pub fn find_all_refs(&self) -> Vec<ReferenceDescriptor> {
let fn_def = match self.pat.syntax().ancestors().find_map(ast::FnDef::cast) {
Some(def) => def,
- None => return Default::default()
+ None => return Default::default(),
};
let fn_scopes = FnScopes::new(fn_def);
- let refs : Vec<_> = fn_def.syntax().descendants()
+ let refs: Vec<_> = fn_def
+ .syntax()
+ .descendants()
.filter_map(ast::NameRef::cast)
- .filter(|name_ref| {
- match resolve_local_name(*name_ref, &fn_scopes) {
- None => false,
- Some(entry) => entry.ptr() == name_ptr,
- }
+ .filter(|name_ref| match resolve_local_name(*name_ref, &fn_scopes) {
+ None => false,
+ Some(entry) => entry.ptr() == name_ptr,
})
.map(|name_ref| ReferenceDescriptor {
name: name_ref.syntax().text().to_string(),
- range : name_ref.syntax().range(),
+ range: name_ref.syntax().range(),
})
.collect();
use std::sync::Arc;
-use relative_path::RelativePathBuf;
-use rustc_hash::{FxHashMap, FxHashSet};
use ra_syntax::{
- SmolStr,
ast::{self, NameOwner},
+ SmolStr,
};
+use relative_path::RelativePathBuf;
+use rustc_hash::{FxHashMap, FxHashSet};
use crate::{
- FileId, Cancelable, FileResolverImp, db,
- input::{SourceRoot, SourceRootId},
+ db,
descriptors::DescriptorDatabase,
+ input::{SourceRoot, SourceRootId},
+ Cancelable, FileId, FileResolverImp,
};
-use super::{
- ModuleData, ModuleTree, ModuleId, LinkId, LinkData, Problem, ModuleScope
-};
-
+use super::{LinkData, LinkId, ModuleData, ModuleId, ModuleScope, ModuleTree, Problem};
-pub(crate) fn submodules(db: &impl DescriptorDatabase, file_id: FileId) -> Cancelable<Arc<Vec<SmolStr>>> {
+pub(crate) fn submodules(
+ db: &impl DescriptorDatabase,
+ file_id: FileId,
+) -> Cancelable<Arc<Vec<SmolStr>>> {
db::check_canceled(db)?;
let file = db.file_syntax(file_id);
let root = file.ast();
Ok(Arc::new(res))
}
-
#[derive(Clone, Hash, PartialEq, Eq, Debug)]
pub struct Submodule {
pub name: SmolStr,
}
-
fn create_module_tree<'a>(
db: &impl DescriptorDatabase,
source_root: SourceRootId,
continue; // TODO: use explicit crate_roots here
}
assert!(!roots.contains_key(&file_id));
- let module_id = build_subtree(db, &source_root, &mut tree, &mut visited, &mut roots, None, file_id)?;
+ let module_id = build_subtree(
+ db,
+ &source_root,
+ &mut tree,
+ &mut visited,
+ &mut roots,
+ None,
+ file_id,
+ )?;
roots.insert(file_id, module_id);
}
Ok(tree)
pub(super) mod imp;
pub(crate) mod scope;
+use ra_syntax::{
+ ast::{self, AstNode, NameOwner},
+ SmolStr, SyntaxNode,
+};
use relative_path::RelativePathBuf;
-use ra_syntax::{ast::{self, NameOwner, AstNode}, SmolStr, SyntaxNode};
use crate::FileId;
impl ModuleTree {
pub(crate) fn modules_for_file(&self, file_id: FileId) -> Vec<ModuleId> {
- self.mods.iter()
+ self.mods
+ .iter()
.enumerate()
- .filter(|(_idx, it)| it.file_id == file_id).map(|(idx, _)| ModuleId(idx as u32))
+ .filter(|(_idx, it)| it.file_id == file_id)
+ .map(|(idx, _)| ModuleId(idx as u32))
.collect()
}
}
pub(crate) fn parent_link(self, tree: &ModuleTree) -> Option<LinkId> {
tree.module(self).parent
- }
+ }
pub(crate) fn parent(self, tree: &ModuleTree) -> Option<ModuleId> {
let link = self.parent_link(tree)?;
Some(tree.link(link).owner)
curr
}
pub(crate) fn child(self, tree: &ModuleTree, name: &str) -> Option<ModuleId> {
- let link = tree.module(self)
+ let link = tree
+ .module(self)
.children
.iter()
.map(|&it| tree.link(it))
.find(|it| it.name == name)?;
Some(*link.points_to.first()?)
}
- pub(crate) fn problems(
- self,
- tree: &ModuleTree,
- root: ast::Root,
- ) -> Vec<(SyntaxNode, Problem)> {
+ pub(crate) fn problems(self, tree: &ModuleTree, root: ast::Root) -> Vec<(SyntaxNode, Problem)> {
tree.module(self)
.children
.iter()
pub(crate) fn owner(self, tree: &ModuleTree) -> ModuleId {
tree.link(self).owner
}
- pub(crate) fn bind_source<'a>(
- self,
- tree: &ModuleTree,
- root: ast::Root<'a>,
- ) -> ast::Module<'a> {
+ pub(crate) fn bind_source<'a>(self, tree: &ModuleTree, root: ast::Root<'a>) -> ast::Module<'a> {
imp::modules(root)
.find(|(name, _)| name == &tree.link(self).name)
.unwrap()
problem: Option<Problem>,
}
-
impl ModuleTree {
fn module(&self, id: ModuleId) -> &ModuleData {
&self.mods[id.0 as usize]
id
}
}
-
//! Backend for module-level scope resolution & completion
-
use ra_syntax::{
ast::{self, ModuleItemOwner},
- File, AstNode, SmolStr,
+ AstNode, File, SmolStr,
};
use crate::syntax_ptr::LocalSyntaxPtr;
#[cfg(test)]
mod tests {
use super::*;
- use ra_syntax::{File};
+ use ra_syntax::File;
fn do_check(code: &str, expected: &[&str]) {
let file = File::parse(&code);
use rayon::prelude::*;
use relative_path::RelativePath;
use rustc_hash::FxHashSet;
-use salsa::{ParallelDatabase, Database};
+use salsa::{Database, ParallelDatabase};
use crate::{
- AnalysisChange,
- db::{
- self, SyntaxDatabase, FileSyntaxQuery,
- },
- input::{SourceRootId, FilesDatabase, SourceRoot, WORKSPACE},
+ completion::{resolve_based_completion, scope_completion, CompletionItem},
+ db::{self, FileSyntaxQuery, SyntaxDatabase},
descriptors::{
- DescriptorDatabase, DeclarationDescriptor,
- module::{ModuleTree, Problem},
function::{FnDescriptor, FnId},
+ module::{ModuleTree, Problem},
+ DeclarationDescriptor, DescriptorDatabase,
},
- completion::{scope_completion, resolve_based_completion, CompletionItem},
+ input::{FilesDatabase, SourceRoot, SourceRootId, WORKSPACE},
symbol_index::SymbolIndex,
syntax_ptr::SyntaxPtrDatabase,
- CrateGraph, CrateId, Diagnostic, FileId, FileResolver, FileSystemEdit, Position,
- Query, SourceChange, SourceFileEdit, Cancelable,
+ AnalysisChange, Cancelable, CrateGraph, CrateId, Diagnostic, FileId, FileResolver,
+ FileSystemEdit, Position, Query, SourceChange, SourceFileEdit,
};
#[derive(Clone, Debug)]
db: db::RootDatabase,
}
-
impl AnalysisHostImpl {
pub fn new() -> AnalysisHostImpl {
let db = db::RootDatabase::default();
}
pub fn analysis(&self) -> AnalysisImpl {
AnalysisImpl {
- db: self.db.fork() // freeze revision here
+ db: self.db.fork(), // freeze revision here
}
}
pub fn apply_change(&mut self, change: AnalysisChange) {
.set(file_id, Arc::new(text))
}
if !(change.files_added.is_empty() && change.files_removed.is_empty()) {
- let file_resolver = change.file_resolver
+ let file_resolver = change
+ .file_resolver
.expect("change resolver when changing set of files");
let mut source_root = SourceRoot::clone(&self.db.source_root(WORKSPACE));
for (file_id, text) in change.files_added {
.set((), Arc::new(libraries));
}
if let Some(crate_graph) = change.crate_graph {
- self.db.query(crate::input::CrateGraphQuery)
+ self.db
+ .query(crate::input::CrateGraphQuery)
.set((), Arc::new(crate_graph))
}
}
}
pub fn world_symbols(&self, query: Query) -> Cancelable<Vec<(FileId, FileSymbol)>> {
let buf: Vec<Arc<SymbolIndex>> = if query.libs {
- self.db.libraries().iter()
+ self.db
+ .libraries()
+ .iter()
.map(|&lib_id| self.db.library_symbols(lib_id))
.collect()
} else {
let files = &self.db.source_root(WORKSPACE).files;
let db = self.db.clone();
- files.par_iter()
+ files
+ .par_iter()
.map_with(db, |db, &file_id| db.file_symbols(file_id))
.filter_map(|it| it.ok())
.collect()
};
- self.db.query(FileSyntaxQuery)
+ self.db
+ .query(FileSyntaxQuery)
.sweep(salsa::SweepStrategy::default().discard_values());
Ok(query.search(&buf))
}
pub fn parent_module(&self, file_id: FileId) -> Cancelable<Vec<(FileId, FileSymbol)>> {
let module_tree = self.module_tree(file_id)?;
- let res = module_tree.modules_for_file(file_id)
+ let res = module_tree
+ .modules_for_file(file_id)
.into_iter()
.filter_map(|module_id| {
let link = module_id.parent_link(&module_tree)?;
pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> {
let module_tree = self.module_tree(file_id)?;
let crate_graph = self.db.crate_graph();
- let res = module_tree.modules_for_file(file_id)
+ let res = module_tree
+ .modules_for_file(file_id)
.into_iter()
.map(|it| it.root(&module_tree))
.map(|it| it.file_id(&module_tree))
pub fn crate_root(&self, crate_id: CrateId) -> FileId {
self.db.crate_graph().crate_roots[&crate_id]
}
- pub fn completions(&self, file_id: FileId, offset: TextUnit) -> Cancelable<Option<Vec<CompletionItem>>> {
+ pub fn completions(
+ &self,
+ file_id: FileId,
+ offset: TextUnit,
+ ) -> Cancelable<Option<Vec<CompletionItem>>> {
let mut res = Vec::new();
let mut has_completions = false;
if let Some(scope_based) = scope_completion(&self.db, file_id, offset) {
res.extend(scope_based);
has_completions = true;
}
- let res = if has_completions {
- Some(res)
- } else {
- None
- };
+ let res = if has_completions { Some(res) } else { None };
Ok(res)
}
pub fn approximately_resolve_symbol(
let syntax = file.syntax();
// Find the binding associated with the offset
- let maybe_binding = find_node_at_offset::<ast::BindPat>(syntax, offset)
- .or_else(|| {
- let name_ref = find_node_at_offset::<ast::NameRef>(syntax, offset)?;
- let resolved = resolve_local_name(&self.db, file_id, name_ref)?;
- find_node_at_offset::<ast::BindPat>(syntax, resolved.1.end())
- });
+ let maybe_binding = find_node_at_offset::<ast::BindPat>(syntax, offset).or_else(|| {
+ let name_ref = find_node_at_offset::<ast::NameRef>(syntax, offset)?;
+ let resolved = resolve_local_name(&self.db, file_id, name_ref)?;
+ find_node_at_offset::<ast::BindPat>(syntax, resolved.1.end())
+ });
let binding = match maybe_binding {
None => return Vec::new(),
let decl = DeclarationDescriptor::new(binding);
let mut ret = vec![(file_id, decl.range)];
- ret.extend(decl.find_all_refs().into_iter()
- .map(|ref_desc| (file_id, ref_desc.range )));
+ ret.extend(
+ decl.find_all_refs()
+ .into_iter()
+ .map(|ref_desc| (file_id, ref_desc.range)),
+ );
ret
}
Some(id) => id,
None => return Vec::new(),
};
- module_id.child(module_tree, name.as_str())
+ module_id
+ .child(module_tree, name.as_str())
.map(|it| it.file_id(module_tree))
.into_iter()
.collect()
-use std::{
- sync::Arc,
- fmt,
-};
+use std::{fmt, sync::Arc};
-use salsa;
-use rustc_hash::FxHashSet;
use relative_path::RelativePath;
use rustc_hash::FxHashMap;
+use rustc_hash::FxHashSet;
+use salsa;
use crate::{symbol_index::SymbolIndex, FileResolverImp};
extern crate rustc_hash;
extern crate salsa;
-mod input;
+mod completion;
mod db;
mod descriptors;
mod imp;
+mod input;
+pub mod mock_analysis;
mod symbol_index;
-mod completion;
mod syntax_ptr;
-pub mod mock_analysis;
-use std::{
- fmt,
- sync::Arc,
-};
+use std::{fmt, sync::Arc};
use ra_syntax::{AtomEdit, File, TextRange, TextUnit};
-use relative_path::RelativePathBuf;
use rayon::prelude::*;
+use relative_path::RelativePathBuf;
use crate::{
imp::{AnalysisHostImpl, AnalysisImpl, FileResolverImp},
};
pub use crate::{
- descriptors::function::FnDescriptor,
completion::CompletionItem,
- input::{FileId, FileResolver, CrateGraph, CrateId},
+ descriptors::function::FnDescriptor,
+ input::{CrateGraph, CrateId, FileId, FileResolver},
};
pub use ra_editor::{
- FileSymbol, Fold, FoldKind, HighlightedRange, LineIndex, Runnable,
- RunnableKind, StructureNode,
+ FileSymbol, Fold, FoldKind, HighlightedRange, LineIndex, Runnable, RunnableKind, StructureNode,
};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
}
}
-impl std::error::Error for Canceled {
-}
+impl std::error::Error for Canceled {}
#[derive(Default)]
pub struct AnalysisChange {
}
}
-
impl AnalysisChange {
pub fn new() -> AnalysisChange {
AnalysisChange::default()
pub fn approximately_resolve_symbol(
&self,
file_id: FileId,
- offset: TextUnit
+ offset: TextUnit,
) -> Cancelable<Vec<(FileId, FileSymbol)>> {
- self.imp
- .approximately_resolve_symbol(file_id, offset)
+ self.imp.approximately_resolve_symbol(file_id, offset)
}
- pub fn find_all_refs(&self, file_id: FileId, offset: TextUnit, ) -> Cancelable<Vec<(FileId, TextRange)>> {
+ pub fn find_all_refs(
+ &self,
+ file_id: FileId,
+ offset: TextUnit,
+ ) -> Cancelable<Vec<(FileId, TextRange)>> {
Ok(self.imp.find_all_refs(file_id, offset))
}
pub fn parent_module(&self, file_id: FileId) -> Cancelable<Vec<(FileId, FileSymbol)>> {
let file = self.imp.file_syntax(file_id);
Ok(ra_editor::highlight(&file))
}
- pub fn completions(&self, file_id: FileId, offset: TextUnit) -> Cancelable<Option<Vec<CompletionItem>>> {
+ pub fn completions(
+ &self,
+ file_id: FileId,
+ offset: TextUnit,
+ ) -> Cancelable<Option<Vec<CompletionItem>>> {
self.imp.completions(file_id, offset)
}
pub fn assists(&self, file_id: FileId, range: TextRange) -> Cancelable<Vec<SourceChange>> {
let file = File::parse(text);
(*file_id, file)
}));
- LibraryData { files, file_resolver: FileResolverImp::new(file_resolver), symbol_index }
+ LibraryData {
+ files,
+ file_resolver: FileResolverImp::new(file_resolver),
+ symbol_index,
+ }
}
}
-
use std::sync::Arc;
-use relative_path::{RelativePath, RelativePathBuf};
use ra_syntax::TextUnit;
+use relative_path::{RelativePath, RelativePathBuf};
use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER};
-use crate::{
- AnalysisChange, Analysis, AnalysisHost, FileId, FileResolver,
-};
+use crate::{Analysis, AnalysisChange, AnalysisHost, FileId, FileResolver};
#[derive(Debug)]
pub struct FilePosition {
let mut res = MockAnalysis::new();
for entry in parse_fixture(fixture) {
if entry.text.contains(CURSOR_MARKER) {
- assert!(position.is_none(), "only one marker (<|>) per fixture is allowed");
+ assert!(
+ position.is_none(),
+ "only one marker (<|>) per fixture is allowed"
+ );
position = Some(res.add_file_with_position(&entry.meta, &entry.text));
} else {
res.add_file(&entry.meta, &entry.text);
FilePosition { file_id, offset }
}
pub fn id_of(&self, path: &str) -> FileId {
- let (idx, _) = self.files.iter().enumerate()
+ let (idx, _) = self
+ .files
+ .iter()
+ .enumerate()
.find(|(_, (p, _text))| path == p)
.expect("no file in this mock");
FileId(idx as u32 + 1)
}
impl Query {
- pub(crate) fn search(
- self,
- indices: &[Arc<SymbolIndex>],
- ) -> Vec<(FileId, FileSymbol)> {
+ pub(crate) fn search(self, indices: &[Arc<SymbolIndex>]) -> Vec<(FileId, FileSymbol)> {
let mut op = fst::map::OpBuilder::new();
for file_symbols in indices.iter() {
let automaton = fst::automaton::Subsequence::new(&self.lowercased);
use std::marker::PhantomData;
use ra_syntax::{
- File, TextRange, SyntaxKind, SyntaxNode, SyntaxNodeRef,
ast::{self, AstNode},
+ File, SyntaxKind, SyntaxNode, SyntaxNodeRef, TextRange,
};
-use crate::FileId;
use crate::db::SyntaxDatabase;
+use crate::FileId;
salsa::query_group! {
pub(crate) trait SyntaxPtrDatabase: SyntaxDatabase {
impl<'a> ToAst for &'a OwnedAst<ast::FnDef<'static>> {
type Ast = ast::FnDef<'a>;
fn to_ast(self) -> ast::FnDef<'a> {
- ast::FnDef::cast(self.syntax.borrowed())
- .unwrap()
+ ast::FnDef::cast(self.syntax.borrowed()).unwrap()
}
}
-
/// A pionter to a syntax node inside a file.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct LocalSyntaxPtr {
if curr.range() == self.range && curr.kind() == self.kind {
return curr.owned();
}
- curr = curr.children()
+ curr = curr
+ .children()
.find(|it| self.range.is_subrange(&it.range()))
.unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self))
}
}
pub(crate) fn into_global(self, file_id: FileId) -> SyntaxPtr {
- SyntaxPtr { file_id, local: self}
+ SyntaxPtr {
+ file_id,
+ local: self,
+ }
}
}
-
#[test]
fn test_local_syntax_ptr() {
let file = File::parse("struct Foo { f: u32, }");
- let field = file.syntax().descendants().find_map(ast::NamedFieldDef::cast).unwrap();
+ let field = file
+ .syntax()
+ .descendants()
+ .find_map(ast::NamedFieldDef::cast)
+ .unwrap();
let ptr = LocalSyntaxPtr::new(field.syntax());
let field_syntax = ptr.resolve(&file);
assert_eq!(field.syntax(), field_syntax);
extern crate rustc_hash;
extern crate test_utils;
-use ra_syntax::{TextRange};
-use test_utils::{assert_eq_dbg};
+use ra_syntax::TextRange;
+use test_utils::assert_eq_dbg;
use ra_analysis::{
+ mock_analysis::{analysis_and_position, single_file, single_file_with_position, MockAnalysis},
AnalysisChange, CrateGraph, FileId, FnDescriptor,
- mock_analysis::{MockAnalysis, single_file, single_file_with_position, analysis_and_position},
};
fn get_signature(text: &str) -> (FnDescriptor, Option<usize>) {
let (analysis, position) = single_file_with_position(text);
- analysis.resolve_callable(position.file_id, position.offset).unwrap().unwrap()
+ analysis
+ .resolve_callable(position.file_id, position.offset)
+ .unwrap()
+ .unwrap()
}
#[test]
fn test_resolve_module() {
- let (analysis, pos) = analysis_and_position("
+ let (analysis, pos) = analysis_and_position(
+ "
//- /lib.rs
mod <|>foo;
//- /foo.rs
// empty
- ");
+ ",
+ );
- let symbols = analysis.approximately_resolve_symbol(pos.file_id, pos.offset).unwrap();
+ let symbols = analysis
+ .approximately_resolve_symbol(pos.file_id, pos.offset)
+ .unwrap();
assert_eq_dbg(
r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#,
&symbols,
);
- let (analysis, pos) = analysis_and_position("
+ let (analysis, pos) = analysis_and_position(
+ "
//- /lib.rs
mod <|>foo;
//- /foo/mod.rs
// empty
- ");
+ ",
+ );
- let symbols = analysis.approximately_resolve_symbol(pos.file_id, pos.offset).unwrap();
+ let symbols = analysis
+ .approximately_resolve_symbol(pos.file_id, pos.offset)
+ .unwrap();
assert_eq_dbg(
r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#,
&symbols,
#[test]
fn test_resolve_parent_module() {
- let (analysis, pos) = analysis_and_position("
+ let (analysis, pos) = analysis_and_position(
+ "
//- /lib.rs
mod foo;
//- /foo.rs
<|>// empty
- ");
+ ",
+ );
let symbols = analysis.parent_module(pos.file_id).unwrap();
assert_eq_dbg(
r#"[(FileId(1), FileSymbol { name: "foo", node_range: [0; 8), kind: MODULE })]"#,
#[test]
fn test_resolve_crate_root() {
- let mock = MockAnalysis::with_files("
+ let mock = MockAnalysis::with_files(
+ "
//- /lib.rs
mod foo;
//- /foo.rs
// emtpy <|>
- ");
+ ",
+ );
let root_file = mock.id_of("/lib.rs");
let mod_file = mock.id_of("/foo.rs");
let mut host = mock.analysis_host();
assert_eq!(desc.ret_type, Some("-> i32".to_string()));
assert_eq!(param, Some(0));
assert_eq!(desc.label, "pub fn add_one(x: i32) -> i32".to_string());
- assert_eq!(desc.doc, Some(
-r#"Adds one to the number given.
+ assert_eq!(
+ desc.doc,
+ Some(
+ r#"Adds one to the number given.
# Examples
let five = 5;
assert_eq!(6, my_crate::add_one(5));
-```"#.into()));
+```"#
+ .into()
+ )
+ );
}
#[test]
pub fn do_it() {
addr {};
addr::add_one(<|>);
-}"#);
+}"#,
+ );
assert_eq!(desc.name, "add_one".to_string());
assert_eq!(desc.params, vec!["x".to_string()]);
assert_eq!(desc.ret_type, Some("-> i32".to_string()));
assert_eq!(param, Some(0));
assert_eq!(desc.label, "pub fn add_one(x: i32) -> i32".to_string());
- assert_eq!(desc.doc, Some(
-r#"Adds one to the number given.
+ assert_eq!(
+ desc.doc,
+ Some(
+ r#"Adds one to the number given.
# Examples
let five = 5;
assert_eq!(6, my_crate::add_one(5));
-```"#.into()));
+```"#
+ .into()
+ )
+ );
}
#[test]
r.finished(<|>);
}
-"#);
+"#,
+ );
assert_eq!(desc.name, "finished".to_string());
- assert_eq!(desc.params, vec!["&mut self".to_string(), "ctx".to_string()]);
+ assert_eq!(
+ desc.params,
+ vec!["&mut self".to_string(), "ctx".to_string()]
+ );
assert_eq!(desc.ret_type, None);
assert_eq!(param, Some(1));
- assert_eq!(desc.doc, Some(
-r#"Method is called when writer finishes.
-
-By default this method stops actor's `Context`."#.into()));
+ assert_eq!(
+ desc.doc,
+ Some(
+ r#"Method is called when writer finishes.
+
+By default this method stops actor's `Context`."#
+ .into()
+ )
+ );
}
-
fn get_all_refs(text: &str) -> Vec<(FileId, TextRange)> {
let (analysis, position) = single_file_with_position(text);
- analysis.find_all_refs(position.file_id, position.offset).unwrap()
+ analysis
+ .find_all_refs(position.file_id, position.offset)
+ .unwrap()
}
#[test]
#[test]
fn test_complete_crate_path() {
- let (analysis, position) = analysis_and_position("
+ let (analysis, position) = analysis_and_position(
+ "
//- /lib.rs
mod foo;
struct Spam;
//- /foo.rs
use crate::Sp<|>
- ");
- let completions = analysis.completions(position.file_id, position.offset).unwrap().unwrap();
+ ",
+ );
+ let completions = analysis
+ .completions(position.file_id, position.offset)
+ .unwrap()
+ .unwrap();
assert_eq_dbg(
r#"[CompletionItem { label: "foo", lookup: None, snippet: None },
CompletionItem { label: "Spam", lookup: None, snippet: None }]"#,
let file = File::parse(&text);
let folds = folding_ranges(&file);
- assert_eq!(folds.len(), ranges.len(), "The amount of folds is different than the expected amount");
- assert_eq!(folds.len(), fold_kinds.len(), "The amount of fold kinds is different than the expected amount");
+ assert_eq!(
+ folds.len(),
+ ranges.len(),
+ "The amount of folds is different than the expected amount"
+ );
+ assert_eq!(
+ folds.len(),
+ fold_kinds.len(),
+ "The amount of fold kinds is different than the expected amount"
+ );
for ((fold, range), fold_kind) in folds
.into_iter()
.zip(ranges.into_iter())
leaf.ancestors().filter_map(N::cast).next()
}
-
-
#[cfg(test)]
mod tests {
use super::*;
use crate::TextRange;
use ra_syntax::{
- algo::{
- visit::{visitor, Visitor},
- },
+ algo::visit::{visitor, Visitor},
ast::{self, NameOwner},
- AstNode, File, SmolStr, SyntaxKind, SyntaxNodeRef,
- WalkEvent,
+ AstNode, File, SmolStr, SyntaxKind, SyntaxNodeRef, WalkEvent,
};
#[derive(Debug, Clone)]
let mut res = Vec::new();
let mut stack = Vec::new();
-
for event in file.syntax().preorder() {
match event {
WalkEvent::Enter(node) => {
stack.push(res.len());
res.push(symbol);
}
- },
+ }
WalkEvent::Leave(node) => {
if structure_node(node).is_some() {
stack.pop().unwrap();
use languageserver_types::{
CodeActionProviderCapability, CompletionOptions, DocumentOnTypeFormattingOptions,
- ExecuteCommandOptions, FoldingRangeProviderCapability, ServerCapabilities,
- SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind,
- TextDocumentSyncOptions, RenameProviderCapability, RenameOptions
+ ExecuteCommandOptions, FoldingRangeProviderCapability, RenameOptions, RenameProviderCapability,
+ ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind,
+ TextDocumentSyncOptions,
};
pub fn server_capabilities() -> ServerCapabilities {
more_trigger_character: None,
}),
folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)),
- rename_provider: Some(RenameProviderCapability::Options(RenameOptions{
- prepare_provider: Some(true)
+ rename_provider: Some(RenameProviderCapability::Options(RenameOptions {
+ prepare_provider: Some(true),
})),
color_provider: None,
execute_command_provider: Some(ExecuteCommandOptions {
.map(|it| it.edits.as_slice())
.unwrap_or(&[]);
let line_col = translate_offset_with_edit(&*line_index, pos.offset, edits);
- let position = Position::new(u64::from(line_col.line), u64::from(u32::from(line_col.col)));
+ let position =
+ Position::new(u64::from(line_col.line), u64::from(u32::from(line_col.col)));
Some(TextDocumentPositionParams {
text_document: TextDocumentIdentifier::new(pos.file_id.try_conv_with(world)?),
position,
mod vfs;
pub type Result<T> = ::std::result::Result<T, ::failure::Error>;
-pub use crate::{caps::server_capabilities, main_loop::main_loop, main_loop::LspError};
\ No newline at end of file
+pub use crate::{caps::server_capabilities, main_loop::main_loop, main_loop::LspError};
use std::collections::HashMap;
-use rustc_hash::FxHashMap;
+use gen_lsp_server::ErrorCode;
use languageserver_types::{
CodeActionResponse, Command, CompletionItem, CompletionItemKind, Diagnostic,
- DiagnosticSeverity, DocumentSymbol, FoldingRange, FoldingRangeKind, FoldingRangeParams,
- InsertTextFormat, Location, Position, SymbolInformation, TextDocumentIdentifier, TextEdit,
- RenameParams, WorkspaceEdit, PrepareRenameResponse, Documentation, MarkupContent, MarkupKind
+ DiagnosticSeverity, DocumentSymbol, Documentation, FoldingRange, FoldingRangeKind,
+ FoldingRangeParams, InsertTextFormat, Location, MarkupContent, MarkupKind, Position,
+ PrepareRenameResponse, RenameParams, SymbolInformation, TextDocumentIdentifier, TextEdit,
+ WorkspaceEdit,
};
-use gen_lsp_server::ErrorCode;
use ra_analysis::{FileId, FoldKind, Query, RunnableKind};
use ra_syntax::text_utils::contains_offset_nonstrict;
+use rustc_hash::FxHashMap;
use serde_json::to_value;
use crate::{
project_model::TargetKind,
req::{self, Decoration},
server_world::ServerWorld,
- Result, LspError
+ LspError, Result,
};
-pub fn handle_syntax_tree(
- world: ServerWorld,
- params: req::SyntaxTreeParams,
-) -> Result<String> {
+pub fn handle_syntax_tree(world: ServerWorld, params: req::SyntaxTreeParams) -> Result<String> {
let id = params.text_document.try_conv_with(&world)?;
let res = world.analysis().syntax_tree(id);
Ok(res)
return Ok(Some(res));
- fn exec_query(
- world: &ServerWorld,
- query: Query,
- ) -> Result<Vec<SymbolInformation>> {
+ fn exec_query(world: &ServerWorld, query: Query) -> Result<Vec<SymbolInformation>> {
let mut res = Vec::new();
for (file_id, symbol) in world.analysis().symbol_search(query)? {
let line_index = world.analysis().file_line_index(file_id);
});
return Ok(res);
- fn runnable_args(world: &ServerWorld, file_id: FileId, kind: &RunnableKind) -> Result<Vec<String>> {
+ fn runnable_args(
+ world: &ServerWorld,
+ file_id: FileId,
+ kind: &RunnableKind,
+ ) -> Result<Vec<String>> {
let spec = CargoTargetSpec::for_file(world, file_id)?;
let mut res = Vec::new();
match kind {
};
let file_id = world.analysis().crate_root(crate_id)?;
let path = world.path_map.get_path(file_id);
- let res = world
- .workspaces
- .iter()
- .find_map(|ws| {
- let tgt = ws.target_by_root(path)?;
- let res = CargoTargetSpec {
- package: tgt.package(ws).name(ws).to_string(),
- target: tgt.name(ws).to_string(),
- target_kind: tgt.kind(ws),
- };
- Some(res)
- });
+ let res = world.workspaces.iter().find_map(|ws| {
+ let tgt = ws.target_by_root(path)?;
+ let res = CargoTargetSpec {
+ package: tgt.package(ws).name(ws).to_string(),
+ target: tgt.name(ws).to_string(),
+ target_kind: tgt.kind(ws),
+ };
+ Some(res)
+ });
Ok(res)
}
}
TargetKind::Other => (),
}
-
}
}
}
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)?
- {
+ if let Some((descriptor, active_param)) = world.analysis().resolve_callable(file_id, offset)? {
let parameters: Vec<ParameterInformation> = descriptor
.params
.iter()
let documentation = if let Some(doc) = descriptor.doc {
Some(Documentation::MarkupContent(MarkupContent {
kind: MarkupKind::Markdown,
- value: doc
+ value: doc,
}))
} else {
None
Ok(Some(PrepareRenameResponse::Range(loc.range)))
}
-pub fn handle_rename(
- world: ServerWorld,
- params: RenameParams,
-) -> Result<Option<WorkspaceEdit>> {
+pub fn handle_rename(world: ServerWorld, params: RenameParams) -> Result<Option<WorkspaceEdit>> {
let file_id = params.text_document.try_conv_with(&world)?;
let line_index = world.analysis().file_line_index(file_id);
let offset = params.position.conv_with(&line_index);
if params.new_name.is_empty() {
- return Err(LspError::new(ErrorCode::InvalidParams as i32, "New Name cannot be empty".into()).into());
+ return Err(LspError::new(
+ ErrorCode::InvalidParams as i32,
+ "New Name cannot be empty".into(),
+ )
+ .into());
}
let refs = world.analysis().find_all_refs(file_id, offset)?;
let mut changes = HashMap::new();
for r in refs {
if let Ok(loc) = to_location(r.0, r.1, &world, &line_index) {
- changes.entry(loc.uri).or_insert(Vec::new()).push(
- TextEdit {
- range: loc.range,
- new_text: params.new_name.clone()
- });
+ changes.entry(loc.uri).or_insert(Vec::new()).push(TextEdit {
+ range: loc.range,
+ new_text: params.new_name.clone(),
+ });
}
}
changes: Some(changes),
// TODO: return this instead if client/server support it. See #144
- document_changes : None,
+ document_changes: None,
}))
}
let refs = world.analysis().find_all_refs(file_id, offset)?;
- Ok(Some(refs.into_iter()
- .filter_map(|r| to_location(r.0, r.1, &world, &line_index).ok())
- .collect()))
+ Ok(Some(
+ refs.into_iter()
+ .filter_map(|r| to_location(r.0, r.1, &world, &line_index).ok())
+ .collect(),
+ ))
}
pub fn handle_code_action(
};
#[derive(Debug, Fail)]
-#[fail(display = "Language Server request failed with {}. ({})", code, message)]
+#[fail(
+ display = "Language Server request failed with {}. ({})",
+ code, message
+)]
pub struct LspError {
pub code: i32,
pub message: String,
impl LspError {
pub fn new(code: i32, message: String) -> LspError {
- LspError {code, message}
+ LspError { code, message }
}
}
}
}
-fn on_task(
- task: Task,
- msg_sender: &Sender<RawMessage>,
- pending_requests: &mut FxHashSet<u64>,
-) {
+fn on_task(task: Task, msg_sender: &Sender<RawMessage>, pending_requests: &mut FxHashSet<u64>) {
match task {
Task::Respond(response) => {
if pending_requests.remove(&response.id) {
self.pool.spawn(move || {
let resp = match f(world, params) {
Ok(resp) => RawResponse::ok::<R>(id, &resp),
- Err(e) => {
- match e.downcast::<LspError>() {
- Ok(lsp_error) => RawResponse::err(id, lsp_error.code, lsp_error.message),
- Err(e) => RawResponse::err(id, ErrorCode::InternalError as i32, format!("{}\n{}", e, e.backtrace()))
+ Err(e) => match e.downcast::<LspError>() {
+ Ok(lsp_error) => {
+ RawResponse::err(id, lsp_error.code, lsp_error.message)
}
- }
+ Err(e) => RawResponse::err(
+ id,
+ ErrorCode::InternalError as i32,
+ format!("{}\n{}", e, e.backtrace()),
+ ),
+ },
};
let task = Task::Respond(resp);
sender.send(task);
if !is_canceled(&e) {
error!("failed to compute diagnostics: {:?}", e);
}
- },
+ }
Ok(params) => {
let not = RawNotification::new::<req::PublishDiagnostics>(¶ms);
sender.send(Task::Notify(not));
if !is_canceled(&e) {
error!("failed to compute decorations: {:?}", e);
}
- },
+ }
Ok(params) => {
let not = RawNotification::new::<req::PublishDecorations>(¶ms);
sender.send(Task::Notify(not))
}
pub fn get_or_insert(&mut self, path: PathBuf, root: Root) -> (bool, FileId) {
let mut inserted = false;
- let file_id = self.path2id
+ let file_id = self
+ .path2id
.get(path.as_path())
.map(|&id| id)
.unwrap_or_else(|| {
notification::*, request::*, ApplyWorkspaceEditParams, CodeActionParams, CompletionParams,
CompletionResponse, DocumentOnTypeFormattingParams, DocumentSymbolParams,
DocumentSymbolResponse, ExecuteCommandParams, Hover, InitializeResult,
- PublishDiagnosticsParams, SignatureHelp, TextDocumentEdit, TextDocumentPositionParams,
- TextEdit, WorkspaceSymbolParams, ReferenceParams,
+ PublishDiagnosticsParams, ReferenceParams, SignatureHelp, TextDocumentEdit,
+ TextDocumentPositionParams, TextEdit, WorkspaceSymbolParams,
};
pub enum SyntaxTree {}
};
use languageserver_types::Url;
-use ra_analysis::{Analysis, AnalysisHost, AnalysisChange, CrateGraph, FileId, FileResolver, LibraryData};
+use ra_analysis::{
+ Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, FileResolver, LibraryData,
+};
use rustc_hash::FxHashMap;
use crate::{
Some((file_id, text))
}
})
- .for_each(|(file_id, text)| {
- change.add_file(file_id, text)
- });
+ .for_each(|(file_id, text)| change.add_file(file_id, text));
}
if inserted {
change.set_file_resolver(Arc::new(self.path_map.clone()))
pub mod visit;
// pub mod walk;
-use crate::{
- text_utils::{contains_offset_nonstrict},
- SyntaxNodeRef, TextRange, TextUnit,
-};
+use crate::{text_utils::contains_offset_nonstrict, SyntaxNodeRef, TextRange, TextUnit};
pub fn find_leaf_at_offset(node: SyntaxNodeRef, offset: TextUnit) -> LeafAtOffset {
let range = node.range();
}
pub trait DocCommentsOwner<'a>: AstNode<'a> {
- fn doc_comments(self) -> AstChildren<'a, Comment<'a>> { children(self) }
+ fn doc_comments(self) -> AstChildren<'a, Comment<'a>> {
+ children(self)
+ }
/// Returns the textual content of a doc comment block as a single string.
/// That is, strips leading `///` and joins lines
self.doc_comments()
.map(|comment| {
let prefix = comment.prefix();
- let trimmed = comment.text().as_str()
+ let trimmed = comment
+ .text()
+ .as_str()
.trim()
.trim_start_matches(prefix)
.trim_start();
trimmed.to_owned()
- }).join("\n")
+ })
+ .join("\n")
}
}
}
}
-
#[derive(Debug, Clone, Copy)]
pub enum PathSegmentKind<'a> {
Name(NameRef<'a>),
impl<'a> PathSegment<'a> {
pub fn parent_path(self) -> Path<'a> {
- self.syntax().parent().and_then(Path::cast)
+ self.syntax()
+ .parent()
+ .and_then(Path::cast)
.expect("segments are always nested in paths")
}
reparsing::AtomEdit,
rowan::{SmolStr, TextRange, TextUnit},
syntax_kinds::SyntaxKind,
- yellow::{Direction, OwnedRoot, RefRoot, SyntaxError, SyntaxNode, SyntaxNodeRef, TreeRoot, WalkEvent},
+ yellow::{
+ Direction, OwnedRoot, RefRoot, SyntaxError, SyntaxNode, SyntaxNodeRef, TreeRoot, WalkEvent,
+ },
};
use crate::yellow::GreenNode;
-use crate::{
- File, SyntaxKind, SyntaxNodeRef, WalkEvent
-};
+use crate::{File, SyntaxKind, SyntaxNodeRef, WalkEvent};
use std::fmt::Write;
/// Parse a file and create a string representation of the resulting parse tree.
res
}
-
#[derive(Debug)]
pub struct FixtureEntry {
pub meta: String,
macro_rules! flush {
() => {
if let Some(meta) = meta {
- res.push(FixtureEntry { meta: meta.to_string(), text: buf.clone() });
+ res.push(FixtureEntry {
+ meta: meta.to_string(),
+ text: buf.clone(),
+ });
buf.clear();
}
};
};
- let margin = fixture.lines()
+ let margin = fixture
+ .lines()
.filter(|it| it.trim_start().starts_with("//-"))
.map(|it| it.len() - it.trim_start().len())
- .next().expect("empty fixture");
- let lines = fixture.lines()
- .filter_map(|line| {
- if line.len() >= margin {
- assert!(line[..margin].trim().is_empty());
- Some(&line[margin..])
- } else {
- assert!(line.trim().is_empty());
- None
- }
- });
+ .next()
+ .expect("empty fixture");
+ let lines = fixture.lines().filter_map(|line| {
+ if line.len() >= margin {
+ assert!(line[..margin].trim().is_empty());
+ Some(&line[margin..])
+ } else {
+ assert!(line.trim().is_empty());
+ None
+ }
+ });
for line in lines {
if line.starts_with("//-") {
-extern crate itertools;
extern crate failure;
+extern crate itertools;
extern crate teraron;
use std::{
process::Command,
};
-use itertools::Itertools;
use failure::bail;
+use itertools::Itertools;
-pub use teraron::{Mode, Verify, Overwrite};
+pub use teraron::{Mode, Overwrite, Verify};
pub type Result<T> = ::std::result::Result<T, failure::Error>;
let grammar = project_root().join(GRAMMAR);
let syntax_kinds = project_root().join(SYNTAX_KINDS);
let ast = project_root().join(AST);
- teraron::generate(
- &syntax_kinds,
- &grammar,
- mode,
- )?;
- teraron::generate(
- &ast,
- &grammar,
- mode,
- )?;
+ teraron::generate(&syntax_kinds, &grammar, mode)?;
+ teraron::generate(&ast, &grammar, mode)?;
Ok(())
}
pub fn run_rustfmt(mode: Mode) -> Result<()> {
run(&format!("rustup install {}", TOOLCHAIN), ".")?;
- run(&format!("rustup component add rustfmt-preview --toolchain {}", TOOLCHAIN), ".")?;
+ run(
+ &format!(
+ "rustup component add rustfmt-preview --toolchain {}",
+ TOOLCHAIN
+ ),
+ ".",
+ )?;
if mode == Verify {
- run(&format!("rustup run {} -- cargo fmt -- --check", TOOLCHAIN), ".")?;
+ run(
+ &format!("rustup run {} -- cargo fmt -- --check", TOOLCHAIN),
+ ".",
+ )?;
} else {
run(&format!("rustup run {} -- cargo fmt", TOOLCHAIN), ".")?;
}
extern crate clap;
extern crate failure;
+extern crate teraron;
extern crate tools;
extern crate walkdir;
-extern crate teraron;
use clap::{App, Arg, SubCommand};
+use failure::bail;
use std::{
collections::HashMap,
fs,
path::{Path, PathBuf},
};
-use tools::{
- collect_tests, Result, Test, generate, Mode, Overwrite, Verify, run, run_rustfmt,
-};
-use failure::bail;
+use tools::{collect_tests, generate, run, run_rustfmt, Mode, Overwrite, Result, Test, Verify};
const GRAMMAR_DIR: &str = "./crates/ra_syntax/src/grammar";
const INLINE_TESTS_DIR: &str = "./crates/ra_syntax/tests/data/parser/inline";
extern crate tools;
-use tools::{
- generate, Verify, run_rustfmt,
-};
+use tools::{generate, run_rustfmt, Verify};
#[test]
fn verify_template_generation() {
#[test]
fn check_code_formatting() {
if let Err(error) = run_rustfmt(Verify) {
- panic!("{}. Please format the code by running `cargo format`", error);
+ panic!(
+ "{}. Please format the code by running `cargo format`",
+ error
+ );
}
}