aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--code/.vscode/launch.json3
-rw-r--r--code/.vscode/tasks.json2
-rw-r--r--code/package.json26
-rw-r--r--code/src/extension.ts42
-rw-r--r--code/tsconfig.json3
-rw-r--r--crates/libeditor/src/typing.rs11
-rw-r--r--crates/libsyntax2/src/algo/mod.rs13
-rw-r--r--crates/libsyntax2/src/lib.rs1
-rw-r--r--crates/libsyntax2/src/text_utils.rs19
-rw-r--r--crates/server/src/main_loop/handlers.rs61
10 files changed, 149 insertions, 32 deletions
diff --git a/code/.vscode/launch.json b/code/.vscode/launch.json
index 5e615ad4c..a5dd523df 100644
--- a/code/.vscode/launch.json
+++ b/code/.vscode/launch.json
@@ -10,6 +10,9 @@
10 "request": "launch", 10 "request": "launch",
11 "runtimeExecutable": "${execPath}", 11 "runtimeExecutable": "${execPath}",
12 "args": ["--extensionDevelopmentPath='./'"], 12 "args": ["--extensionDevelopmentPath='./'"],
13 "env": {
14 "RUST_LOG": "m=trace"
15 },
13 "stopOnEntry": false, 16 "stopOnEntry": false,
14 "sourceMaps": true, 17 "sourceMaps": true,
15 "outFiles": [ "./out/src/**/*.js" ], 18 "outFiles": [ "./out/src/**/*.js" ],
diff --git a/code/.vscode/tasks.json b/code/.vscode/tasks.json
index 8e5a8b9ef..e1cfa4deb 100644
--- a/code/.vscode/tasks.json
+++ b/code/.vscode/tasks.json
@@ -21,7 +21,7 @@
21 "showOutput": "silent", 21 "showOutput": "silent",
22 22
23 // we run the custom script "compile" as defined in package.json 23 // we run the custom script "compile" as defined in package.json
24 "args": ["run", "compile", "--loglevel", "silent"], 24 "args": ["run", "compile",],
25 25
26 // The tsc compiler is started in watching mode 26 // The tsc compiler is started in watching mode
27 "isBackground": true, 27 "isBackground": true,
diff --git a/code/package.json b/code/package.json
index 20a6ceee7..1ed9dfabe 100644
--- a/code/package.json
+++ b/code/package.json
@@ -28,6 +28,28 @@
28 "onLanguage:rust" 28 "onLanguage:rust"
29 ], 29 ],
30 "contributes": { 30 "contributes": {
31 "taskDefinitions": [
32 {
33 "type": "cargo",
34 "required": [
35 "command"
36 ],
37 "properties": {
38 "label": {
39 "type": "string"
40 },
41 "command": {
42 "type": "string"
43 },
44 "args": {
45 "type": "array"
46 },
47 "env": {
48 "type": "object"
49 }
50 }
51 }
52 ],
31 "commands": [ 53 "commands": [
32 { 54 {
33 "command": "libsyntax-rust.syntaxTree", 55 "command": "libsyntax-rust.syntaxTree",
@@ -48,6 +70,10 @@
48 { 70 {
49 "command": "libsyntax-rust.joinLines", 71 "command": "libsyntax-rust.joinLines",
50 "title": "Rust Join Lines" 72 "title": "Rust Join Lines"
73 },
74 {
75 "command": "libsyntax-rust.run",
76 "title": "Rust Run"
51 } 77 }
52 ], 78 ],
53 "keybindings": [ 79 "keybindings": [
diff --git a/code/src/extension.ts b/code/src/extension.ts
index df2109f50..c25e8cb61 100644
--- a/code/src/extension.ts
+++ b/code/src/extension.ts
@@ -81,6 +81,11 @@ export function activate(context: vscode.ExtensionContext) {
81 let e = await vscode.window.showTextDocument(doc) 81 let e = await vscode.window.showTextDocument(doc)
82 e.revealRange(range, vscode.TextEditorRevealType.InCenter) 82 e.revealRange(range, vscode.TextEditorRevealType.InCenter)
83 }) 83 })
84 console.log("ping")
85 registerCommand('libsyntax-rust.run', async (cmd: ProcessSpec) => {
86 let task = createTask(cmd)
87 await vscode.tasks.executeTask(task)
88 })
84 89
85 dispose(vscode.workspace.registerTextDocumentContentProvider( 90 dispose(vscode.workspace.registerTextDocumentContentProvider(
86 'libsyntax-rust', 91 'libsyntax-rust',
@@ -265,3 +270,40 @@ interface Decoration {
265 range: lc.Range, 270 range: lc.Range,
266 tag: string, 271 tag: string,
267} 272}
273
274interface ProcessSpec {
275 bin: string;
276 args: string[];
277 env: { [key: string]: string };
278}
279
280interface CargoTaskDefinition extends vscode.TaskDefinition {
281 type: 'cargo';
282 label: string;
283 command: string;
284 args: Array<string>;
285 env?: { [key: string]: string };
286}
287
288
289function createTask(spec: ProcessSpec): vscode.Task {
290 const TASK_SOURCE = 'Rust';
291 let definition: CargoTaskDefinition = {
292 type: 'cargo',
293 label: 'cargo',
294 command: spec.bin,
295 args: spec.args,
296 env: spec.env
297 }
298
299 let execCmd = `${definition.command} ${definition.args.join(' ')}`;
300 let execOption: vscode.ShellExecutionOptions = {
301 cwd: '.',
302 env: definition.env,
303 };
304 let exec = new vscode.ShellExecution(execCmd, execOption);
305
306 let f = vscode.workspace.workspaceFolders[0]
307 let t = new vscode.Task(definition, f, definition.label, TASK_SOURCE, exec, ['$rustc']);
308 return t;
309}
diff --git a/code/tsconfig.json b/code/tsconfig.json
index 11c3126e0..32a166d0f 100644
--- a/code/tsconfig.json
+++ b/code/tsconfig.json
@@ -7,6 +7,5 @@
7 "sourceMap": true, 7 "sourceMap": true,
8 "rootDir": "." 8 "rootDir": "."
9 }, 9 },
10 "include": [ "src" ], 10 "include": [ "src/*.ts" ],
11 "exclude": [ "node_modules" ]
12} 11}
diff --git a/crates/libeditor/src/typing.rs b/crates/libeditor/src/typing.rs
index 04021d164..cc0d3d272 100644
--- a/crates/libeditor/src/typing.rs
+++ b/crates/libeditor/src/typing.rs
@@ -5,6 +5,7 @@ use libsyntax2::{
5 walk::preorder, 5 walk::preorder,
6 find_covering_node, 6 find_covering_node,
7 }, 7 },
8 text_utils::intersect,
8 SyntaxKind::*, 9 SyntaxKind::*,
9}; 10};
10 11
@@ -53,16 +54,6 @@ pub fn join_lines(file: &ast::ParsedFile, range: TextRange) -> ActionResult {
53 } 54 }
54} 55}
55 56
56fn intersect(r1: TextRange, r2: TextRange) -> Option<TextRange> {
57 let start = r1.start().max(r2.start());
58 let end = r1.end().min(r2.end());
59 if start <= end {
60 Some(TextRange::from_to(start, end))
61 } else {
62 None
63 }
64}
65
66fn remove_newline( 57fn remove_newline(
67 edit: &mut EditBuilder, 58 edit: &mut EditBuilder,
68 node: SyntaxNodeRef, 59 node: SyntaxNodeRef,
diff --git a/crates/libsyntax2/src/algo/mod.rs b/crates/libsyntax2/src/algo/mod.rs
index 6efdff12f..2640d60ea 100644
--- a/crates/libsyntax2/src/algo/mod.rs
+++ b/crates/libsyntax2/src/algo/mod.rs
@@ -1,7 +1,10 @@
1pub mod walk; 1pub mod walk;
2pub mod visit; 2pub mod visit;
3 3
4use {SyntaxNodeRef, TextUnit, TextRange}; 4use {
5 SyntaxNodeRef, TextUnit, TextRange,
6 text_utils::{contains_offset_nonstrict, is_subrange},
7};
5 8
6pub fn find_leaf_at_offset(node: SyntaxNodeRef, offset: TextUnit) -> LeafAtOffset { 9pub fn find_leaf_at_offset(node: SyntaxNodeRef, offset: TextUnit) -> LeafAtOffset {
7 let range = node.range(); 10 let range = node.range();
@@ -116,14 +119,6 @@ fn common_ancestor<'a>(n1: SyntaxNodeRef<'a>, n2: SyntaxNodeRef<'a>) -> SyntaxNo
116 panic!("Can't find common ancestor of {:?} and {:?}", n1, n2) 119 panic!("Can't find common ancestor of {:?} and {:?}", n1, n2)
117} 120}
118 121
119fn contains_offset_nonstrict(range: TextRange, offset: TextUnit) -> bool {
120 range.start() <= offset && offset <= range.end()
121}
122
123fn is_subrange(range: TextRange, subrange: TextRange) -> bool {
124 range.start() <= subrange.start() && subrange.end() <= range.end()
125}
126
127fn generate<T>(seed: Option<T>, step: impl Fn(&T) -> Option<T>) -> impl Iterator<Item=T> { 122fn generate<T>(seed: Option<T>, step: impl Fn(&T) -> Option<T>) -> impl Iterator<Item=T> {
128 ::itertools::unfold(seed, move |slot| { 123 ::itertools::unfold(seed, move |slot| {
129 slot.take().map(|curr| { 124 slot.take().map(|curr| {
diff --git a/crates/libsyntax2/src/lib.rs b/crates/libsyntax2/src/lib.rs
index c078baa3a..53ae18988 100644
--- a/crates/libsyntax2/src/lib.rs
+++ b/crates/libsyntax2/src/lib.rs
@@ -39,6 +39,7 @@ mod syntax_kinds;
39mod yellow; 39mod yellow;
40/// Utilities for simple uses of the parser. 40/// Utilities for simple uses of the parser.
41pub mod utils; 41pub mod utils;
42pub mod text_utils;
42 43
43pub use { 44pub use {
44 text_unit::{TextRange, TextUnit}, 45 text_unit::{TextRange, TextUnit},
diff --git a/crates/libsyntax2/src/text_utils.rs b/crates/libsyntax2/src/text_utils.rs
new file mode 100644
index 000000000..e3d73888f
--- /dev/null
+++ b/crates/libsyntax2/src/text_utils.rs
@@ -0,0 +1,19 @@
1use {TextRange, TextUnit};
2
3pub fn contains_offset_nonstrict(range: TextRange, offset: TextUnit) -> bool {
4 range.start() <= offset && offset <= range.end()
5}
6
7pub fn is_subrange(range: TextRange, subrange: TextRange) -> bool {
8 range.start() <= subrange.start() && subrange.end() <= range.end()
9}
10
11pub fn intersect(r1: TextRange, r2: TextRange) -> Option<TextRange> {
12 let start = r1.start().max(r2.start());
13 let end = r1.end().min(r2.end());
14 if start <= end {
15 Some(TextRange::from_to(start, end))
16 } else {
17 None
18 }
19}
diff --git a/crates/server/src/main_loop/handlers.rs b/crates/server/src/main_loop/handlers.rs
index ae362ddaa..b68e93e46 100644
--- a/crates/server/src/main_loop/handlers.rs
+++ b/crates/server/src/main_loop/handlers.rs
@@ -5,10 +5,13 @@ use languageserver_types::{
5 Command, TextDocumentIdentifier, WorkspaceEdit, 5 Command, TextDocumentIdentifier, WorkspaceEdit,
6 SymbolInformation, Position, Location, TextEdit, 6 SymbolInformation, Position, Location, TextEdit,
7}; 7};
8use serde_json::{to_value, from_value};
8use libanalysis::{Query}; 9use libanalysis::{Query};
9use libeditor; 10use libeditor;
10use libsyntax2::TextUnit; 11use libsyntax2::{
11use serde_json::{to_value, from_value}; 12 TextUnit,
13 text_utils::contains_offset_nonstrict,
14};
12 15
13use ::{ 16use ::{
14 req::{self, Decoration}, Result, 17 req::{self, Decoration}, Result,
@@ -117,7 +120,7 @@ pub fn handle_code_action(
117 let file = world.analysis().file_syntax(file_id)?; 120 let file = world.analysis().file_syntax(file_id)?;
118 let line_index = world.analysis().file_line_index(file_id)?; 121 let line_index = world.analysis().file_line_index(file_id)?;
119 let offset = params.range.conv_with(&line_index).start(); 122 let offset = params.range.conv_with(&line_index).start();
120 let mut ret = Vec::new(); 123 let mut res = Vec::new();
121 124
122 let actions = &[ 125 let actions = &[
123 (ActionId::FlipComma, libeditor::flip_comma(&file, offset).is_some()), 126 (ActionId::FlipComma, libeditor::flip_comma(&file, offset).is_some()),
@@ -128,10 +131,52 @@ pub fn handle_code_action(
128 for (id, edit) in actions { 131 for (id, edit) in actions {
129 if *edit { 132 if *edit {
130 let cmd = apply_code_action_cmd(*id, params.text_document.clone(), offset); 133 let cmd = apply_code_action_cmd(*id, params.text_document.clone(), offset);
131 ret.push(cmd); 134 res.push(cmd);
135 }
136 }
137 for runnable in libeditor::runnables(&file) {
138 if !contains_offset_nonstrict(runnable.range, offset) {
139 continue;
140 }
141
142 #[derive(Serialize)]
143 struct ProcessSpec {
144 bin: String,
145 args: Vec<String>,
146 env: HashMap<String, String>,
132 } 147 }
148
149 let spec = ProcessSpec {
150 bin: "cargo".to_string(),
151 args: match runnable.kind {
152 libeditor::RunnableKind::Test { name } => {
153 vec![
154 "test".to_string(),
155 "--".to_string(),
156 name,
157 "--nocapture".to_string(),
158 ]
159 }
160 libeditor::RunnableKind::Bin => vec!["run".to_string()]
161 },
162 env: {
163 let mut m = HashMap::new();
164 m.insert(
165 "RUST_BACKTRACE".to_string(),
166 "short".to_string(),
167 );
168 m
169 }
170 };
171
172 let cmd = Command {
173 title: "Run ...".to_string(),
174 command: "libsyntax-rust.run".to_string(),
175 arguments: Some(vec![to_value(spec).unwrap()]),
176 };
177 res.push(cmd);
133 } 178 }
134 return Ok(Some(ret)); 179 return Ok(Some(res));
135} 180}
136 181
137pub fn handle_workspace_symbol( 182pub fn handle_workspace_symbol(
@@ -257,11 +302,7 @@ struct ActionRequest {
257} 302}
258 303
259fn apply_code_action_cmd(id: ActionId, doc: TextDocumentIdentifier, offset: TextUnit) -> Command { 304fn apply_code_action_cmd(id: ActionId, doc: TextDocumentIdentifier, offset: TextUnit) -> Command {
260 let action_request = ActionRequest { 305 let action_request = ActionRequest { id, text_document: doc, offset };
261 id,
262 text_document: doc,
263 offset,
264 };
265 Command { 306 Command {
266 title: id.title().to_string(), 307 title: id.title().to_string(),
267 command: "apply_code_action".to_string(), 308 command: "apply_code_action".to_string(),