diff options
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | cli/src/main.rs | 14 | ||||
-rw-r--r-- | codeless/server/.gitignore | 1 | ||||
-rw-r--r-- | codeless/server/Cargo.toml | 4 | ||||
-rw-r--r-- | codeless/server/src/dispatch.rs | 4 | ||||
-rw-r--r-- | codeless/server/src/io.rs | 55 | ||||
-rw-r--r-- | codeless/server/src/main.rs | 126 | ||||
-rw-r--r-- | codeless/server/target/.rustc_info.json | 1 | ||||
-rw-r--r-- | codeless/server/target/debug/.cargo-lock | 0 | ||||
-rw-r--r-- | codeless/server/target/debug/libm.d | 1 | ||||
-rw-r--r-- | codeless/server/target/debug/libm.rmeta | 0 | ||||
-rw-r--r-- | codeless/src/extension.ts | 6 | ||||
-rw-r--r-- | libeditor/src/lib.rs | 3 | ||||
-rw-r--r-- | libeditor/tests/test.rs | 14 | ||||
-rw-r--r-- | src/yellow/green.rs | 6 | ||||
-rw-r--r-- | src/yellow/mod.rs | 53 | ||||
-rw-r--r-- | src/yellow/red.rs | 18 | ||||
-rw-r--r-- | src/yellow/syntax.rs | 40 |
18 files changed, 233 insertions, 115 deletions
diff --git a/Cargo.toml b/Cargo.toml index 77f9c4a8d..55dd9165c 100644 --- a/Cargo.toml +++ b/Cargo.toml | |||
@@ -5,7 +5,7 @@ authors = ["Aleksey Kladov <[email protected]>"] | |||
5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
6 | 6 | ||
7 | [workspace] | 7 | [workspace] |
8 | members = [ "tools", "cli", "libeditor", "libanalysis" ] | 8 | members = [ "tools", "cli", "libeditor", "libanalysis", "codeless/server" ] |
9 | 9 | ||
10 | [dependencies] | 10 | [dependencies] |
11 | unicode-xid = "0.1.0" | 11 | unicode-xid = "0.1.0" |
diff --git a/cli/src/main.rs b/cli/src/main.rs index f6c66743f..45e0a1e4f 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs | |||
@@ -10,7 +10,7 @@ use std::{ | |||
10 | }; | 10 | }; |
11 | use clap::{App, Arg, SubCommand}; | 11 | use clap::{App, Arg, SubCommand}; |
12 | use tools::collect_tests; | 12 | use tools::collect_tests; |
13 | use libeditor::File; | 13 | use libeditor::{ast, syntax_tree, symbols}; |
14 | 14 | ||
15 | type Result<T> = ::std::result::Result<T, failure::Error>; | 15 | type Result<T> = ::std::result::Result<T, failure::Error>; |
16 | 16 | ||
@@ -44,14 +44,14 @@ fn main() -> Result<()> { | |||
44 | let file = file()?; | 44 | let file = file()?; |
45 | let elapsed = start.elapsed(); | 45 | let elapsed = start.elapsed(); |
46 | if !matches.is_present("no-dump") { | 46 | if !matches.is_present("no-dump") { |
47 | println!("{}", file.syntax_tree()); | 47 | println!("{}", syntax_tree(&file)); |
48 | } | 48 | } |
49 | eprintln!("parsing: {:?}", elapsed); | 49 | eprintln!("parsing: {:?}", elapsed); |
50 | ::std::mem::forget(file); | 50 | ::std::mem::forget(file); |
51 | } | 51 | } |
52 | ("symbols", _) => { | 52 | ("symbols", _) => { |
53 | let file = file()?; | 53 | let file = file()?; |
54 | for s in file.symbols() { | 54 | for s in symbols(&file) { |
55 | println!("{:?}", s); | 55 | println!("{:?}", s); |
56 | } | 56 | } |
57 | } | 57 | } |
@@ -68,9 +68,9 @@ fn main() -> Result<()> { | |||
68 | Ok(()) | 68 | Ok(()) |
69 | } | 69 | } |
70 | 70 | ||
71 | fn file() -> Result<File> { | 71 | fn file() -> Result<ast::File> { |
72 | let text = read_stdin()?; | 72 | let text = read_stdin()?; |
73 | Ok(File::new(&text)) | 73 | Ok(ast::File::parse(&text)) |
74 | } | 74 | } |
75 | 75 | ||
76 | fn read_stdin() -> Result<String> { | 76 | fn read_stdin() -> Result<String> { |
@@ -89,7 +89,7 @@ fn render_test(file: &Path, line: usize) -> Result<(String, String)> { | |||
89 | None => bail!("No test found at line {} at {}", line, file.display()), | 89 | None => bail!("No test found at line {} at {}", line, file.display()), |
90 | Some((_start_line, test)) => test, | 90 | Some((_start_line, test)) => test, |
91 | }; | 91 | }; |
92 | let file = File::new(&test.text); | 92 | let file = ast::File::parse(&test.text); |
93 | let tree = file.syntax_tree(); | 93 | let tree = syntax_tree(&file); |
94 | Ok((test.text, tree)) | 94 | Ok((test.text, tree)) |
95 | } | 95 | } |
diff --git a/codeless/server/.gitignore b/codeless/server/.gitignore deleted file mode 100644 index 5a50b7f98..000000000 --- a/codeless/server/.gitignore +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | /target/* | ||
diff --git a/codeless/server/Cargo.toml b/codeless/server/Cargo.toml index 4c3dd345c..f5c32b878 100644 --- a/codeless/server/Cargo.toml +++ b/codeless/server/Cargo.toml | |||
@@ -2,7 +2,6 @@ | |||
2 | name = "m" | 2 | name = "m" |
3 | version = "0.1.0" | 3 | version = "0.1.0" |
4 | authors = ["Aleksey Kladov <[email protected]>"] | 4 | authors = ["Aleksey Kladov <[email protected]>"] |
5 | [workspace] | ||
6 | 5 | ||
7 | [dependencies] | 6 | [dependencies] |
8 | failure = "0.1.2" | 7 | failure = "0.1.2" |
@@ -12,5 +11,8 @@ serde = "1.0.71" | |||
12 | serde_derive = "1.0.71" | 11 | serde_derive = "1.0.71" |
13 | drop_bomb = "0.1.0" | 12 | drop_bomb = "0.1.0" |
14 | crossbeam-channel = "0.2.4" | 13 | crossbeam-channel = "0.2.4" |
14 | threadpool = "1.7.1" | ||
15 | flexi_logger = "0.9.0" | ||
16 | log = "0.4.3" | ||
15 | libeditor = { path = "../../libeditor" } | 17 | libeditor = { path = "../../libeditor" } |
16 | libanalysis = { path = "../../libanalysis" } | 18 | libanalysis = { path = "../../libanalysis" } |
diff --git a/codeless/server/src/dispatch.rs b/codeless/server/src/dispatch.rs index a9476acde..ee87fa6c3 100644 --- a/codeless/server/src/dispatch.rs +++ b/codeless/server/src/dispatch.rs | |||
@@ -24,8 +24,8 @@ impl<R: Request> Responder<R> | |||
24 | R::Params: DeserializeOwned, | 24 | R::Params: DeserializeOwned, |
25 | R::Result: Serialize, | 25 | R::Result: Serialize, |
26 | { | 26 | { |
27 | pub fn respond_with(self, io: &mut Io, f: impl FnOnce() -> Result<R::Result>) -> Result<()> { | 27 | pub fn response(self, io: &mut Io, resp: Result<R::Result>) -> Result<()> { |
28 | match f() { | 28 | match resp { |
29 | Ok(res) => self.result(io, res)?, | 29 | Ok(res) => self.result(io, res)?, |
30 | Err(e) => { | 30 | Err(e) => { |
31 | self.error(io)?; | 31 | self.error(io)?; |
diff --git a/codeless/server/src/io.rs b/codeless/server/src/io.rs index b84103d65..5eafc6942 100644 --- a/codeless/server/src/io.rs +++ b/codeless/server/src/io.rs | |||
@@ -49,16 +49,21 @@ impl MsgReceiver { | |||
49 | match self.chan.recv() { | 49 | match self.chan.recv() { |
50 | Some(msg) => Ok(msg), | 50 | Some(msg) => Ok(msg), |
51 | None => { | 51 | None => { |
52 | self.thread | 52 | self.cleanup()?; |
53 | .take() | 53 | unreachable!() |
54 | .ok_or_else(|| format_err!("MsgReceiver thread panicked"))? | ||
55 | .join() | ||
56 | .map_err(|_| format_err!("MsgReceiver thread panicked"))??; | ||
57 | bail!("client disconnected") | ||
58 | } | 54 | } |
59 | } | 55 | } |
60 | } | 56 | } |
61 | 57 | ||
58 | fn cleanup(&mut self) -> Result<()> { | ||
59 | self.thread | ||
60 | .take() | ||
61 | .ok_or_else(|| format_err!("MsgReceiver thread panicked"))? | ||
62 | .join() | ||
63 | .map_err(|_| format_err!("MsgReceiver thread panicked"))??; | ||
64 | bail!("client disconnected") | ||
65 | } | ||
66 | |||
62 | fn stop(self) -> Result<()> { | 67 | fn stop(self) -> Result<()> { |
63 | // Can't really self.thread.join() here, b/c it might be | 68 | // Can't really self.thread.join() here, b/c it might be |
64 | // blocking on read | 69 | // blocking on read |
@@ -68,7 +73,7 @@ impl MsgReceiver { | |||
68 | 73 | ||
69 | struct MsgSender { | 74 | struct MsgSender { |
70 | chan: Sender<RawMsg>, | 75 | chan: Sender<RawMsg>, |
71 | thread: Option<thread::JoinHandle<Result<()>>>, | 76 | thread: thread::JoinHandle<Result<()>>, |
72 | } | 77 | } |
73 | 78 | ||
74 | impl MsgSender { | 79 | impl MsgSender { |
@@ -76,28 +81,14 @@ impl MsgSender { | |||
76 | self.chan.send(msg) | 81 | self.chan.send(msg) |
77 | } | 82 | } |
78 | 83 | ||
79 | fn stop(mut self) -> Result<()> { | 84 | fn stop(self) -> Result<()> { |
80 | if let Some(thread) = self.thread.take() { | 85 | drop(self.chan); |
81 | thread.join() | 86 | self.thread.join() |
82 | .map_err(|_| format_err!("MsgSender thread panicked"))?? | 87 | .map_err(|_| format_err!("MsgSender thread panicked"))??; |
83 | } | ||
84 | Ok(()) | 88 | Ok(()) |
85 | } | 89 | } |
86 | } | 90 | } |
87 | 91 | ||
88 | impl Drop for MsgSender { | ||
89 | fn drop(&mut self) { | ||
90 | if let Some(thread) = self.thread.take() { | ||
91 | let res = thread.join(); | ||
92 | if thread::panicking() { | ||
93 | drop(res) | ||
94 | } else { | ||
95 | res.unwrap().unwrap() | ||
96 | } | ||
97 | } | ||
98 | } | ||
99 | } | ||
100 | |||
101 | pub struct Io { | 92 | pub struct Io { |
102 | receiver: MsgReceiver, | 93 | receiver: MsgReceiver, |
103 | sender: MsgSender, | 94 | sender: MsgSender, |
@@ -109,7 +100,7 @@ impl Io { | |||
109 | let (tx, rx) = bounded(16); | 100 | let (tx, rx) = bounded(16); |
110 | MsgSender { | 101 | MsgSender { |
111 | chan: tx, | 102 | chan: tx, |
112 | thread: Some(thread::spawn(move || { | 103 | thread: thread::spawn(move || { |
113 | let stdout = stdout(); | 104 | let stdout = stdout(); |
114 | let mut stdout = stdout.lock(); | 105 | let mut stdout = stdout.lock(); |
115 | for msg in rx { | 106 | for msg in rx { |
@@ -126,7 +117,7 @@ impl Io { | |||
126 | write_msg_text(&mut stdout, &text)?; | 117 | write_msg_text(&mut stdout, &text)?; |
127 | } | 118 | } |
128 | Ok(()) | 119 | Ok(()) |
129 | })), | 120 | }), |
130 | } | 121 | } |
131 | }; | 122 | }; |
132 | let receiver = { | 123 | let receiver = { |
@@ -155,6 +146,14 @@ impl Io { | |||
155 | self.receiver.recv() | 146 | self.receiver.recv() |
156 | } | 147 | } |
157 | 148 | ||
149 | pub fn receiver(&mut self) -> &mut Receiver<RawMsg> { | ||
150 | &mut self.receiver.chan | ||
151 | } | ||
152 | |||
153 | pub fn cleanup_receiver(&mut self) -> Result<()> { | ||
154 | self.receiver.cleanup() | ||
155 | } | ||
156 | |||
158 | pub fn stop(self) -> Result<()> { | 157 | pub fn stop(self) -> Result<()> { |
159 | self.receiver.stop()?; | 158 | self.receiver.stop()?; |
160 | self.sender.stop()?; | 159 | self.sender.stop()?; |
@@ -190,10 +189,12 @@ fn read_msg_text(inp: &mut impl BufRead) -> Result<Option<String>> { | |||
190 | buf.resize(size, 0); | 189 | buf.resize(size, 0); |
191 | inp.read_exact(&mut buf)?; | 190 | inp.read_exact(&mut buf)?; |
192 | let buf = String::from_utf8(buf)?; | 191 | let buf = String::from_utf8(buf)?; |
192 | debug!("< {}", buf); | ||
193 | Ok(Some(buf)) | 193 | Ok(Some(buf)) |
194 | } | 194 | } |
195 | 195 | ||
196 | fn write_msg_text(out: &mut impl Write, msg: &str) -> Result<()> { | 196 | fn write_msg_text(out: &mut impl Write, msg: &str) -> Result<()> { |
197 | debug!("> {}", msg); | ||
197 | write!(out, "Content-Length: {}\r\n\r\n", msg.len())?; | 198 | write!(out, "Content-Length: {}\r\n\r\n", msg.len())?; |
198 | out.write_all(msg.as_bytes())?; | 199 | out.write_all(msg.as_bytes())?; |
199 | out.flush()?; | 200 | out.flush()?; |
diff --git a/codeless/server/src/main.rs b/codeless/server/src/main.rs index 11b6b7067..92f6a400c 100644 --- a/codeless/server/src/main.rs +++ b/codeless/server/src/main.rs | |||
@@ -6,7 +6,12 @@ extern crate serde; | |||
6 | extern crate serde_json; | 6 | extern crate serde_json; |
7 | extern crate languageserver_types; | 7 | extern crate languageserver_types; |
8 | extern crate drop_bomb; | 8 | extern crate drop_bomb; |
9 | #[macro_use] | ||
9 | extern crate crossbeam_channel; | 10 | extern crate crossbeam_channel; |
11 | extern crate threadpool; | ||
12 | #[macro_use] | ||
13 | extern crate log; | ||
14 | extern crate flexi_logger; | ||
10 | extern crate libeditor; | 15 | extern crate libeditor; |
11 | extern crate libanalysis; | 16 | extern crate libanalysis; |
12 | 17 | ||
@@ -16,16 +21,50 @@ mod req; | |||
16 | mod dispatch; | 21 | mod dispatch; |
17 | 22 | ||
18 | use languageserver_types::InitializeResult; | 23 | use languageserver_types::InitializeResult; |
24 | use threadpool::ThreadPool; | ||
25 | use crossbeam_channel::{bounded, Sender, Receiver}; | ||
26 | use flexi_logger::Logger; | ||
19 | use libanalysis::WorldState; | 27 | use libanalysis::WorldState; |
20 | use self::io::{Io, RawMsg}; | 28 | |
29 | use ::{ | ||
30 | io::{Io, RawMsg}, | ||
31 | }; | ||
21 | 32 | ||
22 | pub type Result<T> = ::std::result::Result<T, ::failure::Error>; | 33 | pub type Result<T> = ::std::result::Result<T, ::failure::Error>; |
23 | 34 | ||
24 | fn main() -> Result<()> { | 35 | fn main() -> Result<()> { |
36 | Logger::with_env_or_str("m=trace") | ||
37 | .log_to_file() | ||
38 | .directory("log") | ||
39 | .start()?; | ||
40 | info!("starting server"); | ||
41 | match ::std::panic::catch_unwind(|| main_inner()) { | ||
42 | Ok(res) => { | ||
43 | info!("shutting down: {:?}", res); | ||
44 | res | ||
45 | } | ||
46 | Err(_) => { | ||
47 | error!("server panicked"); | ||
48 | bail!("server panicked") | ||
49 | }, | ||
50 | } | ||
51 | } | ||
52 | |||
53 | fn main_inner() -> Result<()> { | ||
25 | let mut io = Io::from_stdio(); | 54 | let mut io = Io::from_stdio(); |
26 | initialize(&mut io)?; | 55 | let res = initialize(&mut io); |
27 | io.stop()?; | 56 | info!("shutting down IO..."); |
28 | Ok(()) | 57 | let io_res = io.stop(); |
58 | info!("... IO is down"); | ||
59 | match (res, io_res) { | ||
60 | (Ok(()), Ok(())) => Ok(()), | ||
61 | (res, Ok(())) => res, | ||
62 | (Ok(()), io_res) => io_res, | ||
63 | (res, Err(io_err)) => { | ||
64 | error!("shutdown error: {:?}", io_err); | ||
65 | res | ||
66 | } | ||
67 | } | ||
29 | } | 68 | } |
30 | 69 | ||
31 | fn initialize(io: &mut Io) -> Result<()> { | 70 | fn initialize(io: &mut Io) -> Result<()> { |
@@ -59,20 +98,69 @@ fn initialize(io: &mut Io) -> Result<()> { | |||
59 | } | 98 | } |
60 | } | 99 | } |
61 | 100 | ||
101 | type Thunk = Box<for<'a> FnBox<&'a mut Io, Result<()>>>; | ||
102 | |||
62 | fn initialized(io: &mut Io) -> Result<()> { | 103 | fn initialized(io: &mut Io) -> Result<()> { |
63 | eprintln!("initialized"); | 104 | let mut world = WorldState::new(); |
64 | let world = WorldState::new(); | 105 | let mut pool = ThreadPool::new(4); |
106 | let (sender, receiver) = bounded::<Thunk>(16); | ||
107 | let res = main_loop(io, &mut world, &mut pool, sender, receiver.clone()); | ||
108 | info!("waiting for background jobs to finish..."); | ||
109 | receiver.for_each(drop); | ||
110 | info!("...background jobs have finished"); | ||
111 | res | ||
112 | } | ||
113 | |||
114 | fn main_loop( | ||
115 | io: &mut Io, | ||
116 | world: &mut WorldState, | ||
117 | pool: &mut ThreadPool, | ||
118 | sender: Sender<Thunk>, | ||
119 | receiver: Receiver<Thunk>, | ||
120 | ) -> Result<()> { | ||
121 | info!("server initialized, serving requests"); | ||
65 | loop { | 122 | loop { |
66 | match io.recv()? { | 123 | enum Event { |
124 | Msg(RawMsg), | ||
125 | Thunk(Thunk), | ||
126 | ReceiverDead, | ||
127 | } | ||
128 | |||
129 | let event = select! { | ||
130 | recv(io.receiver(), msg) => match msg { | ||
131 | Some(msg) => Event::Msg(msg), | ||
132 | None => Event::ReceiverDead, | ||
133 | }, | ||
134 | recv(receiver, thunk) => Event::Thunk(thunk.unwrap()), | ||
135 | }; | ||
136 | |||
137 | let msg = match event { | ||
138 | Event::ReceiverDead => { | ||
139 | io.cleanup_receiver()?; | ||
140 | unreachable!(); | ||
141 | } | ||
142 | Event::Thunk(thunk) => { | ||
143 | thunk.call_box(io)?; | ||
144 | continue; | ||
145 | } | ||
146 | Event::Msg(msg) => msg, | ||
147 | }; | ||
148 | |||
149 | match msg { | ||
67 | RawMsg::Request(req) => { | 150 | RawMsg::Request(req) => { |
68 | let world = world.snapshot(); | ||
69 | if let Some((params, resp)) = dispatch::expect::<req::SyntaxTree>(io, req)? { | 151 | if let Some((params, resp)) = dispatch::expect::<req::SyntaxTree>(io, req)? { |
70 | resp.respond_with(io, || { | 152 | let world = world.snapshot(); |
71 | let path = params.text_document.uri.to_file_path() | 153 | let sender = sender.clone(); |
72 | .map_err(|()| format_err!("invalid path"))?; | 154 | pool.execute(move || { |
73 | let file = world.file_syntax(&path)?; | 155 | let res: Result<String> = (|| { |
74 | Ok(libeditor::syntax_tree(&file)) | 156 | let path = params.text_document.uri.to_file_path() |
75 | })? | 157 | .map_err(|()| format_err!("invalid path"))?; |
158 | let file = world.file_syntax(&path)?; | ||
159 | Ok(libeditor::syntax_tree(&file)) | ||
160 | })(); | ||
161 | |||
162 | sender.send(Box::new(|io: &mut Io| resp.response(io, res))) | ||
163 | }); | ||
76 | } | 164 | } |
77 | } | 165 | } |
78 | msg => { | 166 | msg => { |
@@ -82,3 +170,13 @@ fn initialized(io: &mut Io) -> Result<()> { | |||
82 | } | 170 | } |
83 | } | 171 | } |
84 | 172 | ||
173 | |||
174 | trait FnBox<A, R>: Send { | ||
175 | fn call_box(self: Box<Self>, a: A) -> R; | ||
176 | } | ||
177 | |||
178 | impl<A, R, F: FnOnce(A) -> R + Send> FnBox<A, R> for F { | ||
179 | fn call_box(self: Box<F>, a: A) -> R { | ||
180 | (*self)(a) | ||
181 | } | ||
182 | } | ||
diff --git a/codeless/server/target/.rustc_info.json b/codeless/server/target/.rustc_info.json deleted file mode 100644 index a37ac2011..000000000 --- a/codeless/server/target/.rustc_info.json +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | {"rustc_fingerprint":11898242945176772229,"outputs":{"15337506775154344876":["___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/matklad/.rustup/toolchains/stable-x86_64-unknown-linux-gnu\ndebug_assertions\nproc_macro\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\nunix\n",""],"1617349019360157463":["___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/matklad/.rustup/toolchains/stable-x86_64-unknown-linux-gnu\ndebug_assertions\nproc_macro\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\nunix\n",""],"1164083562126845933":["rustc 1.28.0 (9634041f0 2018-07-30)\nbinary: rustc\ncommit-hash: 9634041f0e8c0f3191d2867311276f19d0a42564\ncommit-date: 2018-07-30\nhost: x86_64-unknown-linux-gnu\nrelease: 1.28.0\nLLVM version: 6.0\n",""]}} \ No newline at end of file | ||
diff --git a/codeless/server/target/debug/.cargo-lock b/codeless/server/target/debug/.cargo-lock deleted file mode 100644 index e69de29bb..000000000 --- a/codeless/server/target/debug/.cargo-lock +++ /dev/null | |||
diff --git a/codeless/server/target/debug/libm.d b/codeless/server/target/debug/libm.d deleted file mode 100644 index 04d8bb9ed..000000000 --- a/codeless/server/target/debug/libm.d +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | /home/matklad/projects/libsyntax2/codeless/server/target/debug/libm.rmeta: /home/matklad/projects/libsyntax2/codeless/server/src/caps.rs /home/matklad/projects/libsyntax2/codeless/server/src/dispatch.rs /home/matklad/projects/libsyntax2/codeless/server/src/io.rs /home/matklad/projects/libsyntax2/codeless/server/src/main.rs /home/matklad/projects/libsyntax2/codeless/server/src/req.rs /home/matklad/projects/libsyntax2/libanalysis/src/lib.rs /home/matklad/projects/libsyntax2/libeditor/src/extend_selection.rs /home/matklad/projects/libsyntax2/libeditor/src/lib.rs /home/matklad/projects/libsyntax2/src/algo/mod.rs /home/matklad/projects/libsyntax2/src/algo/walk.rs /home/matklad/projects/libsyntax2/src/ast/generated.rs /home/matklad/projects/libsyntax2/src/ast/mod.rs /home/matklad/projects/libsyntax2/src/grammar/attributes.rs /home/matklad/projects/libsyntax2/src/grammar/expressions/atom.rs /home/matklad/projects/libsyntax2/src/grammar/expressions/mod.rs /home/matklad/projects/libsyntax2/src/grammar/items/consts.rs /home/matklad/projects/libsyntax2/src/grammar/items/mod.rs /home/matklad/projects/libsyntax2/src/grammar/items/structs.rs /home/matklad/projects/libsyntax2/src/grammar/items/traits.rs /home/matklad/projects/libsyntax2/src/grammar/items/use_item.rs /home/matklad/projects/libsyntax2/src/grammar/mod.rs /home/matklad/projects/libsyntax2/src/grammar/params.rs /home/matklad/projects/libsyntax2/src/grammar/paths.rs /home/matklad/projects/libsyntax2/src/grammar/patterns.rs /home/matklad/projects/libsyntax2/src/grammar/type_args.rs /home/matklad/projects/libsyntax2/src/grammar/type_params.rs /home/matklad/projects/libsyntax2/src/grammar/types.rs /home/matklad/projects/libsyntax2/src/lexer/classes.rs /home/matklad/projects/libsyntax2/src/lexer/comments.rs /home/matklad/projects/libsyntax2/src/lexer/mod.rs /home/matklad/projects/libsyntax2/src/lexer/numbers.rs /home/matklad/projects/libsyntax2/src/lexer/ptr.rs /home/matklad/projects/libsyntax2/src/lexer/strings.rs /home/matklad/projects/libsyntax2/src/lib.rs /home/matklad/projects/libsyntax2/src/parser_api.rs /home/matklad/projects/libsyntax2/src/parser_impl/event.rs /home/matklad/projects/libsyntax2/src/parser_impl/input.rs /home/matklad/projects/libsyntax2/src/parser_impl/mod.rs /home/matklad/projects/libsyntax2/src/smol_str.rs /home/matklad/projects/libsyntax2/src/syntax_kinds/generated.rs /home/matklad/projects/libsyntax2/src/syntax_kinds/mod.rs /home/matklad/projects/libsyntax2/src/utils.rs /home/matklad/projects/libsyntax2/src/yellow/builder.rs /home/matklad/projects/libsyntax2/src/yellow/green.rs /home/matklad/projects/libsyntax2/src/yellow/mod.rs /home/matklad/projects/libsyntax2/src/yellow/red.rs /home/matklad/projects/libsyntax2/src/yellow/syntax.rs | ||
diff --git a/codeless/server/target/debug/libm.rmeta b/codeless/server/target/debug/libm.rmeta deleted file mode 100644 index e69de29bb..000000000 --- a/codeless/server/target/debug/libm.rmeta +++ /dev/null | |||
diff --git a/codeless/src/extension.ts b/codeless/src/extension.ts index 712d93e04..c64065e6b 100644 --- a/codeless/src/extension.ts +++ b/codeless/src/extension.ts | |||
@@ -43,10 +43,8 @@ export function deactivate(): Thenable<void> { | |||
43 | function startServer() { | 43 | function startServer() { |
44 | let run: Executable = { | 44 | let run: Executable = { |
45 | command: "cargo", | 45 | command: "cargo", |
46 | args: ["run"], | 46 | args: ["run", "--package", "m"], |
47 | options: { | 47 | options: { cwd: "." } |
48 | cwd: "./server" | ||
49 | } | ||
50 | } | 48 | } |
51 | let serverOptions: ServerOptions = { | 49 | let serverOptions: ServerOptions = { |
52 | run, | 50 | run, |
diff --git a/libeditor/src/lib.rs b/libeditor/src/lib.rs index 817a2d15b..4e9631a8b 100644 --- a/libeditor/src/lib.rs +++ b/libeditor/src/lib.rs | |||
@@ -6,9 +6,8 @@ use libsyntax2::{ | |||
6 | SyntaxNodeRef, AstNode, | 6 | SyntaxNodeRef, AstNode, |
7 | algo::walk, | 7 | algo::walk, |
8 | SyntaxKind::*, | 8 | SyntaxKind::*, |
9 | ast, | ||
10 | }; | 9 | }; |
11 | pub use libsyntax2::{TextRange, TextUnit}; | 10 | pub use libsyntax2::{TextRange, TextUnit, ast}; |
12 | 11 | ||
13 | #[derive(Debug)] | 12 | #[derive(Debug)] |
14 | pub struct HighlightedRange { | 13 | pub struct HighlightedRange { |
diff --git a/libeditor/tests/test.rs b/libeditor/tests/test.rs index ab8254d16..2a84c5080 100644 --- a/libeditor/tests/test.rs +++ b/libeditor/tests/test.rs | |||
@@ -3,7 +3,7 @@ extern crate itertools; | |||
3 | 3 | ||
4 | use std::fmt; | 4 | use std::fmt; |
5 | use itertools::Itertools; | 5 | use itertools::Itertools; |
6 | use libeditor::{File, TextRange}; | 6 | use libeditor::{ast, highlight, runnables, extend_selection, TextRange}; |
7 | 7 | ||
8 | #[test] | 8 | #[test] |
9 | fn test_extend_selection() { | 9 | fn test_extend_selection() { |
@@ -12,9 +12,9 @@ fn test_extend_selection() { | |||
12 | } | 12 | } |
13 | "#); | 13 | "#); |
14 | let range = TextRange::offset_len(18.into(), 0.into()); | 14 | let range = TextRange::offset_len(18.into(), 0.into()); |
15 | let range = file.extend_selection(range).unwrap(); | 15 | let range = extend_selection(&file, range).unwrap(); |
16 | assert_eq!(range, TextRange::from_to(17.into(), 18.into())); | 16 | assert_eq!(range, TextRange::from_to(17.into(), 18.into())); |
17 | let range = file.extend_selection(range).unwrap(); | 17 | let range = extend_selection(&file, range).unwrap(); |
18 | assert_eq!(range, TextRange::from_to(15.into(), 20.into())); | 18 | assert_eq!(range, TextRange::from_to(15.into(), 20.into())); |
19 | } | 19 | } |
20 | 20 | ||
@@ -25,7 +25,7 @@ fn test_highlighting() { | |||
25 | fn main() {} | 25 | fn main() {} |
26 | println!("Hello, {}!", 92); | 26 | println!("Hello, {}!", 92); |
27 | "#); | 27 | "#); |
28 | let hls = file.highlight(); | 28 | let hls = highlight(&file); |
29 | dbg_eq( | 29 | dbg_eq( |
30 | &hls, | 30 | &hls, |
31 | r#"[HighlightedRange { range: [1; 11), tag: "comment" }, | 31 | r#"[HighlightedRange { range: [1; 11), tag: "comment" }, |
@@ -49,7 +49,7 @@ fn test_foo() {} | |||
49 | #[ignore] | 49 | #[ignore] |
50 | fn test_foo() {} | 50 | fn test_foo() {} |
51 | "#); | 51 | "#); |
52 | let runnables = file.runnables(); | 52 | let runnables = runnables(&file); |
53 | dbg_eq( | 53 | dbg_eq( |
54 | &runnables, | 54 | &runnables, |
55 | r#"[Runnable { range: [1; 13), kind: Bin }, | 55 | r#"[Runnable { range: [1; 13), kind: Bin }, |
@@ -58,8 +58,8 @@ fn test_foo() {} | |||
58 | ) | 58 | ) |
59 | } | 59 | } |
60 | 60 | ||
61 | fn file(text: &str) -> File { | 61 | fn file(text: &str) -> ast::File { |
62 | File::new(text) | 62 | ast::File::parse(text) |
63 | } | 63 | } |
64 | 64 | ||
65 | fn dbg_eq(actual: &impl fmt::Debug, expected: &str) { | 65 | fn dbg_eq(actual: &impl fmt::Debug, expected: &str) { |
diff --git a/src/yellow/green.rs b/src/yellow/green.rs index 787968363..f505b26d7 100644 --- a/src/yellow/green.rs +++ b/src/yellow/green.rs | |||
@@ -56,12 +56,6 @@ impl GreenNode { | |||
56 | } | 56 | } |
57 | } | 57 | } |
58 | 58 | ||
59 | #[test] | ||
60 | fn assert_send_sync() { | ||
61 | fn f<T: Send + Sync>() {} | ||
62 | f::<GreenNode>(); | ||
63 | } | ||
64 | |||
65 | #[derive(Clone, Debug)] | 59 | #[derive(Clone, Debug)] |
66 | pub(crate) struct GreenBranch { | 60 | pub(crate) struct GreenBranch { |
67 | text_len: TextUnit, | 61 | text_len: TextUnit, |
diff --git a/src/yellow/mod.rs b/src/yellow/mod.rs index 6129ecb99..ff3bb221b 100644 --- a/src/yellow/mod.rs +++ b/src/yellow/mod.rs | |||
@@ -3,9 +3,60 @@ mod green; | |||
3 | mod red; | 3 | mod red; |
4 | mod syntax; | 4 | mod syntax; |
5 | 5 | ||
6 | pub use self::syntax::{SyntaxNode, SyntaxNodeRef, SyntaxRoot, TreeRoot, SyntaxError}; | 6 | use std::{ |
7 | ops::Deref, | ||
8 | sync::Arc, | ||
9 | ptr, | ||
10 | }; | ||
11 | pub use self::syntax::{SyntaxNode, SyntaxNodeRef, SyntaxError}; | ||
7 | pub(crate) use self::{ | 12 | pub(crate) use self::{ |
8 | builder::GreenBuilder, | 13 | builder::GreenBuilder, |
9 | green::GreenNode, | 14 | green::GreenNode, |
10 | red::RedNode, | 15 | red::RedNode, |
11 | }; | 16 | }; |
17 | |||
18 | pub trait TreeRoot: Deref<Target=SyntaxRoot> + Clone + Send + Sync {} | ||
19 | |||
20 | #[derive(Debug)] | ||
21 | pub struct SyntaxRoot { | ||
22 | red: RedNode, | ||
23 | pub(crate) errors: Vec<SyntaxError>, | ||
24 | } | ||
25 | |||
26 | impl TreeRoot for Arc<SyntaxRoot> {} | ||
27 | |||
28 | impl<'a> TreeRoot for &'a SyntaxRoot {} | ||
29 | |||
30 | impl SyntaxRoot { | ||
31 | pub(crate) fn new(green: GreenNode, errors: Vec<SyntaxError>) -> SyntaxRoot { | ||
32 | SyntaxRoot { | ||
33 | red: RedNode::new_root(green), | ||
34 | errors, | ||
35 | } | ||
36 | } | ||
37 | } | ||
38 | |||
39 | #[derive(Clone, Copy, PartialEq, Eq, Debug)] | ||
40 | pub(crate) struct RedPtr(ptr::NonNull<RedNode>); | ||
41 | |||
42 | unsafe impl Send for RedPtr {} | ||
43 | |||
44 | unsafe impl Sync for RedPtr {} | ||
45 | |||
46 | impl RedPtr { | ||
47 | fn new(red: &RedNode) -> RedPtr { | ||
48 | RedPtr(red.into()) | ||
49 | } | ||
50 | |||
51 | unsafe fn get<'a>(self, _root: &'a impl TreeRoot) -> &'a RedNode { | ||
52 | &*self.0.as_ptr() | ||
53 | } | ||
54 | } | ||
55 | |||
56 | #[test] | ||
57 | fn assert_send_sync() { | ||
58 | fn f<T: Send + Sync>() {} | ||
59 | f::<GreenNode>(); | ||
60 | f::<RedNode>(); | ||
61 | f::<SyntaxNode>(); | ||
62 | } | ||
diff --git a/src/yellow/red.rs b/src/yellow/red.rs index f57c4a9b7..13ad44c65 100644 --- a/src/yellow/red.rs +++ b/src/yellow/red.rs | |||
@@ -1,7 +1,5 @@ | |||
1 | use std::ptr; | ||
2 | |||
3 | use parking_lot::RwLock; | 1 | use parking_lot::RwLock; |
4 | use {yellow::GreenNode, TextUnit}; | 2 | use {yellow::{GreenNode, RedPtr}, TextUnit}; |
5 | 3 | ||
6 | #[derive(Debug)] | 4 | #[derive(Debug)] |
7 | pub(crate) struct RedNode { | 5 | pub(crate) struct RedNode { |
@@ -12,7 +10,7 @@ pub(crate) struct RedNode { | |||
12 | 10 | ||
13 | #[derive(Debug)] | 11 | #[derive(Debug)] |
14 | struct ParentData { | 12 | struct ParentData { |
15 | parent: ptr::NonNull<RedNode>, | 13 | parent: RedPtr, |
16 | start_offset: TextUnit, | 14 | start_offset: TextUnit, |
17 | index_in_parent: usize, | 15 | index_in_parent: usize, |
18 | } | 16 | } |
@@ -24,7 +22,7 @@ impl RedNode { | |||
24 | 22 | ||
25 | fn new_child( | 23 | fn new_child( |
26 | green: GreenNode, | 24 | green: GreenNode, |
27 | parent: ptr::NonNull<RedNode>, | 25 | parent: RedPtr, |
28 | start_offset: TextUnit, | 26 | start_offset: TextUnit, |
29 | index_in_parent: usize, | 27 | index_in_parent: usize, |
30 | ) -> RedNode { | 28 | ) -> RedNode { |
@@ -64,12 +62,12 @@ impl RedNode { | |||
64 | self.green.children().len() | 62 | self.green.children().len() |
65 | } | 63 | } |
66 | 64 | ||
67 | pub(crate) fn get_child(&self, idx: usize) -> Option<ptr::NonNull<RedNode>> { | 65 | pub(crate) fn get_child(&self, idx: usize) -> Option<RedPtr> { |
68 | if idx >= self.n_children() { | 66 | if idx >= self.n_children() { |
69 | return None; | 67 | return None; |
70 | } | 68 | } |
71 | match &self.children.read()[idx] { | 69 | match &self.children.read()[idx] { |
72 | Some(child) => return Some(child.into()), | 70 | Some(child) => return Some(RedPtr::new(child)), |
73 | None => (), | 71 | None => (), |
74 | }; | 72 | }; |
75 | let green_children = self.green.children(); | 73 | let green_children = self.green.children(); |
@@ -79,15 +77,15 @@ impl RedNode { | |||
79 | .map(|x| x.text_len()) | 77 | .map(|x| x.text_len()) |
80 | .sum::<TextUnit>(); | 78 | .sum::<TextUnit>(); |
81 | let child = | 79 | let child = |
82 | RedNode::new_child(green_children[idx].clone(), self.into(), start_offset, idx); | 80 | RedNode::new_child(green_children[idx].clone(), RedPtr::new(self), start_offset, idx); |
83 | let mut children = self.children.write(); | 81 | let mut children = self.children.write(); |
84 | if children[idx].is_none() { | 82 | if children[idx].is_none() { |
85 | children[idx] = Some(child) | 83 | children[idx] = Some(child) |
86 | } | 84 | } |
87 | Some(children[idx].as_ref().unwrap().into()) | 85 | Some(RedPtr::new(children[idx].as_ref().unwrap())) |
88 | } | 86 | } |
89 | 87 | ||
90 | pub(crate) fn parent(&self) -> Option<ptr::NonNull<RedNode>> { | 88 | pub(crate) fn parent(&self) -> Option<RedPtr> { |
91 | Some(self.parent.as_ref()?.parent) | 89 | Some(self.parent.as_ref()?.parent) |
92 | } | 90 | } |
93 | pub(crate) fn index_in_parent(&self) -> Option<usize> { | 91 | pub(crate) fn index_in_parent(&self) -> Option<usize> { |
diff --git a/src/yellow/syntax.rs b/src/yellow/syntax.rs index 2ba9281fc..6e33310f1 100644 --- a/src/yellow/syntax.rs +++ b/src/yellow/syntax.rs | |||
@@ -1,25 +1,23 @@ | |||
1 | use std::{fmt, ops::Deref, ptr, sync::Arc}; | 1 | use std::{fmt, sync::Arc}; |
2 | 2 | ||
3 | use { | 3 | use { |
4 | yellow::{GreenNode, RedNode}, | 4 | yellow::{RedNode, TreeRoot, SyntaxRoot, RedPtr}, |
5 | SyntaxKind::{self, *}, | 5 | SyntaxKind::{self, *}, |
6 | TextRange, TextUnit, | 6 | TextRange, TextUnit, |
7 | }; | 7 | }; |
8 | 8 | ||
9 | pub trait TreeRoot: Deref<Target = SyntaxRoot> + Clone {} | ||
10 | |||
11 | impl TreeRoot for Arc<SyntaxRoot> {} | ||
12 | |||
13 | impl<'a> TreeRoot for &'a SyntaxRoot {} | ||
14 | 9 | ||
15 | #[derive(Clone, Copy)] | 10 | #[derive(Clone, Copy)] |
16 | pub struct SyntaxNode<R: TreeRoot = Arc<SyntaxRoot>> { | 11 | pub struct SyntaxNode<R: TreeRoot = Arc<SyntaxRoot>> { |
17 | pub(crate) root: R, | 12 | pub(crate) root: R, |
18 | // Guaranteed to not dangle, because `root` holds a | 13 | // Guaranteed to not dangle, because `root` holds a |
19 | // strong reference to red's ancestor | 14 | // strong reference to red's ancestor |
20 | red: ptr::NonNull<RedNode>, | 15 | red: RedPtr, |
21 | } | 16 | } |
22 | 17 | ||
18 | unsafe impl<R: TreeRoot> Send for SyntaxNode<R> {} | ||
19 | unsafe impl<R: TreeRoot> Sync for SyntaxNode<R> {} | ||
20 | |||
23 | impl<R1: TreeRoot, R2: TreeRoot> PartialEq<SyntaxNode<R1>> for SyntaxNode<R2> { | 21 | impl<R1: TreeRoot, R2: TreeRoot> PartialEq<SyntaxNode<R1>> for SyntaxNode<R2> { |
24 | fn eq(&self, other: &SyntaxNode<R1>) -> bool { | 22 | fn eq(&self, other: &SyntaxNode<R1>) -> bool { |
25 | self.red == other.red | 23 | self.red == other.red |
@@ -30,21 +28,6 @@ impl<R: TreeRoot> Eq for SyntaxNode<R> {} | |||
30 | 28 | ||
31 | pub type SyntaxNodeRef<'a> = SyntaxNode<&'a SyntaxRoot>; | 29 | pub type SyntaxNodeRef<'a> = SyntaxNode<&'a SyntaxRoot>; |
32 | 30 | ||
33 | #[derive(Debug)] | ||
34 | pub struct SyntaxRoot { | ||
35 | red: RedNode, | ||
36 | pub(crate) errors: Vec<SyntaxError>, | ||
37 | } | ||
38 | |||
39 | impl SyntaxRoot { | ||
40 | pub(crate) fn new(green: GreenNode, errors: Vec<SyntaxError>) -> SyntaxRoot { | ||
41 | SyntaxRoot { | ||
42 | red: RedNode::new_root(green), | ||
43 | errors, | ||
44 | } | ||
45 | } | ||
46 | } | ||
47 | |||
48 | #[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] | 31 | #[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] |
49 | pub struct SyntaxError { | 32 | pub struct SyntaxError { |
50 | pub msg: String, | 33 | pub msg: String, |
@@ -54,11 +37,8 @@ pub struct SyntaxError { | |||
54 | impl SyntaxNode<Arc<SyntaxRoot>> { | 37 | impl SyntaxNode<Arc<SyntaxRoot>> { |
55 | pub(crate) fn new_owned(root: SyntaxRoot) -> Self { | 38 | pub(crate) fn new_owned(root: SyntaxRoot) -> Self { |
56 | let root = Arc::new(root); | 39 | let root = Arc::new(root); |
57 | let red_weak = ptr::NonNull::from(&root.red); | 40 | let red = RedPtr::new(&root.red); |
58 | SyntaxNode { | 41 | SyntaxNode { root, red } |
59 | root, | ||
60 | red: red_weak, | ||
61 | } | ||
62 | } | 42 | } |
63 | } | 43 | } |
64 | 44 | ||
@@ -66,7 +46,7 @@ impl<R: TreeRoot> SyntaxNode<R> { | |||
66 | pub fn as_ref<'a>(&'a self) -> SyntaxNode<&'a SyntaxRoot> { | 46 | pub fn as_ref<'a>(&'a self) -> SyntaxNode<&'a SyntaxRoot> { |
67 | SyntaxNode { | 47 | SyntaxNode { |
68 | root: &*self.root, | 48 | root: &*self.root, |
69 | red: ptr::NonNull::clone(&self.red), | 49 | red: self.red, |
70 | } | 50 | } |
71 | } | 51 | } |
72 | 52 | ||
@@ -120,7 +100,7 @@ impl<R: TreeRoot> SyntaxNode<R> { | |||
120 | } | 100 | } |
121 | 101 | ||
122 | fn red(&self) -> &RedNode { | 102 | fn red(&self) -> &RedNode { |
123 | unsafe { self.red.as_ref() } | 103 | unsafe { self.red.get(&self.root) } |
124 | } | 104 | } |
125 | } | 105 | } |
126 | 106 | ||