Skip to content

Commit 9f6cf42

Browse files
committed
Switch to file ids
1 parent 1096583 commit 9f6cf42

File tree

8 files changed

+213
-125
lines changed

8 files changed

+213
-125
lines changed

crates/libanalysis/src/lib.rs

Lines changed: 1 addition & 9 deletions
Original file line numberOriginal file lineDiff line numberDiff line change
@@ -37,7 +37,6 @@ pub type Result<T> = ::std::result::Result<T, ::failure::Error>;
37
const INDEXING_THRESHOLD: usize = 128;
37
const INDEXING_THRESHOLD: usize = 128;
38

38

39
pub struct WorldState {
39
pub struct WorldState {
40-
next_file_id: u32,
41
data: Arc<WorldData>
40
data: Arc<WorldData>
42
}
41
}
43

42

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

47

49
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
48
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
50-
pub struct FileId(u32);
49+
pub struct FileId(pub u32);
51

50

52
impl WorldState {
51
impl WorldState {
53
pub fn new() -> WorldState {
52
pub fn new() -> WorldState {
54
WorldState {
53
WorldState {
55-
next_file_id: 0,
56
data: Arc::new(WorldData::default())
54
data: Arc::new(WorldData::default())
57
}
55
}
58
}
56
}
@@ -61,12 +59,6 @@ impl WorldState {
61
World { data: self.data.clone() }
59
World { data: self.data.clone() }
62
}
60
}
63

61

64-
pub fn new_file_id(&mut self) -> FileId {
65-
let id = FileId(self.next_file_id);
66-
self.next_file_id += 1;
67-
id
68-
}
69-
70
pub fn change_file(&mut self, file_id: FileId, text: Option<String>) {
62
pub fn change_file(&mut self, file_id: FileId, text: Option<String>) {
71
self.change_files(::std::iter::once((file_id, text)));
63
self.change_files(::std::iter::once((file_id, text)));
72
}
64
}

crates/server/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberOriginal file lineDiff line numberDiff line change
@@ -16,6 +16,7 @@ log = "0.4.3"
16
url_serde = "0.2.0"
16
url_serde = "0.2.0"
17
languageserver-types = "0.49.0"
17
languageserver-types = "0.49.0"
18
walkdir = "2.2.0"
18
walkdir = "2.2.0"
19+
im = { version = "11.0.1", features = ["arc"] }
19
text_unit = { version = "0.1.2", features = ["serde"] }
20
text_unit = { version = "0.1.2", features = ["serde"] }
20

21

21
libsyntax2 = { path = "../libsyntax2" }
22
libsyntax2 = { path = "../libsyntax2" }

crates/server/src/conv.rs

Lines changed: 59 additions & 13 deletions
Original file line numberOriginal file lineDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
use std::path::Path;
1+
use languageserver_types::{
2-
2+
Range, SymbolKind, Position, TextEdit, Location, Url,
3-
use languageserver_types::{Range, SymbolKind, Position, TextEdit, Location, Url};
3+
TextDocumentIdentifier, VersionedTextDocumentIdentifier, TextDocumentItem,
4+
};
4
use libeditor::{LineIndex, LineCol, Edit, AtomEdit};
5
use libeditor::{LineIndex, LineCol, Edit, AtomEdit};
5
use libsyntax2::{SyntaxKind, TextUnit, TextRange};
6
use libsyntax2::{SyntaxKind, TextUnit, TextRange};
7+
use libanalysis::FileId;
6

8

7-
use Result;
9+
use {Result, PathMap};
8

10

9
pub trait Conv {
11
pub trait Conv {
10
type Output;
12
type Output;
@@ -115,21 +117,65 @@ impl ConvWith for AtomEdit {
115
}
117
}
116
}
118
}
117

119

118-
impl<'a> TryConvWith for (&'a Path, TextRange) {
120+
impl<'a> TryConvWith for &'a Url {
119-
type Ctx = LineIndex;
121+
type Ctx = PathMap;
120-
type Output = Location;
122+
type Output = FileId;
123+
fn try_conv_with(self, path_map: &PathMap) -> Result<FileId> {
124+
let path = self.to_file_path()
125+
.map_err(|()| format_err!("invalid uri: {}", self))?;
126+
path_map.get_id(&path).ok_or_else(|| format_err!("unknown file: {}", path.display()))
127+
}
128+
}
129+
130+
impl TryConvWith for FileId {
131+
type Ctx = PathMap;
132+
type Output = Url;
133+
fn try_conv_with(self, path_map: &PathMap) -> Result<Url> {
134+
let path = path_map.get_path(self);
135+
let url = Url::from_file_path(path)
136+
.map_err(|()| format_err!("can't convert path to url: {}", path.display()))?;
137+
Ok(url)
138+
}
139+
}
140+
141+
impl<'a> TryConvWith for &'a TextDocumentItem {
142+
type Ctx = PathMap;
143+
type Output = FileId;
144+
fn try_conv_with(self, path_map: &PathMap) -> Result<FileId> {
145+
self.uri.try_conv_with(path_map)
146+
}
147+
}
121

148

122-
fn try_conv_with(self, line_index: &LineIndex) -> Result<Location> {
149+
impl<'a> TryConvWith for &'a VersionedTextDocumentIdentifier {
150+
type Ctx = PathMap;
151+
type Output = FileId;
152+
fn try_conv_with(self, path_map: &PathMap) -> Result<FileId> {
153+
self.uri.try_conv_with(path_map)
154+
}
155+
}
156+
157+
impl<'a> TryConvWith for &'a TextDocumentIdentifier {
158+
type Ctx = PathMap;
159+
type Output = FileId;
160+
fn try_conv_with(self, path_map: &PathMap) -> Result<FileId> {
161+
self.uri.try_conv_with(path_map)
162+
}
163+
}
164+
165+
pub fn to_location(
166+
file_id: FileId,
167+
range: TextRange,
168+
path_map: &PathMap,
169+
line_index: &LineIndex,
170+
) -> Result<Location> {
171+
let url = file_id.try_conv_with(path_map)?;
123
let loc = Location::new(
172
let loc = Location::new(
124-
Url::from_file_path(self.0)
173+
url,
125-
.map_err(|()| format_err!("can't convert path to url: {}", self.0.display()))?,
174+
range.conv_with(line_index),
126-
self.1.conv_with(line_index),
127
);
175
);
128
Ok(loc)
176
Ok(loc)
129-
}
130
}
177
}
131

178

132-
133
pub trait MapConvWith<'a>: Sized {
179
pub trait MapConvWith<'a>: Sized {
134
type Ctx;
180
type Ctx;
135
type Output;
181
type Output;

crates/server/src/main.rs

Lines changed: 4 additions & 2 deletions
Original file line numberOriginal file lineDiff line numberDiff line change
@@ -17,23 +17,25 @@ extern crate walkdir;
17
extern crate libeditor;
17
extern crate libeditor;
18
extern crate libanalysis;
18
extern crate libanalysis;
19
extern crate libsyntax2;
19
extern crate libsyntax2;
20+
extern crate im;
20

21

21
mod io;
22
mod io;
22
mod caps;
23
mod caps;
23
mod req;
24
mod req;
24
mod dispatch;
25
mod dispatch;
25-
mod util;
26
mod conv;
26
mod conv;
27
mod main_loop;
27
mod main_loop;
28
mod vfs;
28
mod vfs;
29+
mod path_map;
29

30

30
use threadpool::ThreadPool;
31
use threadpool::ThreadPool;
31
use crossbeam_channel::bounded;
32
use crossbeam_channel::bounded;
32
use flexi_logger::{Logger, Duplicate};
33
use flexi_logger::{Logger, Duplicate};
33
use libanalysis::WorldState;
34
use libanalysis::WorldState;
34

35

35
use ::{
36
use ::{
36-
io::{Io, RawMsg, RawResponse, RawRequest, RawNotification}
37+
io::{Io, RawMsg, RawResponse, RawRequest, RawNotification},
38+
path_map::PathMap,
37
};
39
};
38

40

39
pub type Result<T> = ::std::result::Result<T, ::failure::Error>;
41
pub type Result<T> = ::std::result::Result<T, ::failure::Error>;

crates/server/src/main_loop/handlers.rs

Lines changed: 56 additions & 35 deletions
Original file line numberOriginal file lineDiff line numberDiff line change
@@ -11,27 +11,29 @@ use libsyntax2::TextUnit;
11
use serde_json::{to_value, from_value};
11
use serde_json::{to_value, from_value};
12

12

13
use ::{
13
use ::{
14+
PathMap,
14
req::{self, Decoration}, Result,
15
req::{self, Decoration}, Result,
15-
util::FilePath,
16+
conv::{Conv, ConvWith, TryConvWith, MapConvWith, to_location},
16-
conv::{Conv, ConvWith, TryConvWith, MapConvWith},
17
};
17
};
18

18

19
pub fn handle_syntax_tree(
19
pub fn handle_syntax_tree(
20
world: World,
20
world: World,
21+
path_map: PathMap,
21
params: req::SyntaxTreeParams,
22
params: req::SyntaxTreeParams,
22
) -> Result<String> {
23
) -> Result<String> {
23-
let path = params.text_document.file_path()?;
24+
let id = params.text_document.try_conv_with(&path_map)?;
24-
let file = world.file_syntax(&path)?;
25+
let file = world.file_syntax(id)?;
25
Ok(libeditor::syntax_tree(&file))
26
Ok(libeditor::syntax_tree(&file))
26
}
27
}
27

28

28
pub fn handle_extend_selection(
29
pub fn handle_extend_selection(
29
world: World,
30
world: World,
31+
path_map: PathMap,
30
params: req::ExtendSelectionParams,
32
params: req::ExtendSelectionParams,
31
) -> Result<req::ExtendSelectionResult> {
33
) -> Result<req::ExtendSelectionResult> {
32-
let path = params.text_document.file_path()?;
34+
let file_id = params.text_document.try_conv_with(&path_map)?;
33-
let file = world.file_syntax(&path)?;
35+
let file = world.file_syntax(file_id)?;
34-
let line_index = world.file_line_index(&path)?;
36+
let line_index = world.file_line_index(file_id)?;
35
let selections = params.selections.into_iter()
37
let selections = params.selections.into_iter()
36
.map_conv_with(&line_index)
38
.map_conv_with(&line_index)
37
.map(|r| libeditor::extend_selection(&file, r).unwrap_or(r))
39
.map(|r| libeditor::extend_selection(&file, r).unwrap_or(r))
@@ -42,11 +44,12 @@ pub fn handle_extend_selection(
42

44

43
pub fn handle_document_symbol(
45
pub fn handle_document_symbol(
44
world: World,
46
world: World,
47+
path_map: PathMap,
45
params: req::DocumentSymbolParams,
48
params: req::DocumentSymbolParams,
46
) -> Result<Option<req::DocumentSymbolResponse>> {
49
) -> Result<Option<req::DocumentSymbolResponse>> {
47-
let path = params.text_document.file_path()?;
50+
let file_id = params.text_document.try_conv_with(&path_map)?;
48-
let file = world.file_syntax(&path)?;
51+
let file = world.file_syntax(file_id)?;
49-
let line_index = world.file_line_index(&path)?;
52+
let line_index = world.file_line_index(file_id)?;
50

53

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

55

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

84

82
pub fn handle_code_action(
85
pub fn handle_code_action(
83
world: World,
86
world: World,
87+
path_map: PathMap,
84
params: req::CodeActionParams,
88
params: req::CodeActionParams,
85
) -> Result<Option<Vec<Command>>> {
89
) -> Result<Option<Vec<Command>>> {
86-
let path = params.text_document.file_path()?;
90+
let file_id = params.text_document.try_conv_with(&path_map)?;
87-
let file = world.file_syntax(&path)?;
91+
let file = world.file_syntax(file_id)?;
88-
let line_index = world.file_line_index(&path)?;
92+
let line_index = world.file_line_index(file_id)?;
89
let offset = params.range.conv_with(&line_index).start();
93
let offset = params.range.conv_with(&line_index).start();
90
let mut ret = Vec::new();
94
let mut ret = Vec::new();
91

95

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

109

106
pub fn handle_workspace_symbol(
110
pub fn handle_workspace_symbol(
107
world: World,
111
world: World,
112+
path_map: PathMap,
108
params: req::WorkspaceSymbolParams,
113
params: req::WorkspaceSymbolParams,
109
) -> Result<Option<Vec<SymbolInformation>>> {
114
) -> Result<Option<Vec<SymbolInformation>>> {
110
let all_symbols = params.query.contains("#");
115
let all_symbols = params.query.contains("#");
@@ -119,23 +124,26 @@ pub fn handle_workspace_symbol(
119
q.limit(128);
124
q.limit(128);
120
q
125
q
121
};
126
};
122-
let mut res = exec_query(&world, query)?;
127+
let mut res = exec_query(&world, &path_map, query)?;
123
if res.is_empty() && !all_symbols {
128
if res.is_empty() && !all_symbols {
124
let mut query = Query::new(params.query);
129
let mut query = Query::new(params.query);
125
query.limit(128);
130
query.limit(128);
126-
res = exec_query(&world, query)?;
131+
res = exec_query(&world, &path_map, query)?;
127
}
132
}
128

133

129
return Ok(Some(res));
134
return Ok(Some(res));
130

135

131-
fn exec_query(world: &World, query: Query) -> Result<Vec<SymbolInformation>> {
136+
fn exec_query(world: &World, path_map: &PathMap, query: Query) -> Result<Vec<SymbolInformation>> {
132
let mut res = Vec::new();
137
let mut res = Vec::new();
133-
for (path, symbol) in world.world_symbols(query) {
138+
for (file_id, symbol) in world.world_symbols(query) {
134-
let line_index = world.file_line_index(path)?;
139+
let line_index = world.file_line_index(file_id)?;
135
let info = SymbolInformation {
140
let info = SymbolInformation {
136
name: symbol.name.to_string(),
141
name: symbol.name.to_string(),
137
kind: symbol.kind.conv(),
142
kind: symbol.kind.conv(),
138-
location: (path, symbol.node_range).try_conv_with(&line_index)?,
143+
location: to_location(
144+
file_id, symbol.node_range,
145+
path_map, &line_index
146+
)?,
139
container_name: None,
147
container_name: None,
140
};
148
};
141
res.push(info);
149
res.push(info);
@@ -146,22 +154,27 @@ pub fn handle_workspace_symbol(
146

154

147
pub fn handle_goto_definition(
155
pub fn handle_goto_definition(
148
world: World,
156
world: World,
157+
path_map: PathMap,
149
params: req::TextDocumentPositionParams,
158
params: req::TextDocumentPositionParams,
150
) -> Result<Option<req::GotoDefinitionResponse>> {
159
) -> Result<Option<req::GotoDefinitionResponse>> {
151-
let path = params.text_document.file_path()?;
160+
let file_id = params.text_document.try_conv_with(&path_map)?;
152-
let line_index = world.file_line_index(&path)?;
161+
let line_index = world.file_line_index(file_id)?;
153
let offset = params.position.conv_with(&line_index);
162
let offset = params.position.conv_with(&line_index);
154
let mut res = Vec::new();
163
let mut res = Vec::new();
155-
for (path, symbol) in world.approximately_resolve_symbol(&path, offset)? {
164+
for (file_id, symbol) in world.approximately_resolve_symbol(file_id, offset)? {
156-
let line_index = world.file_line_index(path)?;
165+
let line_index = world.file_line_index(file_id)?;
157-
let location = (path, symbol.node_range).try_conv_with(&line_index)?;
166+
let location = to_location(
167+
file_id, symbol.node_range,
168+
&path_map, &line_index,
169+
)?;
158
res.push(location)
170
res.push(location)
159
}
171
}
160
Ok(Some(req::GotoDefinitionResponse::Array(res)))
172
Ok(Some(req::GotoDefinitionResponse::Array(res)))
161
}
173
}
162

174

163
pub fn handle_execute_command(
175
pub fn handle_execute_command(
164
world: World,
176
world: World,
177+
path_map: PathMap,
165
mut params: req::ExecuteCommandParams,
178
mut params: req::ExecuteCommandParams,
166
) -> Result<req::ApplyWorkspaceEditParams> {
179
) -> Result<req::ApplyWorkspaceEditParams> {
167
if params.command.as_str() != "apply_code_action" {
180
if params.command.as_str() != "apply_code_action" {
@@ -172,8 +185,8 @@ pub fn handle_execute_command(
172
}
185
}
173
let arg = params.arguments.pop().unwrap();
186
let arg = params.arguments.pop().unwrap();
174
let arg: ActionRequest = from_value(arg)?;
187
let arg: ActionRequest = from_value(arg)?;
175-
let path = arg.text_document.file_path()?;
188+
let file_id = arg.text_document.try_conv_with(&path_map)?;
176-
let file = world.file_syntax(&path)?;
189+
let file = world.file_syntax(file_id)?;
177
let edit = match arg.id {
190
let edit = match arg.id {
178
ActionId::FlipComma => libeditor::flip_comma(&file, arg.offset).map(|edit| edit()),
191
ActionId::FlipComma => libeditor::flip_comma(&file, arg.offset).map(|edit| edit()),
179
ActionId::AddDerive => libeditor::add_derive(&file, arg.offset).map(|edit| edit()),
192
ActionId::AddDerive => libeditor::add_derive(&file, arg.offset).map(|edit| edit()),
@@ -182,7 +195,7 @@ pub fn handle_execute_command(
182
Some(edit) => edit,
195
Some(edit) => edit,
183
None => bail!("command not applicable"),
196
None => bail!("command not applicable"),
184
};
197
};
185-
let line_index = world.file_line_index(&path)?;
198+
let line_index = world.file_line_index(file_id)?;
186
let mut changes = HashMap::new();
199
let mut changes = HashMap::new();
187
changes.insert(
200
changes.insert(
188
arg.text_document.uri,
201
arg.text_document.uri,
@@ -231,10 +244,14 @@ impl ActionId {
231
}
244
}
232
}
245
}
233

246

234-
pub fn publish_diagnostics(world: World, uri: Url) -> Result<req::PublishDiagnosticsParams> {
247+
pub fn publish_diagnostics(
235-
let path = uri.file_path()?;
248+
world: World,
236-
let file = world.file_syntax(&path)?;
249+
path_map: PathMap,
237-
let line_index = world.file_line_index(&path)?;
250+
uri: Url
251+
) -> Result<req::PublishDiagnosticsParams> {
252+
let file_id = uri.try_conv_with(&path_map)?;
253+
let file = world.file_syntax(file_id)?;
254+
let line_index = world.file_line_index(file_id)?;
238
let diagnostics = libeditor::diagnostics(&file)
255
let diagnostics = libeditor::diagnostics(&file)
239
.into_iter()
256
.into_iter()
240
.map(|d| Diagnostic {
257
.map(|d| Diagnostic {
@@ -248,10 +265,14 @@ pub fn publish_diagnostics(world: World, uri: Url) -> Result<req::PublishDiagnos
248
Ok(req::PublishDiagnosticsParams { uri, diagnostics })
265
Ok(req::PublishDiagnosticsParams { uri, diagnostics })
249
}
266
}
250

267

251-
pub fn publish_decorations(world: World, uri: Url) -> Result<req::PublishDecorationsParams> {
268+
pub fn publish_decorations(
252-
let path = uri.file_path()?;
269+
world: World,
253-
let file = world.file_syntax(&path)?;
270+
path_map: PathMap,
254-
let line_index = world.file_line_index(&path)?;
271+
uri: Url
272+
) -> Result<req::PublishDecorationsParams> {
273+
let file_id = uri.try_conv_with(&path_map)?;
274+
let file = world.file_syntax(file_id)?;
275+
let line_index = world.file_line_index(file_id)?;
255
let decorations = libeditor::highlight(&file)
276
let decorations = libeditor::highlight(&file)
256
.into_iter()
277
.into_iter()
257
.map(|h| Decoration {
278
.map(|h| Decoration {

0 commit comments

Comments
 (0)