diff options
-rw-r--r-- | crates/ra_editor/src/code_actions.rs | 74 | ||||
-rw-r--r-- | crates/ra_editor/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main.rs | 11 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop.rs | 8 | ||||
-rw-r--r-- | editors/code/package.json | 11 | ||||
-rw-r--r-- | editors/code/src/server.ts | 26 |
6 files changed, 121 insertions, 11 deletions
diff --git a/crates/ra_editor/src/code_actions.rs b/crates/ra_editor/src/code_actions.rs index 688a89c3d..1d78cb7e8 100644 --- a/crates/ra_editor/src/code_actions.rs +++ b/crates/ra_editor/src/code_actions.rs | |||
@@ -4,7 +4,7 @@ use ra_syntax::{ | |||
4 | algo::{find_covering_node, find_leaf_at_offset}, | 4 | algo::{find_covering_node, find_leaf_at_offset}, |
5 | ast::{self, AstNode, AttrsOwner, NameOwner, TypeParamsOwner}, | 5 | ast::{self, AstNode, AttrsOwner, NameOwner, TypeParamsOwner}, |
6 | Direction, SourceFileNode, | 6 | Direction, SourceFileNode, |
7 | SyntaxKind::{COMMA, WHITESPACE, COMMENT}, | 7 | SyntaxKind::{COMMA, WHITESPACE, COMMENT, VISIBILITY, FN_KW, MOD_KW, STRUCT_KW, ENUM_KW, TRAIT_KW, FN_DEF, MODULE, STRUCT_DEF, ENUM_DEF, TRAIT_DEF}, |
8 | SyntaxNodeRef, TextRange, TextUnit, | 8 | SyntaxNodeRef, TextRange, TextUnit, |
9 | }; | 9 | }; |
10 | 10 | ||
@@ -174,6 +174,39 @@ pub fn introduce_variable<'a>( | |||
174 | } | 174 | } |
175 | } | 175 | } |
176 | 176 | ||
177 | pub fn make_pub_crate<'a>( | ||
178 | file: &'a SourceFileNode, | ||
179 | offset: TextUnit, | ||
180 | ) -> Option<impl FnOnce() -> LocalEdit + 'a> { | ||
181 | let syntax = file.syntax(); | ||
182 | |||
183 | let keyword = find_leaf_at_offset(syntax, offset).find(|leaf| match leaf.kind() { | ||
184 | FN_KW | MOD_KW | STRUCT_KW | ENUM_KW | TRAIT_KW => true, | ||
185 | _ => false, | ||
186 | })?; | ||
187 | let parent = keyword.parent()?; | ||
188 | let def_kws = vec![FN_DEF, MODULE, STRUCT_DEF, ENUM_DEF, TRAIT_DEF]; | ||
189 | let node_start = parent.range().start(); | ||
190 | Some(move || { | ||
191 | let mut edit = TextEditBuilder::new(); | ||
192 | |||
193 | if !def_kws.iter().any(|&def_kw| def_kw == parent.kind()) | ||
194 | || parent.children().any(|child| child.kind() == VISIBILITY) | ||
195 | { | ||
196 | return LocalEdit { | ||
197 | edit: edit.finish(), | ||
198 | cursor_position: Some(offset), | ||
199 | }; | ||
200 | } | ||
201 | |||
202 | edit.insert(node_start, "pub(crate) ".to_string()); | ||
203 | LocalEdit { | ||
204 | edit: edit.finish(), | ||
205 | cursor_position: Some(node_start), | ||
206 | } | ||
207 | }) | ||
208 | } | ||
209 | |||
177 | fn non_trivia_sibling(node: SyntaxNodeRef, direction: Direction) -> Option<SyntaxNodeRef> { | 210 | fn non_trivia_sibling(node: SyntaxNodeRef, direction: Direction) -> Option<SyntaxNodeRef> { |
178 | node.siblings(direction) | 211 | node.siblings(direction) |
179 | .skip(1) | 212 | .skip(1) |
@@ -333,4 +366,43 @@ fn foo() { | |||
333 | ); | 366 | ); |
334 | } | 367 | } |
335 | 368 | ||
369 | #[test] | ||
370 | fn test_make_pub_crate() { | ||
371 | check_action( | ||
372 | "<|>fn foo() {}", | ||
373 | "<|>pub(crate) fn foo() {}", | ||
374 | |file, off| make_pub_crate(file, off).map(|f| f()), | ||
375 | ); | ||
376 | check_action( | ||
377 | "f<|>n foo() {}", | ||
378 | "<|>pub(crate) fn foo() {}", | ||
379 | |file, off| make_pub_crate(file, off).map(|f| f()), | ||
380 | ); | ||
381 | check_action( | ||
382 | "<|>struct Foo {}", | ||
383 | "<|>pub(crate) struct Foo {}", | ||
384 | |file, off| make_pub_crate(file, off).map(|f| f()), | ||
385 | ); | ||
386 | check_action("<|>mod foo {}", "<|>pub(crate) mod foo {}", |file, off| { | ||
387 | make_pub_crate(file, off).map(|f| f()) | ||
388 | }); | ||
389 | check_action( | ||
390 | "<|>trait Foo {}", | ||
391 | "<|>pub(crate) trait Foo {}", | ||
392 | |file, off| make_pub_crate(file, off).map(|f| f()), | ||
393 | ); | ||
394 | check_action("m<|>od {}", "<|>pub(crate) mod {}", |file, off| { | ||
395 | make_pub_crate(file, off).map(|f| f()) | ||
396 | }); | ||
397 | check_action( | ||
398 | "pub(crate) f<|>n foo() {}", | ||
399 | "pub(crate) f<|>n foo() {}", | ||
400 | |file, off| make_pub_crate(file, off).map(|f| f()), | ||
401 | ); | ||
402 | check_action( | ||
403 | "unsafe f<|>n foo() {}", | ||
404 | "<|>pub(crate) unsafe fn foo() {}", | ||
405 | |file, off| make_pub_crate(file, off).map(|f| f()), | ||
406 | ); | ||
407 | } | ||
336 | } | 408 | } |
diff --git a/crates/ra_editor/src/lib.rs b/crates/ra_editor/src/lib.rs index 36cabed25..7b63b9a88 100644 --- a/crates/ra_editor/src/lib.rs +++ b/crates/ra_editor/src/lib.rs | |||
@@ -8,7 +8,7 @@ mod test_utils; | |||
8 | mod typing; | 8 | mod typing; |
9 | 9 | ||
10 | pub use self::{ | 10 | pub use self::{ |
11 | code_actions::{add_derive, add_impl, flip_comma, introduce_variable, LocalEdit}, | 11 | code_actions::{add_derive, add_impl, flip_comma, introduce_variable, make_pub_crate, LocalEdit}, |
12 | extend_selection::extend_selection, | 12 | extend_selection::extend_selection, |
13 | folding_ranges::{folding_ranges, Fold, FoldKind}, | 13 | folding_ranges::{folding_ranges, Fold, FoldKind}, |
14 | line_index::{LineCol, LineIndex}, | 14 | line_index::{LineCol, LineIndex}, |
diff --git a/crates/ra_lsp_server/src/main.rs b/crates/ra_lsp_server/src/main.rs index eae601f91..33aa30d70 100644 --- a/crates/ra_lsp_server/src/main.rs +++ b/crates/ra_lsp_server/src/main.rs | |||
@@ -27,7 +27,10 @@ fn main() -> Result<()> { | |||
27 | #[derive(Deserialize)] | 27 | #[derive(Deserialize)] |
28 | #[serde(rename_all = "camelCase")] | 28 | #[serde(rename_all = "camelCase")] |
29 | struct InitializationOptions { | 29 | struct InitializationOptions { |
30 | publish_decorations: bool, | 30 | // Whether the client supports our custom highlighting publishing decorations. |
31 | // This is different to the highlightingOn setting, which is whether the user | ||
32 | // wants our custom highlighting to be used. | ||
33 | publish_decorations: Option<bool>, | ||
31 | } | 34 | } |
32 | 35 | ||
33 | fn main_inner() -> Result<()> { | 36 | fn main_inner() -> Result<()> { |
@@ -42,12 +45,12 @@ fn main_inner() -> Result<()> { | |||
42 | .root_uri | 45 | .root_uri |
43 | .and_then(|it| it.to_file_path().ok()) | 46 | .and_then(|it| it.to_file_path().ok()) |
44 | .unwrap_or(cwd); | 47 | .unwrap_or(cwd); |
45 | let publish_decorations = params | 48 | let supports_decorations = params |
46 | .initialization_options | 49 | .initialization_options |
47 | .and_then(|v| InitializationOptions::deserialize(v).ok()) | 50 | .and_then(|v| InitializationOptions::deserialize(v).ok()) |
48 | .map(|it| it.publish_decorations) | 51 | .and_then(|it| it.publish_decorations) |
49 | == Some(true); | 52 | == Some(true); |
50 | ra_lsp_server::main_loop(false, root, publish_decorations, r, s) | 53 | ra_lsp_server::main_loop(false, root, supports_decorations, r, s) |
51 | }, | 54 | }, |
52 | )?; | 55 | )?; |
53 | log::info!("shutting down IO..."); | 56 | log::info!("shutting down IO..."); |
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 565ec92af..a5a2b5eec 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs | |||
@@ -54,7 +54,7 @@ enum Task { | |||
54 | pub fn main_loop( | 54 | pub fn main_loop( |
55 | internal_mode: bool, | 55 | internal_mode: bool, |
56 | ws_root: PathBuf, | 56 | ws_root: PathBuf, |
57 | publish_decorations: bool, | 57 | supports_decorations: bool, |
58 | msg_receiver: &Receiver<RawMessage>, | 58 | msg_receiver: &Receiver<RawMessage>, |
59 | msg_sender: &Sender<RawMessage>, | 59 | msg_sender: &Sender<RawMessage>, |
60 | ) -> Result<()> { | 60 | ) -> Result<()> { |
@@ -83,7 +83,7 @@ pub fn main_loop( | |||
83 | let mut subs = Subscriptions::new(); | 83 | let mut subs = Subscriptions::new(); |
84 | let main_res = main_loop_inner( | 84 | let main_res = main_loop_inner( |
85 | internal_mode, | 85 | internal_mode, |
86 | publish_decorations, | 86 | supports_decorations, |
87 | &pool, | 87 | &pool, |
88 | msg_sender, | 88 | msg_sender, |
89 | msg_receiver, | 89 | msg_receiver, |
@@ -156,7 +156,7 @@ impl fmt::Debug for Event { | |||
156 | 156 | ||
157 | fn main_loop_inner( | 157 | fn main_loop_inner( |
158 | internal_mode: bool, | 158 | internal_mode: bool, |
159 | publish_decorations: bool, | 159 | supports_decorations: bool, |
160 | pool: &ThreadPool, | 160 | pool: &ThreadPool, |
161 | msg_sender: &Sender<RawMessage>, | 161 | msg_sender: &Sender<RawMessage>, |
162 | msg_receiver: &Receiver<RawMessage>, | 162 | msg_receiver: &Receiver<RawMessage>, |
@@ -240,7 +240,7 @@ fn main_loop_inner( | |||
240 | update_file_notifications_on_threadpool( | 240 | update_file_notifications_on_threadpool( |
241 | pool, | 241 | pool, |
242 | state.snapshot(), | 242 | state.snapshot(), |
243 | publish_decorations, | 243 | supports_decorations, |
244 | task_sender.clone(), | 244 | task_sender.clone(), |
245 | subs.subscriptions(), | 245 | subs.subscriptions(), |
246 | ) | 246 | ) |
diff --git a/editors/code/package.json b/editors/code/package.json index d53e44b21..2989a7016 100644 --- a/editors/code/package.json +++ b/editors/code/package.json | |||
@@ -131,6 +131,17 @@ | |||
131 | "type": "boolean", | 131 | "type": "boolean", |
132 | "default": true, | 132 | "default": true, |
133 | "description": "Highlight Rust code (overrides built-in syntax highlighting)" | 133 | "description": "Highlight Rust code (overrides built-in syntax highlighting)" |
134 | }, | ||
135 | "ra-lsp.trace.server": { | ||
136 | "type": "string", | ||
137 | "scope": "window", | ||
138 | "enum": [ | ||
139 | "off", | ||
140 | "messages", | ||
141 | "verbose" | ||
142 | ], | ||
143 | "default": "off", | ||
144 | "description": "Trace requests to the ra-lsp server" | ||
134 | } | 145 | } |
135 | } | 146 | } |
136 | }, | 147 | }, |
diff --git a/editors/code/src/server.ts b/editors/code/src/server.ts index 75e273f37..75bdf3207 100644 --- a/editors/code/src/server.ts +++ b/editors/code/src/server.ts | |||
@@ -22,7 +22,7 @@ export class Server { | |||
22 | const clientOptions: lc.LanguageClientOptions = { | 22 | const clientOptions: lc.LanguageClientOptions = { |
23 | documentSelector: [{ scheme: 'file', language: 'rust' }], | 23 | documentSelector: [{ scheme: 'file', language: 'rust' }], |
24 | initializationOptions: { | 24 | initializationOptions: { |
25 | publishDecorations: true, | 25 | publishDecorations: true |
26 | } | 26 | } |
27 | }; | 27 | }; |
28 | 28 | ||
@@ -32,6 +32,30 @@ export class Server { | |||
32 | serverOptions, | 32 | serverOptions, |
33 | clientOptions | 33 | clientOptions |
34 | ); | 34 | ); |
35 | // HACK: This is an awful way of filtering out the decorations notifications | ||
36 | // However, pending proper support, this is the most effecitve approach | ||
37 | // Proper support for this would entail a change to vscode-languageclient to allow not notifying on certain messages | ||
38 | // Or the ability to disable the serverside component of highlighting (but this means that to do tracing we need to disable hihlighting) | ||
39 | // This also requires considering our settings strategy, which is work which needs doing | ||
40 | // @ts-ignore The tracer is private to vscode-languageclient, but we need access to it to not log publishDecorations requests | ||
41 | Server.client._tracer = { | ||
42 | log: (messageOrDataObject: string | any, data?: string) => { | ||
43 | if (typeof messageOrDataObject === 'string') { | ||
44 | if ( | ||
45 | messageOrDataObject.includes('m/publishDecorations') || | ||
46 | messageOrDataObject.includes('m/decorationsRequest') | ||
47 | ) { | ||
48 | // Don't log publish decorations requests | ||
49 | } else { | ||
50 | // @ts-ignore This is just a utility function | ||
51 | Server.client.logTrace(messageOrDataObject, data); | ||
52 | } | ||
53 | } else { | ||
54 | // @ts-ignore | ||
55 | Server.client.logObjectTrace(messageOrDataObject); | ||
56 | } | ||
57 | } | ||
58 | }; | ||
35 | Server.client.onReady().then(() => { | 59 | Server.client.onReady().then(() => { |
36 | for (const [type, handler] of notificationHandlers) { | 60 | for (const [type, handler] of notificationHandlers) { |
37 | Server.client.onNotification(type, handler); | 61 | Server.client.onNotification(type, handler); |