Generalize query
This commit is contained in:
parent
0568e76406
commit
7fc91f41d8
5 changed files with 79 additions and 110 deletions
|
@ -1,84 +0,0 @@
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use fst;
|
|
||||||
use fst::IntoStreamer;
|
|
||||||
use file;
|
|
||||||
|
|
||||||
use fall_tree::{TextRange, NodeType};
|
|
||||||
use indxr::{FileIndex, IndexableFileSet};
|
|
||||||
|
|
||||||
use editor::line_index::{LineCol, LineIndex};
|
|
||||||
use editor::fst_subseq::FstSubSeq;
|
|
||||||
use editor::file_symbols::process_symbols;
|
|
||||||
|
|
||||||
use syntax::{STRUCT_DEF, ENUM_DEF, TRAIT_DEF, TYPE_DEF};
|
|
||||||
|
|
||||||
|
|
||||||
pub struct SymbolIndex {
|
|
||||||
index: FileIndex<FileSymbols>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SymbolIndex {
|
|
||||||
pub fn new(roots: Vec<PathBuf>) -> SymbolIndex {
|
|
||||||
let file_set = IndexableFileSet::new(roots, "rs");
|
|
||||||
let index = FileIndex::new(file_set, Box::new(|path| {
|
|
||||||
let text = file::get_text(path).ok()?;
|
|
||||||
Some(FileSymbols::new(text))
|
|
||||||
}));
|
|
||||||
SymbolIndex { index }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn query(&self, query: &str) -> Vec<(PathBuf, Symbol)> {
|
|
||||||
let mut query = Query::new(query);
|
|
||||||
let mut result = Vec::new();
|
|
||||||
self.process_query(&query, &mut result);
|
|
||||||
if result.is_empty() && !query.all_symbols {
|
|
||||||
query.all_symbols = true;
|
|
||||||
self.process_query(&query, &mut result);
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
fn process_query(&self, query: &Query, acc: &mut Vec<(PathBuf, Symbol)>) {
|
|
||||||
self.index.process_files(&mut |file| {
|
|
||||||
query.process(&file.value, &mut |symbol| {
|
|
||||||
acc.push((file.path.clone(), symbol))
|
|
||||||
});
|
|
||||||
acc.len() > 512
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Query {
|
|
||||||
query: String,
|
|
||||||
all_symbols: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Query {
|
|
||||||
fn new(query: &str) -> Query {
|
|
||||||
let all_symbols = query.contains("#");
|
|
||||||
let query: String = query.chars()
|
|
||||||
.filter(|&c| c != '#')
|
|
||||||
.flat_map(char::to_lowercase)
|
|
||||||
.collect();
|
|
||||||
Query { query, all_symbols }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn process(&self, file: &FileSymbols, acc: &mut FnMut(Symbol)) {
|
|
||||||
fn is_type(ty: NodeType) -> bool {
|
|
||||||
match ty {
|
|
||||||
STRUCT_DEF | ENUM_DEF | TRAIT_DEF| TYPE_DEF => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let a = FstSubSeq::new(&self.query);
|
|
||||||
for idx in file.map.search(a).into_stream().into_values() {
|
|
||||||
let idx = idx as usize;
|
|
||||||
let symbol = file.symbols[idx].clone();
|
|
||||||
if self.all_symbols || is_type(symbol.ty) {
|
|
||||||
acc(symbol)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -21,7 +21,8 @@ use std::{
|
||||||
use libsyntax2::ast;
|
use libsyntax2::ast;
|
||||||
use libeditor::{LineIndex, FileSymbol};
|
use libeditor::{LineIndex, FileSymbol};
|
||||||
|
|
||||||
use self::symbol_index::{FileSymbols, Query};
|
use self::symbol_index::{FileSymbols};
|
||||||
|
pub use self::symbol_index::Query;
|
||||||
|
|
||||||
pub type Result<T> = ::std::result::Result<T, ::failure::Error>;
|
pub type Result<T> = ::std::result::Result<T, ::failure::Error>;
|
||||||
|
|
||||||
|
@ -89,14 +90,13 @@ impl World {
|
||||||
Ok(index.clone())
|
Ok(index.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn world_symbols<'a>(&'a self, query: &str) -> impl Iterator<Item=(&'a Path, &'a FileSymbol)> + 'a
|
pub fn world_symbols<'a>(&'a self, query: Query) -> impl Iterator<Item=(&'a Path, &'a FileSymbol)> + 'a
|
||||||
{
|
{
|
||||||
let q = Query::new(query);
|
|
||||||
self.data.file_map.iter()
|
self.data.file_map.iter()
|
||||||
.flat_map(move |(path, data)| {
|
.flat_map(move |(path, data)| {
|
||||||
let path: &'a Path = path.as_path();
|
let path: &'a Path = path.as_path();
|
||||||
let symbols = data.symbols(path);
|
let symbols = data.symbols(path);
|
||||||
q.process(symbols).map(move |s| (path, s))
|
query.process(symbols).map(move |s| (path, s))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ use libsyntax2::{
|
||||||
ast,
|
ast,
|
||||||
SyntaxKind::{self, *},
|
SyntaxKind::{self, *},
|
||||||
};
|
};
|
||||||
use fst::{self, IntoStreamer};
|
use fst::{self, IntoStreamer, Streamer};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct FileSymbols {
|
pub(crate) struct FileSymbols {
|
||||||
|
@ -30,19 +30,30 @@ impl FileSymbols {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct Query {
|
pub struct Query {
|
||||||
query: String,
|
query: String,
|
||||||
all_symbols: bool,
|
lowercased: String,
|
||||||
|
only_types: bool,
|
||||||
|
exact: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Query {
|
impl Query {
|
||||||
pub(crate) fn new(query: &str) -> Query {
|
pub fn new(query: String) -> Query {
|
||||||
let all_symbols = query.contains("#");
|
let lowercased = query.to_lowercase();
|
||||||
let query: String = query.chars()
|
Query {
|
||||||
.filter(|&c| c != '#')
|
query,
|
||||||
.flat_map(char::to_lowercase)
|
lowercased,
|
||||||
.collect();
|
only_types: false,
|
||||||
Query { query, all_symbols }
|
exact: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn only_types(&mut self) {
|
||||||
|
self.only_types = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn exact(&mut self) {
|
||||||
|
self.exact = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn process<'a>(
|
pub(crate) fn process<'a>(
|
||||||
|
@ -55,16 +66,21 @@ impl Query {
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let automaton = fst::automaton::Subsequence::new(&self.query);
|
let automaton = fst::automaton::Subsequence::new(&self.lowercased);
|
||||||
let all_symbols = self.all_symbols;
|
let mut stream = file.map.search(automaton).into_stream();
|
||||||
file.map.search(automaton).into_stream()
|
let mut res = Vec::new();
|
||||||
.into_values()
|
while let Some((_, idx)) = stream.next() {
|
||||||
.into_iter()
|
let idx = idx as usize;
|
||||||
.map(move |idx| {
|
let symbol = &file.symbols[idx];
|
||||||
let idx = idx as usize;
|
if self.only_types && !is_type(symbol.kind) {
|
||||||
&file.symbols[idx]
|
continue;
|
||||||
})
|
}
|
||||||
.filter(move |s| all_symbols || is_type(s.kind))
|
if self.exact && symbol.name != self.query {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
res.push(symbol)
|
||||||
|
}
|
||||||
|
res.into_iter()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ use languageserver_types::{
|
||||||
Command, TextDocumentIdentifier, WorkspaceEdit,
|
Command, TextDocumentIdentifier, WorkspaceEdit,
|
||||||
SymbolInformation, Location,
|
SymbolInformation, Location,
|
||||||
};
|
};
|
||||||
use libanalysis::{World};
|
use libanalysis::{World, Query};
|
||||||
use libeditor;
|
use libeditor;
|
||||||
use libsyntax2::TextUnit;
|
use libsyntax2::TextUnit;
|
||||||
use serde_json::{to_value, from_value};
|
use serde_json::{to_value, from_value};
|
||||||
|
@ -100,7 +100,20 @@ pub fn handle_workspace_symbol(
|
||||||
params: req::WorkspaceSymbolParams,
|
params: req::WorkspaceSymbolParams,
|
||||||
) -> Result<Option<Vec<SymbolInformation>>> {
|
) -> Result<Option<Vec<SymbolInformation>>> {
|
||||||
let mut acc = Vec::new();
|
let mut acc = Vec::new();
|
||||||
for (path, symbol) in world.world_symbols(¶ms.query).take(128) {
|
|
||||||
|
let query = {
|
||||||
|
let all_symbols = params.query.contains("#");
|
||||||
|
let query: String = params.query.chars()
|
||||||
|
.filter(|&c| c != '#')
|
||||||
|
.collect();
|
||||||
|
let mut q = Query::new(query);
|
||||||
|
if !all_symbols {
|
||||||
|
q.only_types();
|
||||||
|
}
|
||||||
|
q
|
||||||
|
};
|
||||||
|
|
||||||
|
for (path, symbol) in world.world_symbols(query).take(128) {
|
||||||
let line_index = world.file_line_index(path)?;
|
let line_index = world.file_line_index(path)?;
|
||||||
|
|
||||||
let info = SymbolInformation {
|
let info = SymbolInformation {
|
||||||
|
|
|
@ -49,6 +49,30 @@ impl<'a> PartialEq<SmolStr> for &'a str {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PartialEq<String> for SmolStr {
|
||||||
|
fn eq(&self, other: &String) -> bool {
|
||||||
|
self.as_str() == other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq<SmolStr> for String {
|
||||||
|
fn eq(&self, other: &SmolStr) -> bool {
|
||||||
|
other == self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> PartialEq<&'a String> for SmolStr {
|
||||||
|
fn eq(&self, other: &&'a String) -> bool {
|
||||||
|
self == *other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> PartialEq<SmolStr> for &'a String {
|
||||||
|
fn eq(&self, other: &SmolStr) -> bool {
|
||||||
|
*self == other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Debug for SmolStr {
|
impl fmt::Debug for SmolStr {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
fmt::Debug::fmt(self.as_str(), f)
|
fmt::Debug::fmt(self.as_str(), f)
|
||||||
|
|
Loading…
Add table
Reference in a new issue