Skip to content

Commit

Permalink
Switch to file ids
Browse files Browse the repository at this point in the history
  • Loading branch information
matklad committed Aug 15, 2018
1 parent 1096583 commit 9f6cf42
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 125 deletions.
10 changes: 1 addition & 9 deletions crates/libanalysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ pub type Result<T> = ::std::result::Result<T, ::failure::Error>;
const INDEXING_THRESHOLD: usize = 128;

pub struct WorldState {
next_file_id: u32,
data: Arc<WorldData>
}

Expand All @@ -47,12 +46,11 @@ pub struct World {
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct FileId(u32);
pub struct FileId(pub u32);

impl WorldState {
pub fn new() -> WorldState {
WorldState {
next_file_id: 0,
data: Arc::new(WorldData::default())
}
}
Expand All @@ -61,12 +59,6 @@ impl WorldState {
World { data: self.data.clone() }
}

pub fn new_file_id(&mut self) -> FileId {
let id = FileId(self.next_file_id);
self.next_file_id += 1;
id
}

pub fn change_file(&mut self, file_id: FileId, text: Option<String>) {
self.change_files(::std::iter::once((file_id, text)));
}
Expand Down
1 change: 1 addition & 0 deletions crates/server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ log = "0.4.3"
url_serde = "0.2.0"
languageserver-types = "0.49.0"
walkdir = "2.2.0"
im = { version = "11.0.1", features = ["arc"] }
text_unit = { version = "0.1.2", features = ["serde"] }

libsyntax2 = { path = "../libsyntax2" }
Expand Down
72 changes: 59 additions & 13 deletions crates/server/src/conv.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use std::path::Path;

use languageserver_types::{Range, SymbolKind, Position, TextEdit, Location, Url};
use languageserver_types::{
Range, SymbolKind, Position, TextEdit, Location, Url,
TextDocumentIdentifier, VersionedTextDocumentIdentifier, TextDocumentItem,
};
use libeditor::{LineIndex, LineCol, Edit, AtomEdit};
use libsyntax2::{SyntaxKind, TextUnit, TextRange};
use libanalysis::FileId;

use Result;
use {Result, PathMap};

pub trait Conv {
type Output;
Expand Down Expand Up @@ -115,21 +117,65 @@ impl ConvWith for AtomEdit {
}
}

impl<'a> TryConvWith for (&'a Path, TextRange) {
type Ctx = LineIndex;
type Output = Location;
impl<'a> TryConvWith for &'a Url {
type Ctx = PathMap;
type Output = FileId;
fn try_conv_with(self, path_map: &PathMap) -> Result<FileId> {
let path = self.to_file_path()
.map_err(|()| format_err!("invalid uri: {}", self))?;
path_map.get_id(&path).ok_or_else(|| format_err!("unknown file: {}", path.display()))
}
}

impl TryConvWith for FileId {
type Ctx = PathMap;
type Output = Url;
fn try_conv_with(self, path_map: &PathMap) -> Result<Url> {
let path = path_map.get_path(self);
let url = Url::from_file_path(path)
.map_err(|()| format_err!("can't convert path to url: {}", path.display()))?;
Ok(url)
}
}

impl<'a> TryConvWith for &'a TextDocumentItem {
type Ctx = PathMap;
type Output = FileId;
fn try_conv_with(self, path_map: &PathMap) -> Result<FileId> {
self.uri.try_conv_with(path_map)
}
}

fn try_conv_with(self, line_index: &LineIndex) -> Result<Location> {
impl<'a> TryConvWith for &'a VersionedTextDocumentIdentifier {
type Ctx = PathMap;
type Output = FileId;
fn try_conv_with(self, path_map: &PathMap) -> Result<FileId> {
self.uri.try_conv_with(path_map)
}
}

impl<'a> TryConvWith for &'a TextDocumentIdentifier {
type Ctx = PathMap;
type Output = FileId;
fn try_conv_with(self, path_map: &PathMap) -> Result<FileId> {
self.uri.try_conv_with(path_map)
}
}

pub fn to_location(
file_id: FileId,
range: TextRange,
path_map: &PathMap,
line_index: &LineIndex,
) -> Result<Location> {
let url = file_id.try_conv_with(path_map)?;
let loc = Location::new(
Url::from_file_path(self.0)
.map_err(|()| format_err!("can't convert path to url: {}", self.0.display()))?,
self.1.conv_with(line_index),
url,
range.conv_with(line_index),
);
Ok(loc)
}
}


pub trait MapConvWith<'a>: Sized {
type Ctx;
type Output;
Expand Down
6 changes: 4 additions & 2 deletions crates/server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,25 @@ extern crate walkdir;
extern crate libeditor;
extern crate libanalysis;
extern crate libsyntax2;
extern crate im;

mod io;
mod caps;
mod req;
mod dispatch;
mod util;
mod conv;
mod main_loop;
mod vfs;
mod path_map;

use threadpool::ThreadPool;
use crossbeam_channel::bounded;
use flexi_logger::{Logger, Duplicate};
use libanalysis::WorldState;

use ::{
io::{Io, RawMsg, RawResponse, RawRequest, RawNotification}
io::{Io, RawMsg, RawResponse, RawRequest, RawNotification},
path_map::PathMap,
};

pub type Result<T> = ::std::result::Result<T, ::failure::Error>;
Expand Down
91 changes: 56 additions & 35 deletions crates/server/src/main_loop/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,29 @@ use libsyntax2::TextUnit;
use serde_json::{to_value, from_value};

use ::{
PathMap,
req::{self, Decoration}, Result,
util::FilePath,
conv::{Conv, ConvWith, TryConvWith, MapConvWith},
conv::{Conv, ConvWith, TryConvWith, MapConvWith, to_location},
};

pub fn handle_syntax_tree(
world: World,
path_map: PathMap,
params: req::SyntaxTreeParams,
) -> Result<String> {
let path = params.text_document.file_path()?;
let file = world.file_syntax(&path)?;
let id = params.text_document.try_conv_with(&path_map)?;
let file = world.file_syntax(id)?;
Ok(libeditor::syntax_tree(&file))
}

pub fn handle_extend_selection(
world: World,
path_map: PathMap,
params: req::ExtendSelectionParams,
) -> Result<req::ExtendSelectionResult> {
let path = params.text_document.file_path()?;
let file = world.file_syntax(&path)?;
let line_index = world.file_line_index(&path)?;
let file_id = params.text_document.try_conv_with(&path_map)?;
let file = world.file_syntax(file_id)?;
let line_index = world.file_line_index(file_id)?;
let selections = params.selections.into_iter()
.map_conv_with(&line_index)
.map(|r| libeditor::extend_selection(&file, r).unwrap_or(r))
Expand All @@ -42,11 +44,12 @@ pub fn handle_extend_selection(

pub fn handle_document_symbol(
world: World,
path_map: PathMap,
params: req::DocumentSymbolParams,
) -> Result<Option<req::DocumentSymbolResponse>> {
let path = params.text_document.file_path()?;
let file = world.file_syntax(&path)?;
let line_index = world.file_line_index(&path)?;
let file_id = params.text_document.try_conv_with(&path_map)?;
let file = world.file_syntax(file_id)?;
let line_index = world.file_line_index(file_id)?;

let mut parents: Vec<(DocumentSymbol, Option<usize>)> = Vec::new();

Expand Down Expand Up @@ -81,11 +84,12 @@ pub fn handle_document_symbol(

pub fn handle_code_action(
world: World,
path_map: PathMap,
params: req::CodeActionParams,
) -> Result<Option<Vec<Command>>> {
let path = params.text_document.file_path()?;
let file = world.file_syntax(&path)?;
let line_index = world.file_line_index(&path)?;
let file_id = params.text_document.try_conv_with(&path_map)?;
let file = world.file_syntax(file_id)?;
let line_index = world.file_line_index(file_id)?;
let offset = params.range.conv_with(&line_index).start();
let mut ret = Vec::new();

Expand All @@ -105,6 +109,7 @@ pub fn handle_code_action(

pub fn handle_workspace_symbol(
world: World,
path_map: PathMap,
params: req::WorkspaceSymbolParams,
) -> Result<Option<Vec<SymbolInformation>>> {
let all_symbols = params.query.contains("#");
Expand All @@ -119,23 +124,26 @@ pub fn handle_workspace_symbol(
q.limit(128);
q
};
let mut res = exec_query(&world, query)?;
let mut res = exec_query(&world, &path_map, query)?;
if res.is_empty() && !all_symbols {
let mut query = Query::new(params.query);
query.limit(128);
res = exec_query(&world, query)?;
res = exec_query(&world, &path_map, query)?;
}

return Ok(Some(res));

fn exec_query(world: &World, query: Query) -> Result<Vec<SymbolInformation>> {
fn exec_query(world: &World, path_map: &PathMap, query: Query) -> Result<Vec<SymbolInformation>> {
let mut res = Vec::new();
for (path, symbol) in world.world_symbols(query) {
let line_index = world.file_line_index(path)?;
for (file_id, symbol) in world.world_symbols(query) {
let line_index = world.file_line_index(file_id)?;
let info = SymbolInformation {
name: symbol.name.to_string(),
kind: symbol.kind.conv(),
location: (path, symbol.node_range).try_conv_with(&line_index)?,
location: to_location(
file_id, symbol.node_range,
path_map, &line_index
)?,
container_name: None,
};
res.push(info);
Expand All @@ -146,22 +154,27 @@ pub fn handle_workspace_symbol(

pub fn handle_goto_definition(
world: World,
path_map: PathMap,
params: req::TextDocumentPositionParams,
) -> Result<Option<req::GotoDefinitionResponse>> {
let path = params.text_document.file_path()?;
let line_index = world.file_line_index(&path)?;
let file_id = params.text_document.try_conv_with(&path_map)?;
let line_index = world.file_line_index(file_id)?;
let offset = params.position.conv_with(&line_index);
let mut res = Vec::new();
for (path, symbol) in world.approximately_resolve_symbol(&path, offset)? {
let line_index = world.file_line_index(path)?;
let location = (path, symbol.node_range).try_conv_with(&line_index)?;
for (file_id, symbol) in world.approximately_resolve_symbol(file_id, offset)? {
let line_index = world.file_line_index(file_id)?;
let location = to_location(
file_id, symbol.node_range,
&path_map, &line_index,
)?;
res.push(location)
}
Ok(Some(req::GotoDefinitionResponse::Array(res)))
}

pub fn handle_execute_command(
world: World,
path_map: PathMap,
mut params: req::ExecuteCommandParams,
) -> Result<req::ApplyWorkspaceEditParams> {
if params.command.as_str() != "apply_code_action" {
Expand All @@ -172,8 +185,8 @@ pub fn handle_execute_command(
}
let arg = params.arguments.pop().unwrap();
let arg: ActionRequest = from_value(arg)?;
let path = arg.text_document.file_path()?;
let file = world.file_syntax(&path)?;
let file_id = arg.text_document.try_conv_with(&path_map)?;
let file = world.file_syntax(file_id)?;
let edit = match arg.id {
ActionId::FlipComma => libeditor::flip_comma(&file, arg.offset).map(|edit| edit()),
ActionId::AddDerive => libeditor::add_derive(&file, arg.offset).map(|edit| edit()),
Expand All @@ -182,7 +195,7 @@ pub fn handle_execute_command(
Some(edit) => edit,
None => bail!("command not applicable"),
};
let line_index = world.file_line_index(&path)?;
let line_index = world.file_line_index(file_id)?;
let mut changes = HashMap::new();
changes.insert(
arg.text_document.uri,
Expand Down Expand Up @@ -231,10 +244,14 @@ impl ActionId {
}
}

pub fn publish_diagnostics(world: World, uri: Url) -> Result<req::PublishDiagnosticsParams> {
let path = uri.file_path()?;
let file = world.file_syntax(&path)?;
let line_index = world.file_line_index(&path)?;
pub fn publish_diagnostics(
world: World,
path_map: PathMap,
uri: Url
) -> Result<req::PublishDiagnosticsParams> {
let file_id = uri.try_conv_with(&path_map)?;
let file = world.file_syntax(file_id)?;
let line_index = world.file_line_index(file_id)?;
let diagnostics = libeditor::diagnostics(&file)
.into_iter()
.map(|d| Diagnostic {
Expand All @@ -248,10 +265,14 @@ pub fn publish_diagnostics(world: World, uri: Url) -> Result<req::PublishDiagnos
Ok(req::PublishDiagnosticsParams { uri, diagnostics })
}

pub fn publish_decorations(world: World, uri: Url) -> Result<req::PublishDecorationsParams> {
let path = uri.file_path()?;
let file = world.file_syntax(&path)?;
let line_index = world.file_line_index(&path)?;
pub fn publish_decorations(
world: World,
path_map: PathMap,
uri: Url
) -> Result<req::PublishDecorationsParams> {
let file_id = uri.try_conv_with(&path_map)?;
let file = world.file_syntax(file_id)?;
let line_index = world.file_line_index(file_id)?;
let decorations = libeditor::highlight(&file)
.into_iter()
.map(|h| Decoration {
Expand Down
Loading

0 comments on commit 9f6cf42

Please sign in to comment.